changeset 189:b0d64dde62af

Fix username tab completion. Should now work like in Irssi, though the problem with usernames with whitespace still exists.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 16 Nov 2010 19:28:31 +0200
parents 6b399b7ce40b
children df284de8b118
files nnchat.c
diffstat 1 files changed, 63 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/nnchat.c	Tue Nov 16 02:40:17 2010 +0200
+++ b/nnchat.c	Tue Nov 16 19:28:31 2010 +0200
@@ -732,48 +732,78 @@
 
 BOOL performTabCompletion(nn_editbuf_t *buf)
 {
-    static char *previous = NULL;
-    static char *pattern = NULL;
+    static char *previous = NULL, *pattern = NULL;
+    BOOL again = FALSE, hasSeparator = FALSE, newPattern = FALSE, hasSpace = FALSE;
+    char *str = buf->data;
     int mode = 0;
-    BOOL again = FALSE;
-    char *str = buf->data;
-    ssize_t endPos = 0, startPos = buf->pos;
+    ssize_t endPos, startPos = buf->pos;
 
-    if (startPos > 1 && str[startPos - 1] == ' ') {
+    /* previous word */
+    if (startPos >= 2 && str[startPos - 1] == ' ' && str[startPos - 2] != ' ') {
         startPos -= 2;
-        if (str[startPos] == optNickSep)
-            startPos--;
-        if (startPos <= 0 || str[startPos] == ' ')
-            return FALSE;
         endPos = startPos;
         while (startPos > 0 && str[startPos - 1] != ' ') startPos--;
         mode = 1;
     } else
-    if (str[startPos - 1] != ' ' && (startPos == buf->len || str[startPos] == ' ')) {
-        char *npattern;
-
+    /* middle of a word, new pattern */
+    if (startPos < buf->len && str[startPos] != ' ') {
+        endPos = startPos;
+        while (startPos > 0 && str[startPos - 1] != ' ') startPos--;
+        while (endPos < buf->len - 1 && str[endPos + 1] != ' ') endPos++;
+        newPattern = TRUE;
+        mode = 2;
+    } else
+    /* previous word, new pattern */
+    if (startPos >= 1 && str[startPos - 1] != ' ') {
+        startPos -= 1;
         endPos = startPos;
         while (startPos > 0 && str[startPos - 1] != ' ') startPos--;
-        while (endPos < buf->len && str[endPos] != ' ') endPos++;
-        while (endPos > 0 && str[endPos] == ' ') endPos--;
-        if (str[endPos] == optNickSep)
+        newPattern = TRUE;
+        mode = 3;
+    } else {
+        if (optDebug)
+            printMsg("no mode\n");
+        return FALSE;
+    }
+
+    if (str[endPos] == optNickSep) {
+        endPos--;
+        if (startPos > 0) {
+            if (optDebug)
+                printMsg("str[endPos] == optNickSep && startPos > 0 (%d)\n", startPos);
             return FALSE;
-        
+        }
+        hasSeparator = TRUE;
+    }
+
+    if (buf->pos > 0 && str[buf->pos - 1] == ' ')
+        hasSpace = TRUE;
+    if (buf->pos <= buf->len && str[buf->pos] == ' ')
+        hasSpace = TRUE;
+    
+    if (newPattern) {
         /* Get pattern, check if it matches previous pattern and set 'again' flag */
-        npattern = nn_editbuf_get_string(buf, startPos, endPos);
+        char *npattern = nn_editbuf_get_string(buf, startPos, endPos);
         if (pattern && npattern && strcasecmp(npattern, pattern) == 0)
             again = TRUE;
-        th_free(pattern); pattern = npattern;
+        
+        th_free(pattern);
+        pattern = npattern;
+        
         if (!again) {
             th_free(previous);
             previous = NULL;
         }
-        mode = 2;
-    } 
+    }
 
-    if (optDebug)
-        printMsg("sPos=%d, ePos=%d <-> bLen=%d : pat='%s' (mode=%d, again=%s)\n",
-                  startPos, endPos, buf->len, pattern, mode, again ? "yes" : "no");
+    if (optDebug) {
+        printMsg("sPos=%d, ePos=%d <-> bPos=%d, bufLen=%d : pat='%s' (again=%s, hassep=%s, hasspc=%s, newpat=%s, mode=%d)\n",
+                  startPos, endPos, buf->pos, buf->len, pattern,
+                  again ? "yes" : "no",
+                  hasSeparator ? "yes" : "no",
+                  hasSpace ? "yes" : "no",
+                  newPattern ? "yes" : "no", mode);
+    }
 
     if (pattern) {
         nn_user_t *user = nn_user_match(nnUsers, pattern, previous, again);
@@ -790,14 +820,16 @@
             for (i = startPos; *c; i++, c++)
                 nn_editbuf_insert(buf, i, *c);
 
-            if (previous == NULL || again) {
-                if (startPos == 0) {
-                    nn_editbuf_insert(buf, i++, optNickSep);
-                    startPos++;
-                }
+            if (!hasSeparator && startPos == 0) {
+                nn_editbuf_insert(buf, i++, optNickSep);
+                startPos++;
+            }
+            if (hasSeparator)
+                startPos++;
+            if (!hasSpace)
                 nn_editbuf_insert(buf, i++, ' ');
-            }
-            nn_editbuf_setpos(buf, startPos + 2 + strlen(user->name));
+
+            nn_editbuf_setpos(buf, startPos + 1 + strlen(user->name));
 
             th_free(previous);
             previous = th_strdup(user->name);