changeset 2143:2f294c2b6778

Add a backward completion (Oleg) When we skip some needed item with tab, we can back with shift+tab.
author Mikael Berthe <mikael@lilotux.net>
date Sun, 06 Jul 2014 14:51:17 +0200
parents 0e8a25503ee1
children d3348deb32bd
files mcabber/mcabber/commands.c mcabber/mcabber/compl.c mcabber/mcabber/compl.h mcabber/mcabber/screen.c mcabber/mcabber/screen.h
diffstat 5 files changed, 41 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/mcabber/mcabber/commands.c	Sun Jul 06 14:51:14 2014 +0200
+++ b/mcabber/mcabber/commands.c	Sun Jul 06 14:51:17 2014 +0200
@@ -4078,7 +4078,9 @@
   } else if (!strcasecmp(arg, "compl_cancel")) {
     readline_cancel_completion();
   } else if (!strcasecmp(arg, "compl_do")) {
-    readline_do_completion();
+    readline_do_completion(TRUE);
+  } else if (!strcasecmp(arg, "compl_do_bwd")) {
+    readline_do_completion(FALSE);
   } else if (!strcasecmp(arg, "clear_history")) {
     readline_clear_history();
   } else {
--- a/mcabber/mcabber/compl.c	Sun Jul 06 14:51:14 2014 +0200
+++ b/mcabber/mcabber/compl.c	Sun Jul 06 14:51:17 2014 +0200
@@ -41,10 +41,10 @@
 
 // Completion structure
 typedef struct {
-  GSList *list;         // list of matches
+  GList *list;          // list of matches
   guint len_prefix;     // length of text already typed by the user
   guint len_compl;      // length of the last completion
-  GSList *next;         // pointer to next completion to try
+  GList *next;          // pointer to next completion to try
 } compl;
 
 typedef GSList *(*compl_handler_t) (void); // XXX userdata? *dynlist?
@@ -233,12 +233,13 @@
         else
           compval = g_strdup(word+len);
         // for a bit of efficiency, will reverse order afterwards
-        c->list = g_slist_prepend(c->list, compval);
+        c->list = g_list_prepend(c->list, compval);
         ret_len ++;
       }
     }
   }
-  c->next = c->list = g_slist_reverse (c->list);
+  c->list = g_list_reverse(c->list);
+  c->next = NULL;
   InputCompl = c;
   return ret_len;
 }
@@ -246,14 +247,14 @@
 //  done_completion();
 void done_completion(void)
 {
-  GSList *clp;
+  GList *clp;
 
   if (!InputCompl)  return;
 
   // Free the current completion list
-  for (clp = InputCompl->list; clp; clp = g_slist_next(clp))
+  for (clp = InputCompl->list; clp; clp = g_list_next(clp))
     g_free(clp->data);
-  g_slist_free(InputCompl->list);
+  g_list_free(InputCompl->list);
   g_free(InputCompl);
   InputCompl = NULL;
 }
@@ -267,7 +268,7 @@
 }
 
 // Returns pointer to text to insert, NULL if no completion.
-const char *complete()
+const char *complete(gboolean fwd)
 {
   compl* c = InputCompl;
   char *r;
@@ -275,12 +276,25 @@
   if (!InputCompl)  return NULL;
 
   if (!c->next) {
-    c->next = c->list;  // back to the beginning
+    if (fwd)
+      c->next = c->list;  // back to the beginning
+    else
+      c->next = g_list_last(c->list); // back to the ending
+  } else {
+    if (fwd)
+      c->next = g_list_next(c->next);
+    else
+      c->next = g_list_previous(c->next);
+  }
+
+  if (!c->next) {
+    c->next = NULL;
     c->len_compl = 0;
     return NULL;
   }
+
   r = (char*)c->next->data;
-  c->next = g_slist_next(c->next);
+
   if (!utf8_mode) {
     c->len_compl = strlen(r);
   } else {
--- a/mcabber/mcabber/compl.h	Sun Jul 06 14:51:14 2014 +0200
+++ b/mcabber/mcabber/compl.h	Sun Jul 06 14:51:17 2014 +0200
@@ -51,7 +51,7 @@
                        const gchar *suffix);
 void    done_completion(void);
 guint   cancel_completion(void);
-const char *complete(void);
+const char *complete(gboolean fwd);
 
 #endif /* __MCABBER_COMPL_H__ */
 
--- a/mcabber/mcabber/screen.c	Sun Jul 06 14:51:14 2014 +0200
+++ b/mcabber/mcabber/screen.c	Sun Jul 06 14:51:17 2014 +0200
@@ -84,7 +84,7 @@
 static void scr_cancel_current_completion(void);
 static void scr_end_current_completion(void);
 static void scr_insert_text(const char*);
-static void scr_handle_tab(void);
+static void scr_handle_tab(gboolean fwd);
 
 #if defined XEP0022 || defined XEP0085
 static gboolean scr_chatstates_timeout();
@@ -3673,13 +3673,13 @@
   check_offset(-1);
 }
 
-void readline_do_completion(void)
+void readline_do_completion(gboolean fwd)
 {
   int i, n;
 
   if (multimode != 2) {
     // Not in verbatim multi-line mode
-    scr_handle_tab();
+    scr_handle_tab(fwd);
   } else {
     // Verbatim multi-line mode: expand tab
     char tabstr[9];
@@ -3888,7 +3888,8 @@
 //  scr_handle_tab()
 // Function called when tab is pressed.
 // Initiate or continue a completion...
-static void scr_handle_tab(void)
+// If fwd is false, a backward-completion is requested.
+static void scr_handle_tab(gboolean fwd)
 {
   int nrow;
   const char *row;
@@ -3973,7 +3974,7 @@
         g_slist_free(list);
       }
       // Now complete
-      cchar = complete();
+      cchar = complete(fwd);
       if (cchar)
         scr_insert_text(cchar);
       completion_started = TRUE;
@@ -3981,7 +3982,7 @@
   } else {      // Completion already initialized
     scr_cancel_current_completion();
     // Now complete again
-    cchar = complete();
+    cchar = complete(fwd);
     if (cchar)
       scr_insert_text(cchar);
   }
@@ -4362,7 +4363,10 @@
     case ERR:
         break;
     case 9:     // Tab
-        readline_do_completion();
+        readline_do_completion(TRUE);   // Forward-completion
+        break;
+    case 353:   // Shift-Tab
+        readline_do_completion(FALSE);  // Backward-completion
         break;
     case 13:    // Enter
     case 343:   // Enter on Maemo
@@ -4423,7 +4427,7 @@
     }
   }
 
-  if (completion_started && key != 9 && key != KEY_RESIZE)
+  if (completion_started && key != 9 && key != 353 && key != KEY_RESIZE)
     scr_end_current_completion();
   refresh_inputline();
 
--- a/mcabber/mcabber/screen.h	Sun Jul 06 14:51:14 2014 +0200
+++ b/mcabber/mcabber/screen.h	Sun Jul 06 14:51:17 2014 +0200
@@ -181,7 +181,7 @@
 int  readline_accept_line(int down_history);
 void readline_clear_history(void);
 void readline_cancel_completion(void);
-void readline_do_completion(void);
+void readline_do_completion(gboolean fwd);
 void readline_refresh_screen(void);
 void readline_disable_chat_mode(guint show_roster);
 void readline_hist_beginning_search_bwd(void);