1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -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;
}
#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, 0);
g_return_val_if_fail(item != NULL, 0);
g_return_val_if_fail(array != NULL, -1);
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++) {
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]);

View File

@ -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: */

View File

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

View File

@ -314,10 +314,13 @@ static void event_cmderror(gpointer errorp, const char *arg)
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, g_strerror(errno));
break;
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;
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;
default:
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 },
{ "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 }
};

View File

@ -63,7 +63,10 @@ enum {
IRCTXT_FILL_6,
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[];