mirror of
https://github.com/weechat/weechat.git
synced 2026-07-06 17:53:13 +02:00
core: allow incomplete commands if unambiguous (task #5419)
This commit is contained in:
@@ -103,6 +103,7 @@ struct t_config_option *config_look_color_nick_offline;
|
||||
struct t_config_option *config_look_color_pairs_auto_reset;
|
||||
struct t_config_option *config_look_color_real_white;
|
||||
struct t_config_option *config_look_command_chars;
|
||||
struct t_config_option *config_look_command_incomplete;
|
||||
struct t_config_option *config_look_confirm_quit;
|
||||
struct t_config_option *config_look_day_change;
|
||||
struct t_config_option *config_look_day_change_message_1date;
|
||||
@@ -2219,6 +2220,12 @@ config_weechat_init_options ()
|
||||
"input must start with one of these chars; the slash (\"/\") is "
|
||||
"always considered as command prefix (example: \".$\")"),
|
||||
NULL, 0, 0, "", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
config_look_command_incomplete = config_file_new_option (
|
||||
weechat_config_file, ptr_section,
|
||||
"command_incomplete", "boolean",
|
||||
N_("if set, incomplete and unambigous commands are allowed, for "
|
||||
"example /he for /help"),
|
||||
NULL, 0, 0, "off", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
config_look_confirm_quit = config_file_new_option (
|
||||
weechat_config_file, ptr_section,
|
||||
"confirm_quit", "boolean",
|
||||
|
||||
@@ -141,6 +141,7 @@ extern struct t_config_option *config_look_color_nick_offline;
|
||||
extern struct t_config_option *config_look_color_pairs_auto_reset;
|
||||
extern struct t_config_option *config_look_color_real_white;
|
||||
extern struct t_config_option *config_look_command_chars;
|
||||
extern struct t_config_option *config_look_command_incomplete;
|
||||
extern struct t_config_option *config_look_confirm_quit;
|
||||
extern struct t_config_option *config_look_day_change;
|
||||
extern struct t_config_option *config_look_day_change_message_1date;
|
||||
|
||||
+72
-43
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "weechat.h"
|
||||
#include "wee-hook.h"
|
||||
#include "wee-config.h"
|
||||
#include "wee-hashtable.h"
|
||||
#include "wee-hdata.h"
|
||||
#include "wee-infolist.h"
|
||||
@@ -654,12 +655,12 @@ hook_command (struct t_weechat_plugin *plugin, const char *command,
|
||||
* Executes a command hook.
|
||||
*
|
||||
* Returns:
|
||||
* 0: command executed and failed
|
||||
* 1: command executed successfully
|
||||
* -1: command not found
|
||||
* -2: command is ambiguous (same command exists for another plugin, and we
|
||||
* don't know which one to run)
|
||||
* -3: command is already running
|
||||
* HOOK_COMMAND_EXEC_OK: command executed successfully
|
||||
* HOOK_COMMAND_EXEC_ERROR: command executed and failed
|
||||
* HOOK_COMMAND_EXEC_NOT_FOUND: command not found
|
||||
* HOOK_COMMAND_EXEC_AMBIGUOUS: command is ambiguous (same command exists for
|
||||
* another plugin, and we don't know which one to run)
|
||||
* HOOK_COMMAND_EXEC_RUNNING: command is already running
|
||||
*/
|
||||
|
||||
int
|
||||
@@ -668,62 +669,79 @@ hook_command_exec (struct t_gui_buffer *buffer, int any_plugin,
|
||||
{
|
||||
struct t_hook *ptr_hook, *next_hook;
|
||||
struct t_hook *hook_plugin, *hook_other_plugin, *hook_other_plugin2;
|
||||
struct t_hook *hook_incomplete_command;
|
||||
char **argv, **argv_eol, *ptr_command_name;
|
||||
int argc, rc, count_other_plugin;
|
||||
int argc, rc, length_command_name, allow_incomplete_commands;
|
||||
int count_other_plugin, count_incomplete_commands;
|
||||
|
||||
if (!buffer || !string || !string[0])
|
||||
return -1;
|
||||
return HOOK_COMMAND_EXEC_NOT_FOUND;
|
||||
|
||||
if (hook_command_run_exec (buffer, string) == WEECHAT_RC_OK_EAT)
|
||||
return 1;
|
||||
return HOOK_COMMAND_EXEC_OK;
|
||||
|
||||
argv = string_split (string, " ", 0, 0, &argc);
|
||||
if (argc == 0)
|
||||
{
|
||||
string_free_split (argv);
|
||||
return -1;
|
||||
return HOOK_COMMAND_EXEC_NOT_FOUND;
|
||||
}
|
||||
argv_eol = string_split (string, " ", 1, 0, NULL);
|
||||
|
||||
ptr_command_name = utf8_next_char (argv[0]);
|
||||
length_command_name = strlen (ptr_command_name);
|
||||
|
||||
hook_exec_start ();
|
||||
|
||||
hook_plugin = NULL;
|
||||
hook_other_plugin = NULL;
|
||||
hook_other_plugin2 = NULL;
|
||||
hook_incomplete_command = NULL;
|
||||
count_other_plugin = 0;
|
||||
allow_incomplete_commands = CONFIG_BOOLEAN(config_look_command_incomplete);
|
||||
count_incomplete_commands = 0;
|
||||
ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND];
|
||||
while (ptr_hook)
|
||||
{
|
||||
next_hook = ptr_hook->next_hook;
|
||||
|
||||
if (!ptr_hook->deleted
|
||||
&& (string_strcasecmp (ptr_command_name,
|
||||
HOOK_COMMAND(ptr_hook, command)) == 0))
|
||||
if (!ptr_hook->deleted)
|
||||
{
|
||||
if (ptr_hook->plugin == plugin)
|
||||
if (string_strcasecmp (ptr_command_name,
|
||||
HOOK_COMMAND(ptr_hook, command)) == 0)
|
||||
{
|
||||
if (!hook_plugin)
|
||||
hook_plugin = ptr_hook;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (any_plugin)
|
||||
if (ptr_hook->plugin == plugin)
|
||||
{
|
||||
if (!hook_other_plugin)
|
||||
hook_other_plugin = ptr_hook;
|
||||
else if (!hook_other_plugin2)
|
||||
hook_other_plugin2 = ptr_hook;
|
||||
count_other_plugin++;
|
||||
if (!hook_plugin)
|
||||
hook_plugin = ptr_hook;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (any_plugin)
|
||||
{
|
||||
if (!hook_other_plugin)
|
||||
hook_other_plugin = ptr_hook;
|
||||
else if (!hook_other_plugin2)
|
||||
hook_other_plugin2 = ptr_hook;
|
||||
count_other_plugin++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (allow_incomplete_commands
|
||||
&& (string_strncasecmp (ptr_command_name,
|
||||
HOOK_COMMAND(ptr_hook, command),
|
||||
length_command_name) == 0))
|
||||
{
|
||||
hook_incomplete_command = ptr_hook;
|
||||
count_incomplete_commands++;
|
||||
}
|
||||
}
|
||||
|
||||
ptr_hook = next_hook;
|
||||
}
|
||||
|
||||
rc = -1;
|
||||
rc = HOOK_COMMAND_EXEC_NOT_FOUND;
|
||||
ptr_hook = NULL;
|
||||
|
||||
if (hook_plugin || hook_other_plugin)
|
||||
{
|
||||
@@ -735,7 +753,7 @@ hook_command_exec (struct t_gui_buffer *buffer, int any_plugin,
|
||||
* command was found for other plugins with the same priority
|
||||
* => we don't know which one to run!
|
||||
*/
|
||||
rc = -2;
|
||||
rc = HOOK_COMMAND_EXEC_AMBIGUOUS_PLUGINS;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -758,24 +776,35 @@ hook_command_exec (struct t_gui_buffer *buffer, int any_plugin,
|
||||
*/
|
||||
ptr_hook = (hook_plugin) ? hook_plugin : hook_other_plugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hook_incomplete_command)
|
||||
{
|
||||
if (count_incomplete_commands == 1)
|
||||
ptr_hook = hook_incomplete_command;
|
||||
else
|
||||
rc = HOOK_COMMAND_EXEC_AMBIGUOUS_INCOMPLETE;
|
||||
}
|
||||
|
||||
if (ptr_hook->running >= HOOK_COMMAND_MAX_CALLS)
|
||||
{
|
||||
/* loop in execution of command => do NOT execute again */
|
||||
rc = -3;
|
||||
}
|
||||
/* execute the command for the hook found */
|
||||
if (ptr_hook)
|
||||
{
|
||||
if (ptr_hook->running >= HOOK_COMMAND_MAX_CALLS)
|
||||
{
|
||||
/* loop in execution of command => do NOT execute again */
|
||||
rc = HOOK_COMMAND_EXEC_RUNNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* execute the command! */
|
||||
ptr_hook->running++;
|
||||
rc = (int) (HOOK_COMMAND(ptr_hook, callback))
|
||||
(ptr_hook->callback_data, buffer, argc, argv, argv_eol);
|
||||
ptr_hook->running--;
|
||||
if (rc == WEECHAT_RC_ERROR)
|
||||
rc = HOOK_COMMAND_EXEC_ERROR;
|
||||
else
|
||||
{
|
||||
/* execute the command! */
|
||||
ptr_hook->running++;
|
||||
rc = (int) (HOOK_COMMAND(ptr_hook, callback))
|
||||
(ptr_hook->callback_data, buffer, argc, argv, argv_eol);
|
||||
ptr_hook->running--;
|
||||
if (rc == WEECHAT_RC_ERROR)
|
||||
rc = 0;
|
||||
else
|
||||
rc = 1;
|
||||
}
|
||||
rc = HOOK_COMMAND_EXEC_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,14 @@ enum t_hook_type
|
||||
/* max calls that can be done for a command (recursive calls) */
|
||||
#define HOOK_COMMAND_MAX_CALLS 5
|
||||
|
||||
/* return code when a command is executed */
|
||||
#define HOOK_COMMAND_EXEC_OK 1
|
||||
#define HOOK_COMMAND_EXEC_ERROR 0
|
||||
#define HOOK_COMMAND_EXEC_NOT_FOUND -1
|
||||
#define HOOK_COMMAND_EXEC_AMBIGUOUS_PLUGINS -2
|
||||
#define HOOK_COMMAND_EXEC_AMBIGUOUS_INCOMPLETE -3
|
||||
#define HOOK_COMMAND_EXEC_RUNNING -4
|
||||
|
||||
/* flags for fd hooks */
|
||||
#define HOOK_FD_FLAG_READ 1
|
||||
#define HOOK_FD_FLAG_WRITE 2
|
||||
|
||||
+41
-22
@@ -100,35 +100,22 @@ input_exec_command (struct t_gui_buffer *buffer,
|
||||
/* execute command */
|
||||
switch (hook_command_exec (buffer, any_plugin, plugin, command))
|
||||
{
|
||||
case 0: /* command hooked, KO */
|
||||
case HOOK_COMMAND_EXEC_OK:
|
||||
/* command hooked, OK (executed) */
|
||||
break;
|
||||
case HOOK_COMMAND_EXEC_ERROR:
|
||||
/* command hooked, error */
|
||||
gui_chat_printf_date_tags (NULL, 0, GUI_FILTER_TAG_NO_FILTER,
|
||||
_("%sError with command \"%s\" (help on "
|
||||
"command: /help %s)"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
command, command_name + 1);
|
||||
break;
|
||||
case 1: /* command hooked, OK (executed) */
|
||||
break;
|
||||
case -2: /* command is ambiguous (exists for other plugins) */
|
||||
gui_chat_printf_date_tags (NULL, 0, GUI_FILTER_TAG_NO_FILTER,
|
||||
_("%sError: ambiguous command \"%s\": "
|
||||
"it exists in many plugins and not in "
|
||||
"\"%s\" plugin"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
command_name,
|
||||
plugin_get_name (plugin));
|
||||
break;
|
||||
case -3: /* command is running */
|
||||
gui_chat_printf_date_tags (NULL, 0, GUI_FILTER_TAG_NO_FILTER,
|
||||
_("%sError: too much calls to command "
|
||||
"\"%s\" (looping)"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
command_name);
|
||||
break;
|
||||
default: /* no command hooked */
|
||||
case HOOK_COMMAND_EXEC_NOT_FOUND:
|
||||
/*
|
||||
* if unknown commands are accepted by this buffer, just send
|
||||
* input text as data to buffer, otherwise display error
|
||||
* command not found: if unknown commands are accepted by this
|
||||
* buffer, just send input text as data to buffer,
|
||||
* otherwise display error
|
||||
*/
|
||||
if (buffer->input_get_unknown_commands)
|
||||
{
|
||||
@@ -143,6 +130,38 @@ input_exec_command (struct t_gui_buffer *buffer,
|
||||
command_name);
|
||||
}
|
||||
break;
|
||||
case HOOK_COMMAND_EXEC_AMBIGUOUS_PLUGINS:
|
||||
/* command is ambiguous (exists for other plugins) */
|
||||
gui_chat_printf_date_tags (NULL, 0, GUI_FILTER_TAG_NO_FILTER,
|
||||
_("%sError: ambiguous command \"%s\": "
|
||||
"it exists in many plugins and not in "
|
||||
"\"%s\" plugin"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
command_name,
|
||||
plugin_get_name (plugin));
|
||||
break;
|
||||
case HOOK_COMMAND_EXEC_AMBIGUOUS_INCOMPLETE:
|
||||
/*
|
||||
* command is ambiguous (incomplete command and many commands
|
||||
* start with this name)
|
||||
*/
|
||||
gui_chat_printf_date_tags (NULL, 0, GUI_FILTER_TAG_NO_FILTER,
|
||||
_("%sError: incomplete command \"%s\" "
|
||||
"and many commands start with this "
|
||||
"name"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
command_name);
|
||||
break;
|
||||
case HOOK_COMMAND_EXEC_RUNNING:
|
||||
/* command is running */
|
||||
gui_chat_printf_date_tags (NULL, 0, GUI_FILTER_TAG_NO_FILTER,
|
||||
_("%sError: too much calls to command "
|
||||
"\"%s\" (looping)"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
command_name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free (command);
|
||||
free (command_name);
|
||||
|
||||
@@ -224,27 +224,45 @@ struct t_hook *
|
||||
gui_completion_search_command (struct t_weechat_plugin *plugin,
|
||||
const char *command)
|
||||
{
|
||||
struct t_hook *ptr_hook, *hook_for_other_plugin;
|
||||
struct t_hook *ptr_hook, *hook_for_other_plugin, *hook_incomplete_command;
|
||||
int length_command, allow_incomplete_commands, count_incomplete_commands;
|
||||
|
||||
hook_for_other_plugin = NULL;
|
||||
hook_incomplete_command = NULL;
|
||||
length_command = strlen (command);
|
||||
count_incomplete_commands = 0;
|
||||
allow_incomplete_commands = CONFIG_BOOLEAN(config_look_command_incomplete);
|
||||
|
||||
for (ptr_hook = weechat_hooks[HOOK_TYPE_COMMAND]; ptr_hook;
|
||||
ptr_hook = ptr_hook->next_hook)
|
||||
{
|
||||
if (!ptr_hook->deleted
|
||||
&& HOOK_COMMAND(ptr_hook, command)
|
||||
&& HOOK_COMMAND(ptr_hook, command)[0]
|
||||
&& (string_strcasecmp (HOOK_COMMAND(ptr_hook, command),
|
||||
command) == 0))
|
||||
&& HOOK_COMMAND(ptr_hook, command)[0])
|
||||
{
|
||||
if (ptr_hook->plugin == plugin)
|
||||
return ptr_hook;
|
||||
|
||||
hook_for_other_plugin = ptr_hook;
|
||||
if (string_strcasecmp (HOOK_COMMAND(ptr_hook, command),
|
||||
command) == 0)
|
||||
{
|
||||
if (ptr_hook->plugin == plugin)
|
||||
return ptr_hook;
|
||||
hook_for_other_plugin = ptr_hook;
|
||||
}
|
||||
else if (allow_incomplete_commands
|
||||
&& (string_strncasecmp (HOOK_COMMAND(ptr_hook, command),
|
||||
command,
|
||||
length_command) == 0))
|
||||
{
|
||||
hook_incomplete_command = ptr_hook;
|
||||
count_incomplete_commands++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hook_for_other_plugin;
|
||||
if (hook_for_other_plugin)
|
||||
return hook_for_other_plugin;
|
||||
|
||||
return (count_incomplete_commands == 1) ?
|
||||
hook_incomplete_command : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user