OSDN Git Service

android: Add history to line editor in haltest
authorJerzy Kasenberg <jerzy.kasenberg@tieto.com>
Wed, 16 Oct 2013 14:00:10 +0000 (16:00 +0200)
committerJohan Hedberg <johan.hedberg@intel.com>
Wed, 16 Oct 2013 15:32:51 +0000 (18:32 +0300)
Added simple history to editor to save time.

android/Android.mk
android/client/history.c [new file with mode: 0644]
android/client/history.h [new file with mode: 0644]
android/client/terminal.c

index 2eac3ec..d49056c 100644 (file)
@@ -60,6 +60,7 @@ LOCAL_SRC_FILES := \
        client/haltest.c \
        client/pollhandler.c \
        client/terminal.c \
+       client/history.c \
 
 LOCAL_SHARED_LIBRARIES := libhardware
 
diff --git a/android/client/history.c b/android/client/history.c
new file mode 100644 (file)
index 0000000..6481174
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "history.h"
+
+/*
+ * Very simple history storage for easy usage of tool
+ */
+
+#define HISTORY_DEPTH 20
+#define LINE_SIZE 100
+static char lines[HISTORY_DEPTH][LINE_SIZE];
+static int last_line = 0;
+static int history_size = 0;
+
+/* TODO: Storing history not implemented yet */
+void history_store(const char *filename)
+{
+}
+
+/* Restoring history from file */
+void history_restore(const char *filename)
+{
+       char line[1000];
+       FILE *f = fopen(filename, "rt");
+
+       if (f == NULL)
+               return;
+
+       for (;;) {
+               if (fgets(line, 1000, f) != NULL) {
+                       int l = strlen(line);
+                       while (l > 0 && isspace(line[--l]))
+                               line[l] = 0;
+                       if (l > 0)
+                               history_add_line(line);
+               } else
+                       break;
+       }
+       fclose(f);
+}
+
+/* Add new line to history buffer */
+void history_add_line(const char *line)
+{
+       if (line == NULL || strlen(line) == 0)
+               return;
+
+       if (strcmp(line, lines[last_line]) == 0)
+               return;
+
+       last_line = (last_line + 1) % HISTORY_DEPTH;
+       strncpy(&lines[last_line][0], line, LINE_SIZE - 1);
+       if (history_size < HISTORY_DEPTH)
+               history_size++;
+}
+
+/*
+ * Get n-th line from history
+ * 0 - means latest
+ * -1 - means oldest
+ * return -1 if there is no such line
+ */
+int history_get_line(int n, char *buf, int buf_size)
+{
+       if (n == -1)
+               n = history_size - 1;
+
+       if (n >= history_size || buf_size == 0 || n < 0)
+               return -1;
+
+       strncpy(buf,
+               &lines[(HISTORY_DEPTH + last_line - n) % HISTORY_DEPTH][0],
+               buf_size - 1);
+       buf[buf_size - 1] = 0;
+
+       return n;
+}
diff --git a/android/client/history.h b/android/client/history.h
new file mode 100644 (file)
index 0000000..26085b5
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+void history_store(const char *filename);
+void history_restore(const char *filename);
+void history_add_line(const char *line);
+int history_get_line(int n, char *buf, int buf_size);
index 42fe340..b484ef6 100644 (file)
@@ -22,6 +22,7 @@
 #include <termios.h>
 
 #include "terminal.h"
+#include "history.h"
 
 /*
  * Character sequences recognized by code in this file
@@ -107,6 +108,9 @@ static int line_buf_ix = 0;
 /* current length of input line */
 static int line_len = 0;
 
+/* line index used for fetching lines from history */
+static int line_index = 0;
+
 /*
  * Moves cursor to right or left
  *
@@ -189,6 +193,87 @@ int terminal_vprint(const char *format, va_list args)
 }
 
 /*
+ * Call this when text in line_buf was changed
+ * and line needs to be redrawn
+ */
+static void terminal_line_replaced(void)
+{
+       int len = strlen(line_buf);
+
+       /* line is shorter that previous */
+       if (len < line_len) {
+               /* if new line is shorter move cursor to end of new end */
+               while (line_buf_ix > len) {
+                       putchar('\b');
+                       line_buf_ix--;
+               }
+               /* If cursor was not at the end, move it to the end */
+               if (line_buf_ix < line_len)
+                       printf("%.*s", line_len - line_buf_ix,
+                                       line_buf + line_buf_ix);
+               /* over write end of previous line */
+               while (line_len >= len++)
+                       putchar(' ');
+       }
+       /* draw new line */
+       printf("\r>%s", line_buf);
+       /* set up indexes to new line */
+       line_len = strlen(line_buf);
+       line_buf_ix = line_len;
+}
+
+/*
+ * Function tries to replace current line with specified line in history
+ * new_line_index - new line to show, -1 to show oldest
+ */
+static void terminal_get_line_from_history(int new_line_index)
+{
+       new_line_index = history_get_line(new_line_index,
+                                               line_buf, LINE_BUF_MAX);
+
+       if (new_line_index >= 0) {
+               terminal_line_replaced();
+               line_index = new_line_index;
+       }
+}
+
+/*
+ * Function searches history back or forward for command line that starts
+ * with characters up to cursor position
+ *
+ * back - true - searches backward
+ * back - false - searches forward (more recent commands)
+ */
+static void terminal_match_hitory(bool back)
+{
+       char buf[line_buf_ix + 1];
+       int line;
+       int matching_line = -1;
+       int dir = back ? 1 : -1;
+
+       line = line_index + dir;
+       while (matching_line == -1 && line >= 0) {
+               int new_line_index;
+
+               new_line_index = history_get_line(line, buf, line_buf_ix + 1);
+               if (new_line_index < 0)
+                       break;
+
+               if (0 == strncmp(line_buf, buf, line_buf_ix))
+                       matching_line = line;
+               line += dir;
+       }
+
+       if (matching_line >= 0) {
+               int pos = line_buf_ix;
+               terminal_get_line_from_history(matching_line);
+               /* move back to cursor position to origianl place */
+               line_buf_ix = pos;
+               terminal_move_cursor(pos - line_len);
+       }
+}
+
+/*
  * Converts terminal character sequences to single value representing
  * keyboard keys
  */
@@ -335,13 +420,30 @@ void terminal_process_char(int c, void (*process_line)(char *line))
                        printf("%.*s", (int) (line_buf_ix - old_pos),
                                                        line_buf + old_pos);
                break;
+       case KEY_SUP:
+               terminal_get_line_from_history(-1);
+               break;
+       case KEY_SDOWN:
+               if (line_index > 0)
+                       terminal_get_line_from_history(0);
+               break;
        case KEY_UP:
+               terminal_get_line_from_history(line_index + 1);
+               break;
        case KEY_DOWN:
+               if (line_index > 0)
+                       terminal_get_line_from_history(line_index - 1);
                break;
        case '\n':
        case '\r':
+               /*
+                * On new line add line to history
+                * forget history position
+                */
+               history_add_line(line_buf);
                line_len = 0;
                line_buf_ix = 0;
+               line_index = -1;
                /* print new line */
                putchar(c);
                process_line(line_buf);
@@ -383,7 +485,12 @@ void terminal_process_char(int c, void (*process_line)(char *line))
        case KEY_MDOWN:
        case KEY_STAB:
        case KEY_M_n:
+               /* Search history forward */
+               terminal_match_hitory(false);
+               break;
        case KEY_M_p:
+               /* Search history backward */
+               terminal_match_hitory(true);
                break;
        default:
                if (!isprint(c)) {