1
0
mirror of https://github.com/irssi/irssi.git synced 2025-01-03 14:56:47 -05:00

-options can now be completed with tabulator. There's also automatic

completion for them, like instead of /join -invite you can use just
/join -i.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@385 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2000-06-28 15:36:57 +00:00 committed by cras
parent 6757207328
commit c248de0eca
6 changed files with 118 additions and 26 deletions

View File

@ -129,9 +129,6 @@ COMMAND_REC *command_find(const char *cmd)
return NULL; return NULL;
} }
#define iscmdtype(c) \
((c) == '-' || (c) == '+' || (c) == '@')
static GSList *optlist_find(GSList *optlist, const char *option) static GSList *optlist_find(GSList *optlist, const char *option)
{ {
while (optlist != NULL) { while (optlist != NULL) {
@ -240,21 +237,41 @@ static char *cmd_get_quoted_param(char **data)
return pos; 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; char **tmp;
int index; int index, found, len;
g_return_val_if_fail(array != NULL, 0); g_return_val_if_fail(array != NULL, -1);
g_return_val_if_fail(item != NULL, 0); g_return_val_if_fail(option != NULL, -1);
index = 0; len = strlen(option);
g_return_val_if_fail(len > 0, -1);
found = -1; index = 0;
for (tmp = array; *tmp != NULL; tmp++, index++) { for (tmp = array; *tmp != NULL; tmp++, index++) {
if (g_strcasecmp(*tmp + iscmdtype(**tmp), item) == 0) const char *text = *tmp + iscmdtype(**tmp);
return index;
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, 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; *data = option;
return CMDERR_OPTION_UNKNOWN; 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 /* if we used a shortcut of parameter, put
the whole parameter name in options table */ the whole parameter name in options table */
option = optlist[pos] + iscmdtype(*optlist[pos]); option = optlist[pos] + iscmdtype(*optlist[pos]);

View File

@ -10,7 +10,8 @@ typedef struct {
} COMMAND_REC; } COMMAND_REC;
enum { 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_OPTION_ARG_MISSING = -1, /* argument missing for -option */
CMDERR_ERRNO, /* get the error from errno */ CMDERR_ERRNO, /* get the error from errno */
@ -22,15 +23,20 @@ enum {
CMDERR_NOT_GOOD_IDEA /* not good idea to do, -yes overrides this */ CMDERR_NOT_GOOD_IDEA /* not good idea to do, -yes overrides this */
}; };
/* Return the full command for `alias' */
#define alias_find(alias) \ #define alias_find(alias) \
iconfig_get_str("aliases", alias, NULL) iconfig_get_str("aliases", alias, NULL)
#define cmd_return_error(a) { signal_emit("error command", 1, GINT_TO_POINTER(a)); signal_stop(); return; } /* Returning from command function with error */
#define cmd_param_error(a) { cmd_params_free(free_arg); cmd_return_error(a); } #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 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); 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(a, b, c) command_bind_to(1, a, b, c)
#define command_bind_first(a, b, c) command_bind_to(0, 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 You can call this command multiple times for same command, options
will be merged. If there's any conflicts with option types, the last will be merged. If there's any conflicts with option types, the last
call will override the previous */ call will override the previous */
#define iscmdtype(c) \
((c) == '-' || (c) == '+' || (c) == '@')
void command_set_options(const char *cmd, const char *options); void command_set_options(const char *cmd, const char *options);
/* count can have these flags: */ /* count can have these flags: */

View File

@ -173,6 +173,8 @@ GList *list_add_file(GList *list, const char *name)
struct stat statbuf; struct stat statbuf;
char *fname; char *fname;
g_return_val_if_fail(name != NULL, NULL);
fname = convert_home(name); fname = convert_home(name);
if (stat(fname, &statbuf) == 0) { if (stat(fname, &statbuf) == 0) {
list = g_list_append(list, !S_ISDIR(statbuf.st_mode) ? g_strdup(name) : list = g_list_append(list, !S_ISDIR(statbuf.st_mode) ? g_strdup(name) :
@ -191,6 +193,8 @@ GList *filename_complete(const char *path)
char *realpath, *dir, *basename, *name; char *realpath, *dir, *basename, *name;
int len; int len;
g_return_val_if_fail(path != NULL, NULL);
list = NULL; list = NULL;
/* get directory part of the path - expand ~/ */ /* get directory part of the path - expand ~/ */
@ -237,6 +241,8 @@ static int is_base_command(const char *command)
GSList *tmp; GSList *tmp;
int len; int len;
g_return_val_if_fail(command != NULL, FALSE);
/* find "command "s */ /* find "command "s */
len = strlen(command); len = strlen(command);
for (tmp = commands; tmp != NULL; tmp = tmp->next) { for (tmp = commands; tmp != NULL; tmp = tmp->next) {
@ -255,6 +261,8 @@ static GList *completion_get_settings(const char *key)
GSList *tmp, *sets; GSList *tmp, *sets;
int len; int len;
g_return_val_if_fail(key != NULL, NULL);
sets = settings_get_sorted(); sets = settings_get_sorted();
len = strlen(key); len = strlen(key);
@ -275,6 +283,8 @@ static GList *completion_get_bool_settings(const char *key)
GSList *tmp, *sets; GSList *tmp, *sets;
int len; int len;
g_return_val_if_fail(key != NULL, NULL);
sets = settings_get_sorted(); sets = settings_get_sorted();
len = strlen(key); len = strlen(key);
@ -297,6 +307,8 @@ static GList *completion_get_commands(const char *cmd, char cmdchar)
char *word; char *word;
int len; int len;
g_return_val_if_fail(cmd != NULL, NULL);
len = strlen(cmd); len = strlen(cmd);
complist = NULL; complist = NULL;
for (tmp = commands; tmp != NULL; tmp = tmp->next) { for (tmp = commands; tmp != NULL; tmp = tmp->next) {
@ -323,6 +335,8 @@ static GList *completion_get_subcommands(const char *cmd)
char *spacepos; char *spacepos;
int len, skip; int len, skip;
g_return_val_if_fail(cmd != NULL, NULL);
/* get the number of chars to skip at the start of command. */ /* get the number of chars to skip at the start of command. */
spacepos = strrchr(cmd, ' '); spacepos = strrchr(cmd, ' ');
skip = spacepos == NULL ? 0 : skip = spacepos == NULL ? 0 :
@ -345,12 +359,38 @@ static GList *completion_get_subcommands(const char *cmd)
return complist; return complist;
} }
GList *completion_get_options(const char *cmd, const char *option)
{
COMMAND_REC *rec;
GList *list;
char **tmp;
int len;
g_return_val_if_fail(cmd != NULL, NULL);
g_return_val_if_fail(option != NULL, NULL);
rec = command_find(cmd);
if (rec == NULL) return NULL;
list = NULL;
len = strlen(option);
for (tmp = rec->options; *tmp != NULL; tmp++) {
if (len == 0 || g_strncasecmp(*tmp, option, len) == 0)
list = g_list_append(list, g_strconcat("-", *tmp + iscmdtype(**tmp), NULL));
}
return list;
}
/* split the line to command and arguments */ /* split the line to command and arguments */
static char *line_get_command(const char *line, char **args, int aliases) static char *line_get_command(const char *line, char **args, int aliases)
{ {
const char *ptr, *cmdargs; const char *ptr, *cmdargs;
char *cmd, *checkcmd; char *cmd, *checkcmd;
g_return_val_if_fail(line != NULL, NULL);
g_return_val_if_fail(args != NULL, NULL);
cmd = checkcmd = NULL; *args = ""; cmd = checkcmd = NULL; *args = "";
cmdargs = NULL; ptr = line; cmdargs = NULL; ptr = line;
@ -391,6 +431,8 @@ static char *expand_aliases(const char *line)
{ {
char *cmd, *args, *ret; char *cmd, *args, *ret;
g_return_val_if_fail(line != NULL, NULL);
cmd = line_get_command(line, &args, TRUE); cmd = line_get_command(line, &args, TRUE);
if (cmd == NULL) return g_strdup(line); if (cmd == NULL) return g_strdup(line);
if (*args == '\0') return cmd; if (*args == '\0') return cmd;
@ -448,16 +490,27 @@ static void sig_complete_word(GList **list, WINDOW_REC *window,
return; return;
} }
/* complete parameters */
cmd = line_get_command(line, &args, FALSE); cmd = line_get_command(line, &args, FALSE);
if (cmd != NULL) { if (cmd == NULL) {
signal = g_strconcat("complete command ", cmd, NULL); g_free(line);
signal_emit(signal, 5, list, window, word, args, want_space); return;
g_free(signal);
g_free(cmd);
} }
/* we're completing -option? */
if (*word == '-') {
*list = completion_get_options(cmd, word+1);
g_free(cmd);
g_free(line);
return;
}
/* complete parameters */
signal = g_strconcat("complete command ", cmd, NULL);
signal_emit(signal, 5, list, window, word, args, want_space);
g_free(signal);
g_free(cmd);
g_free(line); g_free(line);
} }

View File

@ -314,10 +314,13 @@ static void event_cmderror(gpointer errorp, const char *arg)
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, g_strerror(errno)); printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, g_strerror(errno));
break; break;
case CMDERR_OPTION_UNKNOWN: case CMDERR_OPTION_UNKNOWN:
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown argument: %s", arg); printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_OPTION_UNKNOWN, arg);
break;
case CMDERR_OPTION_AMBIGUOUS:
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_OPTION_AMBIGUOUS, arg);
break; break;
case CMDERR_OPTION_ARG_MISSING: case CMDERR_OPTION_ARG_MISSING:
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Missing required argument for: %s", arg); printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_OPTION_MISSING_ARG, arg);
break; break;
default: default:
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error]); printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error]);

View File

@ -91,6 +91,9 @@ FORMAT_REC fecommon_core_formats[] = {
{ "not_toggle", "Value must be either ON, OFF or TOGGLE", 0 }, { "not_toggle", "Value must be either ON, OFF or TOGGLE", 0 },
{ "perl_error", "Perl error: $0", 1, { 0 } }, { "perl_error", "Perl error: $0", 1, { 0 } },
{ "option_unknown", "Unknown option: $0", 1, { 0 } },
{ "option_ambiguous", "Ambiguous option: $0", 1, { 0 } },
{ "option_missing_arg", "Missing required argument for: $0", 1, { 0 } },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };

View File

@ -63,7 +63,10 @@ enum {
IRCTXT_FILL_6, IRCTXT_FILL_6,
IRCTXT_NOT_TOGGLE, IRCTXT_NOT_TOGGLE,
IRCTXT_PERL_ERROR IRCTXT_PERL_ERROR,
IRCTXT_OPTION_UNKNOWN,
IRCTXT_OPTION_AMBIGUOUS,
IRCTXT_OPTION_MISSING_ARG
}; };
extern FORMAT_REC fecommon_core_formats[]; extern FORMAT_REC fecommon_core_formats[];