changeset 450:a8373a1ce1eb

Implement command tab completion.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 26 May 2012 05:09:40 +0300
parents 7d9fa9f7caf1
children 733396469e5d
files main.c
diffstat 1 files changed, 93 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/main.c	Sat May 26 04:09:03 2012 +0300
+++ b/main.c	Sat May 26 05:09:40 2012 +0300
@@ -1156,53 +1156,54 @@
 } nn_usercmd_t;
 
 
-static nn_usercmd_t userCmds[] =
+static nn_usercmd_t userCmdsTable[] =
 {
     // Server side commands, we just implement completion
-    { "me",       CMDARG_STRING,   0, NULL },
-    { "status",   CMDARG_STRING,   0, NULL },
-    { "list",     CMDARG_NONE,     0, nncmd_list_all_users },
+    { "/me",       CMDARG_STRING,   0, NULL },
+    { "/status",   CMDARG_STRING,   0, NULL },
+    { "/list",     CMDARG_NONE,     0, nncmd_list_all_users },
 
     // List internal username list
-    { "who",      CMDARG_NONE,     0, nncmd_names },
-    { "names",    CMDARG_NONE,     0, nncmd_names },
+    { "/who",      CMDARG_NONE,     0, nncmd_names },
+    { "/names",    CMDARG_NONE,     0, nncmd_names },
 
-    { "w",        CMDARG_NICK,     0, nncmd_open_profile },
-    { "profile",  CMDARG_NICK,     0, nncmd_open_profile },
+    { "/w",        CMDARG_NICK,     0, nncmd_open_profile },
+    { "/profile",  CMDARG_NICK,     0, nncmd_open_profile },
 
-    { "query",    CMDARG_NICK,     0, nncmd_open_query },
-    { "close",    CMDARG_OPTIONAL, 0, nncmd_close_query },
-    { "win",      CMDARG_OPTIONAL, 0, nncmd_window_info },
+    { "/query",    CMDARG_NICK,     0, nncmd_open_query },
+    { "/close",    CMDARG_OPTIONAL, 0, nncmd_close_query },
+    { "/win",      CMDARG_OPTIONAL, 0, nncmd_window_info },
 
-    { "ignore",   CMDARG_NICK,     0, nncmd_ignore },
-    { "color",    CMDARG_STRING,   0, nncmd_set_color },
-    { "save",     CMDARG_NONE,     0, nncmd_save_config },
+    { "/ignore",   CMDARG_NICK,     0, nncmd_ignore },
+    { "/color",    CMDARG_STRING,   0, nncmd_set_color },
+    { "/save",     CMDARG_NONE,     0, nncmd_save_config },
 };
 
-static const int nuserCmds = sizeof(userCmds) / sizeof(userCmds[0]);
+static qlist_t *userCmds = NULL;
+
+
+void nn_usercmd_init()
+{
+    size_t i;
+    for (i = 0; i < sizeof(userCmdsTable) / sizeof(userCmdsTable[0]); i++)
+    {
+        th_llist_append(&userCmds, &userCmdsTable[i]);
+        userCmdsTable[i].len = strlen(userCmdsTable[i].name);
+    }
+}
 
 
 int nn_handle_command(nn_conn_t *conn, char *buf)
 {
-    static BOOL userCmdsInit = FALSE;
-    int i;
-
-    // Initialize command structure
-    if (!userCmdsInit)
-    {
-        for (i = 0; i < nuserCmds; i++)
-            userCmds[i].len = strlen(userCmds[i].name);
+    qlist_t *curr;
 
-        userCmdsInit = TRUE;
-    }
-
+    for (curr = userCmds; curr != NULL; curr = curr->next)
+    {
+        nn_usercmd_t *cmd = curr->data;
 
-    for (i = 0; i < nuserCmds; i++)
-    {
-        nn_usercmd_t *cmd = &userCmds[i];
-        if (!th_strncasecmp(buf + 1, cmd->name, cmd->len))
+        if (!th_strncasecmp(buf, cmd->name, cmd->len))
         {
-            char *nbuf = str_trim_left(buf + 1 + cmd->len);
+            char *nbuf = str_trim_left(buf + cmd->len);
 
             switch (cmd->flags)
             {
@@ -1210,7 +1211,7 @@
                 case CMDARG_STRING:
                     if (!nbuf[0])
                     {
-                        printMsgQ(currWin, "Command: /%s requires an argument.\n", cmd->name);
+                        printMsgQ(currWin, "Command %s requires an argument.\n", cmd->name);
                         return 1;
                     }
                     break;
@@ -1218,7 +1219,7 @@
                 case CMDARG_NONE:
                     if (nbuf[0])
                     {
-                        printMsgQ(currWin, "Command: /%s does not take arguments.\n", cmd->name);
+                        printMsgQ(currWin, "Command %s does not take arguments.\n", cmd->name);
                         return 1;
                     }
                     break;
@@ -1251,6 +1252,52 @@
 }
 
 
+static nn_usercmd_t *nn_usercmd_match_do(qlist_t *list, const char *pattern, size_t len)
+{
+    qlist_t *node;
+    for (node = list; node != NULL; node = node->next)
+    {
+        nn_usercmd_t *cmd = node->data;
+        if (len <= strlen(cmd->name) && th_strncasecmp(cmd->name, pattern, len) == 0)
+            return cmd;
+    }
+    return NULL;
+}
+
+
+nn_usercmd_t *nn_usercmd_match(qlist_t *list, const char *pattern, const char *current, BOOL again)
+{
+    nn_usercmd_t *curr;
+    size_t len;
+
+    if (list == NULL || pattern == NULL) return NULL;
+
+    len = strlen(pattern);
+    
+    if (current != NULL)
+    {
+        qlist_t *node;
+        for (node = list; node != NULL; node = node->next)
+        {
+            curr = node->data;
+            if (th_strcasecmp(curr->name, current) == 0)
+            {
+                if (again)
+                    return curr;
+
+                if ((curr = nn_usercmd_match_do(node->next, pattern, len)) != NULL)
+                    return curr;
+            }
+        }
+    }
+
+    if ((curr = nn_usercmd_match_do(list, pattern, len)) != NULL)
+        return curr;
+
+    return NULL;
+}
+
+
 int nn_handle_input(nn_conn_t *conn, char *buf, size_t bufLen)
 {
     BOOL result;
@@ -1434,13 +1481,18 @@
 
     if (isCommand)
     {
-/*
-        int i;
-        for (i = 0; i < nuserCmds; i++)
+        nn_usercmd_t *cmd = nn_usercmd_match(userCmds, pattern, previous, again);
+        if (cmd)
         {
-            if (nncmd_match(pattern, 
+            size_t i;
+            nn_tabcomplete_replace(buf, &i, startPos, endPos, cmd->name);
+
+            if (!hasSpace)
+                nn_editbuf_insert(buf, i++, ' ');
+
+            nn_tabcomplete_finish(buf, &previous, startPos, cmd->name);
+            return TRUE;
         }
-*/
     }
     else
     {
@@ -1870,6 +1922,9 @@
     nn_conn_send_msg_v(conn, optUserNameEnc, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword);
     th_free(tmpStr);
 
+    // Initialize user commands
+    nn_usercmd_init();
+    
     // Initialize random numbers
     prevTime = time(NULL);
     srandom((int) prevTime);