diff options
author | Timo Sirainen <cras@irssi.org> | 2000-06-28 17:15:37 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2000-06-28 17:15:37 +0000 |
commit | 7e531cec7a80a3bc6cecb844d66ae5127f7e7a94 (patch) | |
tree | 2e2452b4fbec35a8a34e0b7364544c43d71bcd83 /src/core/commands.c | |
parent | dd7ce4af23a0bb68a8c735c7e9a4c0d9c50ae08b (diff) | |
download | irssi-7e531cec7a80a3bc6cecb844d66ae5127f7e7a94.zip |
Automatic command completion and a few other fixes.
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@387 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/core/commands.c')
-rw-r--r-- | src/core/commands.c | 162 |
1 files changed, 114 insertions, 48 deletions
diff --git a/src/core/commands.c b/src/core/commands.c index 06c2add6..311097e2 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -36,6 +36,22 @@ char *current_command; static GSList *cmdget_funcs; static int signal_default_command; +COMMAND_REC *command_find(const char *cmd) +{ + GSList *tmp; + + g_return_val_if_fail(cmd != NULL, NULL); + + for (tmp = commands; tmp != NULL; tmp = tmp->next) { + COMMAND_REC *rec = tmp->data; + + if (g_strcasecmp(rec->cmd, cmd) == 0) + return rec; + } + + return NULL; +} + void command_bind_to(int pos, const char *cmd, const char *category, SIGNAL_FUNC func) { COMMAND_REC *rec; @@ -43,10 +59,14 @@ void command_bind_to(int pos, const char *cmd, const char *category, SIGNAL_FUNC g_return_if_fail(cmd != NULL); - rec = g_new0(COMMAND_REC, 1); - rec->cmd = g_strdup(cmd); - rec->category = category == NULL ? NULL : g_strdup(category); - commands = g_slist_append(commands, rec); + rec = command_find(cmd); + if (rec == NULL) { + rec = g_new0(COMMAND_REC, 1); + rec->cmd = g_strdup(cmd); + rec->category = category == NULL ? NULL : g_strdup(category); + commands = g_slist_append(commands, rec); + } + rec->count++; if (func != NULL) { str = g_strconcat("command ", cmd, NULL); @@ -70,19 +90,14 @@ void command_free(COMMAND_REC *rec) void command_unbind(const char *cmd, SIGNAL_FUNC func) { - GSList *tmp; + COMMAND_REC *rec; char *str; g_return_if_fail(cmd != NULL); - for (tmp = commands; tmp != NULL; tmp = tmp->next) { - COMMAND_REC *rec = tmp->data; - - if (g_strcasecmp(rec->cmd, cmd) == 0) { - command_free(rec); - break; - } - } + rec = command_find(cmd); + if (rec != NULL && --rec->count == 0) + command_free(rec); if (func != NULL) { str = g_strconcat("command ", cmd, NULL); @@ -91,42 +106,81 @@ void command_unbind(const char *cmd, SIGNAL_FUNC func) } } +/* Expand `cmd' - returns `cmd' if not found, NULL if more than one + match is found */ +static const char *command_expand(char *cmd) +{ + GSList *tmp; + const char *match; + int len; + + g_return_val_if_fail(cmd != NULL, NULL); + + match = NULL; + len = strlen(cmd); + for (tmp = commands; tmp != NULL; tmp = tmp->next) { + COMMAND_REC *rec = tmp->data; + + if (g_strncasecmp(rec->cmd, cmd, len) == 0 && + strchr(rec->cmd+len, ' ') == NULL) { + if (match != NULL) { + /* multiple matches */ + signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_AMBIGUOUS), cmd); + return NULL; + } + + if (rec->cmd[len] == '\0') { + /* full match */ + return rec->cmd; + } + + /* check that this is the only match */ + match = rec->cmd; + } + } + + return match != NULL ? match : cmd; +} + void command_runsub(const char *cmd, const char *data, void *server, void *item) { - char *subcmd, *defcmd, *args; + const char *newcmd; + char *orig, *subcmd, *defcmd, *args; g_return_if_fail(data != NULL); + if (*data == '\0') { + /* no subcommand given - unknown command? */ + signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_UNKNOWN), cmd); + return; + } + /* get command.. */ - subcmd = g_strdup_printf("command %s %s", cmd, data); - args = strchr(subcmd+9 + strlen(cmd), ' '); + orig = subcmd = g_strdup_printf("command %s %s", cmd, data); + args = strchr(subcmd+8 + strlen(cmd)+1, ' '); if (args != NULL) *args++ = '\0'; else args = ""; while (*args == ' ') args++; + /* check if this command can be expanded */ + newcmd = command_expand(subcmd+8); + if (newcmd == NULL) { + /* ambiguous command */ + g_free(orig); + return; + } + + subcmd = g_strconcat("command ", newcmd, NULL); + g_strdown(subcmd); if (!signal_emit(subcmd, 3, args, server, item)) { defcmd = g_strdup_printf("default command %s", cmd); if (!signal_emit(defcmd, 3, data, server, item)) - signal_emit("unknown command", 3, strchr(subcmd, ' ')+1, server, item); + signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_UNKNOWN), subcmd+8); g_free(defcmd); } - g_free(subcmd); -} - -COMMAND_REC *command_find(const char *cmd) -{ - GSList *tmp; - - g_return_val_if_fail(cmd != NULL, NULL); - - for (tmp = commands; tmp != NULL; tmp = tmp->next) { - COMMAND_REC *rec = tmp->data; - - if (g_strcasecmp(rec->cmd, cmd) == 0) - return rec; - } - return NULL; + g_free(subcmd); + g_free(orig); } static GSList *optlist_find(GSList *optlist, const char *option) @@ -475,30 +529,42 @@ void cmd_get_remove_func(CMD_GET_FUNC func) static void parse_command(const char *command, int expand_aliases, SERVER_REC *server, void *item) { - const char *alias; - char *cmd, *str, *args, *oldcmd; + const char *alias, *newcmd; + char *cmd, *orig, *args, *oldcmd; - cmd = str = g_strconcat("command ", command, NULL); + cmd = orig = g_strconcat("command ", command, NULL); args = strchr(cmd+8, ' '); if (args != NULL) *args++ = '\0'; else args = ""; /* check if there's an alias for command */ alias = expand_aliases ? alias_find(cmd+8) : NULL; - if (alias != NULL) + if (alias != NULL) { eval_special_string(alias, args, server, item); - else { - if (server != NULL) - server_redirect_default((SERVER_REC *) server, cmd); - - g_strdown(cmd); - oldcmd = current_command; - current_command = cmd+8; - if (!signal_emit(cmd, 3, args, server, item)) - signal_emit_id(signal_default_command, 3, command, server, item); - current_command = oldcmd; + g_free(orig); + return; } - g_free(str); + /* check if this command can be expanded */ + newcmd = command_expand(cmd+8); + if (newcmd == NULL) { + /* ambiguous command */ + g_free(orig); + return; + } + + cmd = g_strconcat("command ", newcmd, NULL); + if (server != NULL) + server_redirect_default((SERVER_REC *) server, cmd); + + g_strdown(cmd); + oldcmd = current_command; + current_command = cmd+8; + if (!signal_emit(cmd, 3, args, server, item)) + signal_emit_id(signal_default_command, 3, command, server, item); + current_command = oldcmd; + + g_free(cmd); + g_free(orig); } static void event_command(const char *line, SERVER_REC *server, void *item) |