Show typed text as last completion entry (#253).
authorDaniel Carl <danielcarl@gmx.de>
Sun, 22 Nov 2015 21:17:25 +0000 (22:17 +0100)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 22 Nov 2015 21:31:56 +0000 (22:31 +0100)
This patch adapts the vim behaviour. If you reach the end of the
possible completion items, the initial content is written to the
inputbox. This makes it easier to change the filter string to reduce the
completion by simply step right to the very last entry with <S-Tab>.

src/completion.c
src/completion.h
src/ex.c

index 48cd08f..d90ed17 100644 (file)
@@ -161,7 +161,12 @@ gboolean completion_create(GtkTreeModel *model, CompletionSelectFunc selfunc,
     return true;
 }
 
-void completion_next(gboolean back)
+/**
+ * Moves the selection to the next/previous tree item.
+ * If the end/beginning is reached return false and start on the opposite end
+ * on the next call.
+ */
+gboolean completion_next(gboolean back)
 {
     int rows;
     GtkTreePath *path;
@@ -171,12 +176,22 @@ void completion_next(gboolean back)
     if (back) {
         /* step back */
         if (--comp.active < 0) {
-            comp.active = rows - 1;
+            if (comp.active == -1) {
+                gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(comp.tree)));
+                return false;
+            } else {
+                comp.active = rows - 1;
+            }
         }
     } else {
         /* step forward */
         if (++comp.active >= rows) {
-            comp.active = 0;
+            if (comp.active == rows) {
+                gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(comp.tree)));
+                return false;
+            } else {
+                comp.active = 0;
+            }
         }
     }
 
@@ -184,6 +199,8 @@ void completion_next(gboolean back)
     path = gtk_tree_path_new_from_indices(comp.active, -1);
     gtk_tree_view_set_cursor(tree, path, NULL, false);
     gtk_tree_path_free(path);
+
+    return true;
 }
 
 void completion_clean(void)
index 4ef496e..26b057d 100644 (file)
@@ -35,6 +35,6 @@ typedef void (*CompletionSelectFunc) (char *match);
 gboolean completion_create(GtkTreeModel *model, CompletionSelectFunc selfunc,
     gboolean back);
 void completion_clean(void);
-void completion_next(gboolean back);
+gboolean completion_next(gboolean back);
 
 #endif /* end of include guard: _COMPLETION_H */
index 56634f2..e3e4281 100644 (file)
--- a/src/ex.c
+++ b/src/ex.c
@@ -208,6 +208,7 @@ static struct {
     guint count;
     char  *prefix;  /* completion prefix like :, ? and / */
     char  *current; /* holds the current written input box content */
+    char  *token;   /* initial filter content */
 } excomp;
 
 static struct {
@@ -1102,8 +1103,11 @@ static gboolean complete(short direction)
     /* if completion was already started move to the next/prev item */
     if (vb.mode->flags & FLAG_COMPLETION) {
         if (excomp.current && !strcmp(input, excomp.current)) {
-            /* step through the next/prev completion item */
-            completion_next(direction < 0);
+            /* Step through the next/prev completion item. */
+            if (!completion_next(direction < 0)) {
+                /* If we stepped over the last/first item - put the initial content in */
+                completion_select(excomp.token);
+            }
             g_free(input);
 
             return true;
@@ -1135,7 +1139,6 @@ static gboolean complete(short direction)
          * there is a space after the command and the optional '!' bang. */
         if (parse_command_name(&in, arg) && parse_bang(&in, arg) && VB_IS_SPACE(*in)) {
             const char *token;
-
             /* Get only the last word of input string for the completion for
              * bookmark tag completion. */
             if (arg->code == EX_BMA) {
@@ -1155,6 +1158,7 @@ static gboolean complete(short direction)
              * the ':open ' if ':open something' is completed. This means that
              * the completion will only the none prefix part of the input */
             OVERWRITE_NSTRING(excomp.prefix, input, token - input + 1);
+            OVERWRITE_STRING(excomp.token, token + 1);
 
             /* the token points to a space, skip this */
             skip_whitespace(&token);
@@ -1212,6 +1216,7 @@ static gboolean complete(short direction)
         } else { /* complete command names */
             /* restore the 'in' pointer after try to parse command name */
             in = before_cmdname;
+            OVERWRITE_STRING(excomp.token, in);
 
             /* Backup the parsed data so we can access them in
              * completion_select function. */
@@ -1225,6 +1230,7 @@ static gboolean complete(short direction)
         free_cmdarg(arg);
     } else if (*in == '/' || *in == '?') {
         if (history_fill_completion(store, HISTORY_SEARCH, in + 1)) {
+            OVERWRITE_STRING(excomp.token, in + 1);
             OVERWRITE_NSTRING(excomp.prefix, in, 1);
             sort  = true;
             found = true;