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:
parent
6757207328
commit
c248de0eca
@ -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]);
|
||||||
|
@ -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: */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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]);
|
||||||
|
@ -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 }
|
||||||
};
|
};
|
||||||
|
@ -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[];
|
||||||
|
Loading…
Reference in New Issue
Block a user