]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
edit: Add history buffer search
authorJouni Malinen <j@w1.fi>
Sat, 20 Nov 2010 15:55:35 +0000 (17:55 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 20 Nov 2010 15:55:35 +0000 (17:55 +0200)
Ctrl-R can now be used to start history search mode.

src/utils/edit.c

index 22b91746e755a4ed1b13271fa21a24bd084f725a..d4de2b1683caf280064ab9af3dfdebad2539897f 100644 (file)
@@ -37,6 +37,9 @@ static char ** (*edit_completion_cb)(void *ctx, const char *cmd, int pos) =
 static struct termios prevt, newt;
 
 
+#define CLEAR_END_LINE "\e[K"
+
+
 void edit_clear_line(void)
 {
        int i;
@@ -785,13 +788,169 @@ static enum edit_key_code edit_read_key(int sock)
 }
 
 
+static char search_buf[21];
+static int search_skip;
+
+static char * search_find(void)
+{
+       int pos = history_pos;
+       size_t len = os_strlen(search_buf);
+       int skip = search_skip;
+
+       if (len == 0)
+               return NULL;
+
+       for (;;) {
+               if (pos == 0)
+                       pos = CMD_HISTORY_LEN - 1;
+               else
+                       pos--;
+               if (pos == history_pos) {
+                       search_skip = 0;
+                       return NULL;
+               }
+
+               if (os_strstr(history_buf[pos], search_buf)) {
+                       if (skip == 0)
+                               return history_buf[pos];
+                       skip--;
+               }
+       }
+}
+
+
+static void search_redraw(void)
+{
+       char *match = search_find();
+       printf("\rsearch '%s': %s" CLEAR_END_LINE,
+              search_buf, match ? match : "");
+       printf("\rsearch '%s", search_buf);
+       fflush(stdout);
+}
+
+
+static void search_start(void)
+{
+       edit_clear_line();
+       search_buf[0] = '\0';
+       search_skip = 0;
+       search_redraw();
+}
+
+
+static void search_clear(void)
+{
+       search_redraw();
+       printf("\r" CLEAR_END_LINE);
+}
+
+
+static void search_stop(void)
+{
+       char *match = search_find();
+       search_buf[0] = '\0';
+       search_clear();
+       if (match) {
+               os_strlcpy(cmdbuf, match, CMD_BUF_LEN);
+               cmdbuf_len = os_strlen(cmdbuf);
+               cmdbuf_pos = cmdbuf_len;
+       }
+       edit_redraw();
+}
+
+
+static void search_cancel(void)
+{
+       search_buf[0] = '\0';
+       search_clear();
+       edit_redraw();
+}
+
+
+static void search_backspace(void)
+{
+       size_t len;
+       len = os_strlen(search_buf);
+       if (len == 0)
+               return;
+       search_buf[len - 1] = '\0';
+       search_skip = 0;
+       search_redraw();
+}
+
+
+static void search_next(void)
+{
+       search_skip++;
+       search_find();
+       search_redraw();
+}
+
+
+static void search_char(char c)
+{
+       size_t len;
+       len = os_strlen(search_buf);
+       if (len == sizeof(search_buf) - 1)
+               return;
+       search_buf[len] = c;
+       search_buf[len + 1] = '\0';
+       search_skip = 0;
+       search_redraw();
+}
+
+
+static enum edit_key_code search_key(enum edit_key_code c)
+{
+       switch (c) {
+       case EDIT_KEY_ENTER:
+       case EDIT_KEY_CTRL_J:
+       case EDIT_KEY_LEFT:
+       case EDIT_KEY_RIGHT:
+       case EDIT_KEY_HOME:
+       case EDIT_KEY_END:
+       case EDIT_KEY_CTRL_A:
+       case EDIT_KEY_CTRL_E:
+               search_stop();
+               return c;
+       case EDIT_KEY_DOWN:
+       case EDIT_KEY_UP:
+               search_cancel();
+               return EDIT_KEY_EOF;
+       case EDIT_KEY_CTRL_H:
+       case EDIT_KEY_BACKSPACE:
+               search_backspace();
+               break;
+       case EDIT_KEY_CTRL_R:
+               search_next();
+               break;
+       default:
+               if (c >= 32 && c <= 255)
+                       search_char(c);
+               break;
+       }
+
+       return EDIT_KEY_NONE;
+}
+
+
 static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx)
 {
        static int last_tab = 0;
+       static int search = 0;
        enum edit_key_code c;
 
        c = edit_read_key(sock);
 
+       if (search) {
+               c = search_key(c);
+               if (c == EDIT_KEY_NONE)
+                       return;
+               search = 0;
+               if (c == EDIT_KEY_EOF)
+                       return;
+       }
+
        if (c != EDIT_KEY_TAB && c != EDIT_KEY_NONE)
                last_tab = 0;
 
@@ -867,7 +1026,8 @@ static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx)
                edit_redraw();
                break;
        case EDIT_KEY_CTRL_R:
-               /* TODO: search history */
+               search = 1;
+               search_start();
                break;
        case EDIT_KEY_CTRL_U:
                clear_left();