# HG changeset patch # User Matti Hamalainen # Date 1337998180 -10800 # Node ID a8373a1ce1eb5bf511d6e31d88578090cc9fda1e # Parent 7d9fa9f7caf155519227ba5b1f10c830b1a2d8e1 Implement command tab completion. diff -r 7d9fa9f7caf1 -r a8373a1ce1eb main.c --- 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);