summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/commands.c46
-rw-r--r--src/core/commands.h16
2 files changed, 46 insertions, 16 deletions
diff --git a/src/core/commands.c b/src/core/commands.c
index b2151c1e..06c2add6 100644
--- a/src/core/commands.c
+++ b/src/core/commands.c
@@ -129,9 +129,6 @@ COMMAND_REC *command_find(const char *cmd)
return NULL;
}
-#define iscmdtype(c) \
- ((c) == '-' || (c) == '+' || (c) == '@')
-
static GSList *optlist_find(GSList *optlist, const char *option)
{
while (optlist != NULL) {
@@ -240,21 +237,41 @@ static char *cmd_get_quoted_param(char **data)
return pos;
}
-static int option_find(char **array, const char *item)
+/* Find specified option from list of options - the `option' might be
+ shortened version of the full command. Returns index where the
+ option was found, -1 if not found or -2 if there was multiple matches. */
+static int option_find(char **array, const char *option)
{
char **tmp;
- int index;
+ int index, found, len;
+
+ g_return_val_if_fail(array != NULL, -1);
+ g_return_val_if_fail(option != NULL, -1);
- g_return_val_if_fail(array != NULL, 0);
- g_return_val_if_fail(item != NULL, 0);
+ len = strlen(option);
+ g_return_val_if_fail(len > 0, -1);
- index = 0;
+ found = -1; index = 0;
for (tmp = array; *tmp != NULL; tmp++, index++) {
- if (g_strcasecmp(*tmp + iscmdtype(**tmp), item) == 0)
- return index;
+ const char *text = *tmp + iscmdtype(**tmp);
+
+ if (g_strncasecmp(text, option, len) == 0) {
+ if (text[len] == '\0') {
+ /* full match */
+ return index;
+ }
+
+ if (found != -1) {
+ /* multiple matches - abort */
+ return -2;
+ }
+
+ /* partial match, check that it's the only one */
+ found = index;
+ }
}
- return -1;
+ return found;
}
static int get_cmd_options(char **data, int ignore_unknown,
@@ -295,7 +312,12 @@ static int get_cmd_options(char **data, int ignore_unknown,
*data = option;
return CMDERR_OPTION_UNKNOWN;
}
- if (pos != -1) {
+ if (pos == -2 && !ignore_unknown) {
+ /* multiple matches */
+ *data = option;
+ return CMDERR_OPTION_AMBIGUOUS;
+ }
+ if (pos >= 0) {
/* if we used a shortcut of parameter, put
the whole parameter name in options table */
option = optlist[pos] + iscmdtype(*optlist[pos]);
diff --git a/src/core/commands.h b/src/core/commands.h
index 1f1dc8dd..fa553518 100644
--- a/src/core/commands.h
+++ b/src/core/commands.h
@@ -10,7 +10,8 @@ typedef struct {
} COMMAND_REC;
enum {
- CMDERR_OPTION_UNKNOWN = -2, /* unknown -option */
+ CMDERR_OPTION_UNKNOWN = -3, /* unknown -option */
+ CMDERR_OPTION_AMBIGUOUS = -2, /* ambiguous -option */
CMDERR_OPTION_ARG_MISSING = -1, /* argument missing for -option */
CMDERR_ERRNO, /* get the error from errno */
@@ -22,15 +23,20 @@ enum {
CMDERR_NOT_GOOD_IDEA /* not good idea to do, -yes overrides this */
};
+/* Return the full command for `alias' */
#define alias_find(alias) \
iconfig_get_str("aliases", alias, NULL)
-#define cmd_return_error(a) { signal_emit("error command", 1, GINT_TO_POINTER(a)); signal_stop(); return; }
-#define cmd_param_error(a) { cmd_params_free(free_arg); cmd_return_error(a); }
+/* Returning from command function with error */
+#define cmd_return_error(a) \
+ { signal_emit("error command", 1, GINT_TO_POINTER(a)); signal_stop(); return; }
+#define cmd_param_error(a) \
+ { cmd_params_free(free_arg); cmd_return_error(a); }
extern GSList *commands;
-extern char *current_command;
+extern char *current_command; /* the command we're right now. */
+/* Bind command to specified function. */
void command_bind_to(int pos, const char *cmd, const char *category, SIGNAL_FUNC func);
#define command_bind(a, b, c) command_bind_to(1, a, b, c)
#define command_bind_first(a, b, c) command_bind_to(0, a, b, c)
@@ -57,6 +63,8 @@ COMMAND_REC *command_find(const char *cmd);
You can call this command multiple times for same command, options
will be merged. If there's any conflicts with option types, the last
call will override the previous */
+#define iscmdtype(c) \
+ ((c) == '-' || (c) == '+' || (c) == '@')
void command_set_options(const char *cmd, const char *options);
/* count can have these flags: */