diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2007-12-07 15:01:37 +0100 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2007-12-07 15:01:37 +0100 |
commit | 72a694ed4c78df15b68ef4698b16f7072919f3ee (patch) | |
tree | 499e976612d6fe1d92675149707350c38b74758b /src | |
parent | 495e6bd5df9163148676821d610c9ef863326f70 (diff) | |
download | weechat-72a694ed4c78df15b68ef4698b16f7072919f3ee.zip |
Added completion hook, to let plugins add custom completions for commands
Diffstat (limited to 'src')
-rw-r--r-- | src/core/wee-command.c | 20 | ||||
-rw-r--r-- | src/core/wee-hook.c | 86 | ||||
-rw-r--r-- | src/core/wee-hook.h | 13 | ||||
-rw-r--r-- | src/gui/gui-completion.c | 79 | ||||
-rw-r--r-- | src/plugins/alias/alias.c | 29 | ||||
-rw-r--r-- | src/plugins/plugin-api.c | 15 | ||||
-rw-r--r-- | src/plugins/plugin-api.h | 4 | ||||
-rw-r--r-- | src/plugins/plugin.c | 1 | ||||
-rw-r--r-- | src/plugins/weechat-plugin.h | 6 |
9 files changed, 230 insertions, 23 deletions
diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 487527656..72405bc9a 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -1020,7 +1020,7 @@ command_plugin_list (char *name, int full) { if (!hook_found) gui_chat_printf (NULL, - _(" configuration otions " + _(" configuration options " "hooked:")); hook_found = 1; gui_chat_printf (NULL, @@ -1031,6 +1031,24 @@ command_plugin_list (char *name, int full) HOOK_CONFIG(ptr_hook, option) : "*"); } } + + /* completion hooked */ + hook_found = 0; + for (ptr_hook = weechat_hooks; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if ((ptr_hook->plugin == ptr_plugin) + && (ptr_hook->type == HOOK_TYPE_COMPLETION)) + { + if (!hook_found) + gui_chat_printf (NULL, + _(" completion hooked:")); + hook_found = 1; + gui_chat_printf (NULL, + " %s", + HOOK_COMPLETION(ptr_hook, completion)); + } + } } } } diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index a1db2b586..ebe656c39 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -827,6 +827,80 @@ hook_config_exec (char *type, char *option, char *value) } /* + * hook_completion: hook a completion + */ + +struct t_hook * +hook_completion (void *plugin, char *completion, + t_hook_callback_completion *callback, void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_completion *new_hook_completion; + + if (!completion || !completion[0] || strchr (completion, ' ')) + return NULL; + + new_hook = (struct t_hook *)malloc (sizeof (struct t_hook)); + if (!new_hook) + return NULL; + new_hook_completion = (struct t_hook_completion *)malloc (sizeof (struct t_hook_completion)); + if (!new_hook_completion) + { + free (new_hook); + return NULL; + } + + hook_init (new_hook, plugin, HOOK_TYPE_COMPLETION, callback_data); + + new_hook->hook_data = new_hook_completion; + new_hook_completion->callback = callback; + new_hook_completion->completion = strdup (completion); + + hook_add_to_list (new_hook); + + return new_hook; +} + +/* + * hook_completion_exec: execute completion hook + */ + +void +hook_completion_exec (void *plugin, char *completion, void *list) +{ + struct t_hook *ptr_hook, *next_hook; + + hook_exec_recursion++; + + ptr_hook = weechat_hooks; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if ((ptr_hook->type == HOOK_TYPE_COMPLETION) + && (!ptr_hook->running) + && (ptr_hook->plugin == plugin) + && (string_strcasecmp (HOOK_COMPLETION(ptr_hook, completion), + completion) == 0)) + { + ptr_hook->running = 1; + (void) (HOOK_COMPLETION(ptr_hook, callback)) + (ptr_hook->callback_data, completion, list); + if (ptr_hook->type == HOOK_TYPE_COMPLETION) + ptr_hook->running = 0; + } + + ptr_hook = next_hook; + } + + if (hook_exec_recursion > 0) + hook_exec_recursion--; + + if (hook_exec_recursion == 0) + hook_remove_deleted (); +} + +/* * unhook: unhook something */ @@ -894,6 +968,11 @@ unhook (struct t_hook *hook) free (HOOK_CONFIG(hook, option)); free ((struct t_hook_config *)hook->hook_data); break; + case HOOK_TYPE_COMPLETION: + if (HOOK_COMPLETION(hook, completion)) + free (HOOK_COMPLETION(hook, completion)); + free ((struct t_hook_completion *)hook->hook_data); + break; } hook->hook_data = NULL; } @@ -1021,6 +1100,13 @@ hook_print_log () log_printf (" type . . . . . . . . : '%s'", HOOK_CONFIG(ptr_hook, type)); log_printf (" option . . . . . . . : '%s'", HOOK_CONFIG(ptr_hook, option)); break; + case HOOK_TYPE_COMPLETION: + log_printf (" type . . . . . . . . . : %d (completion)", ptr_hook->type); + log_printf (" callback_data. . . . . : 0x%X", ptr_hook->callback_data); + log_printf (" completion data:"); + log_printf (" callback . . . . . . : 0x%X", HOOK_COMPLETION(ptr_hook, callback)); + log_printf (" completion . . . . . : '%s'", HOOK_COMPLETION(ptr_hook, completion)); + break; } log_printf (" running. . . . . . . . : %d", ptr_hook->running); log_printf (" prev_hook. . . . . . . : 0x%X", ptr_hook->prev_hook); diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index 7bf23300b..ceb49998a 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -31,6 +31,7 @@ enum t_hook_type HOOK_TYPE_PRINT, /* printed message */ HOOK_TYPE_EVENT, /* event */ HOOK_TYPE_CONFIG, /* config option */ + HOOK_TYPE_COMPLETION, /* custom completions */ }; #define HOOK_FD_FLAG_READ 1 @@ -43,6 +44,7 @@ enum t_hook_type #define HOOK_PRINT(hook, var) (((struct t_hook_print *)hook->hook_data)->var) #define HOOK_EVENT(hook, var) (((struct t_hook_event *)hook->hook_data)->var) #define HOOK_CONFIG(hook, var) (((struct t_hook_config *)hook->hook_data)->var) +#define HOOK_COMPLETION(hook, var) (((struct t_hook_completion *)hook->hook_data)->var) struct t_hook { @@ -121,6 +123,14 @@ struct t_hook_config /* (NULL = hook for all options) */ }; +typedef int (t_hook_callback_completion)(void *, char *, void *); + +struct t_hook_completion +{ + t_hook_callback_completion *callback; /* completion callback */ + char *completion; /* name of completion */ +}; + /* hook variables */ extern struct t_hook *weechat_hooks; @@ -149,6 +159,9 @@ extern void hook_event_exec (char *, void *); extern struct t_hook *hook_config (void *, char *, char *, t_hook_callback_config *, void *); extern void hook_config_exec (char *, char *, char *); +extern struct t_hook *hook_completion (void *, char *, + t_hook_callback_completion *, void *); +extern void hook_completion_exec (void *, char *, void *); extern void unhook (struct t_hook *); extern void unhook_all_plugin (void *); diff --git a/src/gui/gui-completion.c b/src/gui/gui-completion.c index 6598d8c3d..555404648 100644 --- a/src/gui/gui-completion.c +++ b/src/gui/gui-completion.c @@ -127,18 +127,14 @@ gui_completion_stop (struct t_gui_completion *completion) } /* - * gui_completion_get_command_infos: return completion template and max arg - * for command + * gui_completion_search_command: search command hook */ -void -gui_completion_get_command_infos (struct t_gui_completion *completion, - char **template) +struct t_hook * +gui_completion_search_command (struct t_gui_completion *completion) { struct t_hook *ptr_hook; - *template = NULL; - for (ptr_hook = weechat_hooks; ptr_hook; ptr_hook = ptr_hook->next_hook) { @@ -148,11 +144,11 @@ gui_completion_get_command_infos (struct t_gui_completion *completion, && (HOOK_COMMAND(ptr_hook, level) == 0) && (string_strcasecmp (HOOK_COMMAND(ptr_hook, command), completion->base_command) == 0)) - { - *template = HOOK_COMMAND(ptr_hook, completion); - return; - } + return ptr_hook; } + + /* command not found */ + return NULL; } /* @@ -862,13 +858,29 @@ gui_completion_list_add_weechat_cmd (struct t_gui_completion *completion) } /* + * gui_completion_custom: custom completion by a plugin + */ + +void +gui_completion_custom (struct t_gui_completion *completion, + char *custom_completion, + struct t_weechat_plugin *plugin) +{ + hook_completion_exec (plugin, + custom_completion, + completion->completion_list); +} + +/* * gui_completion_build_list_template: build data list according to a template */ void -gui_completion_build_list_template (struct t_gui_completion *completion, char *template) +gui_completion_build_list_template (struct t_gui_completion *completion, + char *template, + struct t_weechat_plugin *plugin) { - char *word, *pos; + char *word, *pos, *pos_end, *custom_completion; int word_offset; word = strdup (template); @@ -963,6 +975,25 @@ gui_completion_build_list_template (struct t_gui_completion *completion, char *t case 'w': /* WeeChat commands */ gui_completion_list_add_weechat_cmd (completion); break; + case '(': /* custom completion by a plugin */ + pos++; + pos_end = strchr (pos, ')'); + if (pos_end) + { + if (pos_end > pos) + { + custom_completion = strndup (pos, + pos_end - pos); + if (custom_completion) + { + gui_completion_custom (completion, + custom_completion, + plugin); + free (custom_completion); + } + } + pos = pos_end + 1; + } } } break; @@ -985,33 +1016,37 @@ gui_completion_build_list_template (struct t_gui_completion *completion, char *t void gui_completion_build_list (struct t_gui_completion *completion) { + struct t_hook *ptr_hook; char *template, *pos_template, *pos_space; int repeat_last, i, length; repeat_last = 0; - gui_completion_get_command_infos (completion, &template); - if (!template || (strcmp (template, "-") == 0)) + ptr_hook = gui_completion_search_command (completion); + if (!ptr_hook || !HOOK_COMMAND(ptr_hook, completion) + || (strcmp (HOOK_COMMAND(ptr_hook, completion), "-") == 0)) { gui_completion_stop (completion); return; } - - length = strlen (template); + + length = strlen (HOOK_COMMAND(ptr_hook, completion)); if (length >= 2) { - if (strcmp (template + length - 2, "%*") == 0) + if (strcmp (HOOK_COMMAND(ptr_hook, completion) + length - 2, + "%*") == 0) repeat_last = 1; } i = 1; - pos_template = template; + pos_template = HOOK_COMMAND(ptr_hook, completion); while (pos_template && pos_template[0]) { pos_space = strchr (pos_template, ' '); if (i == completion->base_command_arg) { - gui_completion_build_list_template (completion, pos_template); + gui_completion_build_list_template (completion, pos_template, + ptr_hook->plugin); return; } if (pos_space) @@ -1028,7 +1063,9 @@ gui_completion_build_list (struct t_gui_completion *completion) { pos_space = rindex (template, ' '); gui_completion_build_list_template (completion, - (pos_space) ? pos_space + 1 : template); + (pos_space) ? + pos_space + 1 : template, + ptr_hook->plugin); } } diff --git a/src/plugins/alias/alias.c b/src/plugins/alias/alias.c index cee9e7b22..b7a74be8e 100644 --- a/src/plugins/alias/alias.c +++ b/src/plugins/alias/alias.c @@ -43,6 +43,7 @@ struct t_alias *last_alias = NULL; struct t_hook *alias_command = NULL; struct t_hook *unalias_command = NULL; struct t_hook *config_reload = NULL; +struct t_hook *completion = NULL; /* @@ -691,6 +692,28 @@ unalias_command_cb (void *data, void *buffer, int argc, char **argv, } /* + * alias_completion_cb: callback for completion + */ + +int +alias_completion_cb (void *data, char *completion, void *list) +{ + struct t_alias *ptr_alias; + + /* make C compiler happy */ + (void) data; + (void) completion; + + for (ptr_alias = alias_list; ptr_alias; + ptr_alias = ptr_alias->next_alias) + { + weechat_list_add (list, ptr_alias->name, "sort"); + } + + return PLUGIN_RC_SUCCESS; +} + +/* * weechat_plugin_init: initialize alias plugin */ @@ -734,12 +757,15 @@ weechat_plugin_init (struct t_weechat_plugin *plugin) N_("alias_name"), N_("alias_name: name of alias to " "remove"), - "%h", + "%(alias)", unalias_command_cb, NULL); config_reload = weechat_hook_event ("config_reload", alias_config_reload_event_cb, NULL); + completion = weechat_hook_completion ("alias", + alias_completion_cb, NULL); + return PLUGIN_RC_SUCCESS; } @@ -756,6 +782,7 @@ weechat_plugin_end () weechat_unhook (alias_command); weechat_unhook (unalias_command); weechat_unhook (config_reload); + weechat_unhook (completion); return PLUGIN_RC_SUCCESS; } diff --git a/src/plugins/plugin-api.c b/src/plugins/plugin-api.c index 88b712983..d16e4e520 100644 --- a/src/plugins/plugin-api.c +++ b/src/plugins/plugin-api.c @@ -1186,6 +1186,21 @@ plugin_api_hook_config (struct t_weechat_plugin *plugin, char *config_type, } /* + * plugin_api_hook_completion: hook a completion + */ + +struct t_hook * +plugin_api_hook_completion (struct t_weechat_plugin *plugin, char *completion, + int (*callback)(void *, char *, void *), + void *data) +{ + if (plugin && callback) + return hook_completion (plugin, completion, callback, data); + + return NULL; +} + +/* * plugin_api_unhook: unhook something */ diff --git a/src/plugins/plugin-api.h b/src/plugins/plugin-api.h index d1ceda88d..7b0b83ae3 100644 --- a/src/plugins/plugin-api.h +++ b/src/plugins/plugin-api.h @@ -146,6 +146,10 @@ extern struct t_hook *plugin_api_hook_config (struct t_weechat_plugin *, char *, char *, int (*)(void *, char *, char *, char *), void *); +extern struct t_hook *plugin_api_hook_completion (struct t_weechat_plugin *, + char *, + int (*)(void *, char *, void *), + void *); extern void plugin_api_unhook (struct t_weechat_plugin *, void *); extern void plugin_api_unhook_all (struct t_weechat_plugin *); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 09b481734..f1057c3cf 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -289,6 +289,7 @@ plugin_load (char *filename) new_plugin->hook_print = &plugin_api_hook_print; new_plugin->hook_event = &plugin_api_hook_event; new_plugin->hook_config = &plugin_api_hook_config; + new_plugin->hook_completion = &plugin_api_hook_completion; new_plugin->unhook = &plugin_api_unhook; new_plugin->unhook_all = &plugin_api_unhook_all; diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index 115c9f032..3bdbc2b39 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -155,6 +155,9 @@ struct t_weechat_plugin struct t_hook *(*hook_config) (struct t_weechat_plugin *, char *, char *, int (*)(void *, char *, char *, char *), void *); + struct t_hook *(*hook_completion) (struct t_weechat_plugin *, char *, + int (*)(void *, char *, void *), + void *); void (*unhook) (struct t_weechat_plugin *, void *); void (*unhook_all) (struct t_weechat_plugin *); @@ -364,6 +367,9 @@ struct t_weechat_plugin #define weechat_hook_config(__type, __option, __callback, __data) \ weechat_plugin->hook_config(weechat_plugin, __type, __option, \ __callback, __data) +#define weechat_hook_completion(__completion, __callback, __data) \ + weechat_plugin->hook_completion(weechat_plugin, __completion, \ + __callback, __data) #define weechat_unhook(__hook) \ weechat_plugin->unhook(weechat_plugin, __hook) #define weechat_unhook_all() \ |