diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2023-09-04 23:15:29 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2023-10-17 18:14:53 +0200 |
commit | bbf42a5d09687155f73daf2ff7ba73aa2e925f1c (patch) | |
tree | 8c91d1ffc1a9df3adfd5b365eb205175818a42fe /src | |
parent | e34071131ec31b53c9dc4491f9eb2aa546a23ac7 (diff) | |
download | weechat-bbf42a5d09687155f73daf2ff7ba73aa2e925f1c.zip |
api: add support of format/translation of command arguments description line by line (issue #2005)
Diffstat (limited to 'src')
-rw-r--r-- | src/core/hook/wee-hook-command.c | 240 | ||||
-rw-r--r-- | src/core/hook/wee-hook-command.h | 1 | ||||
-rw-r--r-- | src/core/wee-command.c | 11 | ||||
-rw-r--r-- | src/core/wee-command.h | 3 | ||||
-rw-r--r-- | src/core/wee-doc.c | 12 | ||||
-rw-r--r-- | src/core/weechat.h | 1 | ||||
-rw-r--r-- | src/plugins/weechat-plugin.h | 14 |
7 files changed, 268 insertions, 14 deletions
diff --git a/src/core/hook/wee-hook-command.c b/src/core/hook/wee-hook-command.c index 355b3c63a..3e985fa01 100644 --- a/src/core/hook/wee-hook-command.c +++ b/src/core/hook/wee-hook-command.c @@ -270,6 +270,236 @@ hook_command_build_completion (struct t_hook_command *hook_command) } /* + * Removes all raw markers from a string: converts "raw[xxx]" to "xxx". + * + * Note: result must be freed after use. + */ + +char * +hook_command_remove_raw_markers (const char *string) +{ + const char *ptr_string, *pos_raw, *pos_end; + char **result; + + if (!string) + return NULL; + + result = string_dyn_alloc (128); + if (!result) + return NULL; + + ptr_string = string; + + while (ptr_string[0]) + { + pos_raw = strstr (ptr_string, "raw["); + if (!pos_raw) + { + string_dyn_concat (result, ptr_string, -1); + break; + } + pos_end = strchr (pos_raw, ']'); + if (!pos_end) + { + string_dyn_concat (result, ptr_string, -1); + break; + } + if (pos_raw > ptr_string) + string_dyn_concat (result, ptr_string, pos_raw - ptr_string); + if (pos_end > pos_raw + 4) + string_dyn_concat (result, pos_raw + 4, pos_end - pos_raw - 4); + ptr_string = pos_end + 1; + } + + return string_dyn_free (result, 0); +} + +/* + * Frees an argument description. + */ + +void +hook_command_arraylist_arg_desc_free (void *data, struct t_arraylist *arraylist, + void *pointer) +{ + /* make C compiler happy */ + (void) data; + (void) arraylist; + + free (pointer); +} + +/* + * Formats and translates arguments description of a command. + * + * Note: result must be freed after use. + */ + +char * +hook_command_format_args_description (const char *args_description) +{ + struct t_arraylist *args; + const char *pos, *ptr_line; + char **lines, **result, *arg_translated, *arg_name, *line_translated; + int i, j, num_lines, length, max_length_arg, size, line_after_args; + int lines_added; + + if (!args_description) + return NULL; + + if (!args_description[0]) + return strdup (args_description); + + /* if args description is not formatted, translate the whole string */ + if (strncmp (args_description, + WEECHAT_HOOK_COMMAND_STR_FORMATTED "\n", + strlen (WEECHAT_HOOK_COMMAND_STR_FORMATTED) + 1) != 0) + { + return strdup (_(args_description)); + } + + /* translate line by line and indent properly arguments */ + result = NULL; + lines = NULL; + args = NULL; + + result = string_dyn_alloc (1024); + if (!result) + goto error; + + lines = string_split (args_description, "\n", NULL, 0, 0, &num_lines); + if (!lines) + goto error; + + if (num_lines == 0) + { + string_free_split (lines); + return string_dyn_free (result, 0); + } + + args = arraylist_new (num_lines, 0, 1, + NULL, NULL, + &hook_command_arraylist_arg_desc_free, NULL); + if (!args) + goto error; + + /* store description of arguments and find longest argument name on screen */ + line_after_args = -1; + max_length_arg = 0; + for (i = 0; i < num_lines; i++) + { + if (!lines[i][0]) + { + line_after_args = i; + break; + } + if (strcmp (lines[i], WEECHAT_HOOK_COMMAND_STR_FORMATTED) == 0) + continue; + arg_translated = hook_command_remove_raw_markers (_(lines[i])); + if (!arg_translated) + continue; + arraylist_add (args, arg_translated); + if ((strncmp (arg_translated, "> ", 2) == 0) + || (strncmp (arg_translated, ">> ", 3) == 0)) + continue; + pos = strchr (arg_translated, ':'); + if (!pos) + continue; + arg_name = string_strndup (arg_translated, pos - arg_translated); + if (arg_name) + { + length = utf8_strlen_screen (arg_name); + if (length > max_length_arg) + max_length_arg = length; + free (arg_name); + } + } + + /* add arguments with their description */ + lines_added = 0; + size = arraylist_size (args); + for (i = 0; i < size; i++) + { + ptr_line = (const char *)arraylist_get (args, i); + if (!ptr_line) + continue; + if (lines_added > 0) + string_dyn_concat (result, "\n", -1); + if (strncmp (ptr_line, "> ", 2) == 0) + { + /* indented line: after the argument name */ + for (j = 0; j < max_length_arg + 2; j++) + { + string_dyn_concat (result, " ", -1); + } + ptr_line += 2; + } + else if (strncmp (ptr_line, ">> ", 3) == 0) + { + /* indented line: after the argument name (+ 2 spaces) */ + for (j = 0; j < max_length_arg + 4; j++) + { + string_dyn_concat (result, " ", -1); + } + ptr_line += 3; + } + else + { + pos = strchr (ptr_line, ':'); + if (pos) + { + arg_name = string_strndup (ptr_line, pos - ptr_line); + if (arg_name) + { + length = utf8_strlen_screen (arg_name); + for (j = length; j < max_length_arg; j++) + { + string_dyn_concat (result, " ", -1); + } + free (arg_name); + } + } + } + string_dyn_concat (result, ptr_line, -1); + lines_added++; + } + + /* add additional description (after arguments) */ + if (line_after_args >= 0) + { + for (i = line_after_args; i < num_lines; i++) + { + if (lines_added > 0) + string_dyn_concat (result, "\n", -1); + if (lines[i][0]) + { + line_translated = hook_command_remove_raw_markers (_(lines[i])); + if (line_translated) + { + string_dyn_concat (result, line_translated, -1); + lines_added++; + free (line_translated); + } + } + } + } + + arraylist_free (args); + string_free_split (lines); + + return string_dyn_free (result, 0); + +error: + if (args) + arraylist_free (args); + if (result) + string_dyn_free (result, 1); + if (lines) + string_free_split (lines); + return NULL; +} + +/* * Hooks a command. * * Returns pointer to new hook, NULL if error. @@ -820,6 +1050,8 @@ int hook_command_add_to_infolist (struct t_infolist_item *item, struct t_hook *hook) { + char *args_desc_nls; + if (!item || !hook || !hook->hook_data) return 0; @@ -846,11 +1078,13 @@ hook_command_add_to_infolist (struct t_infolist_item *item, if (!infolist_new_var_string (item, "args_description", HOOK_COMMAND(hook, args_description))) return 0; + args_desc_nls = hook_command_format_args_description ( + HOOK_COMMAND(hook, args_description)); if (!infolist_new_var_string (item, "args_description_nls", - (HOOK_COMMAND(hook, args_description) - && HOOK_COMMAND(hook, args_description)[0]) ? - _(HOOK_COMMAND(hook, args_description)) : "")) + (args_desc_nls) ? args_desc_nls : "")) return 0; + if (args_desc_nls) + free (args_desc_nls); if (!infolist_new_var_string (item, "completion", HOOK_COMMAND(hook, completion))) return 0; diff --git a/src/core/hook/wee-hook-command.h b/src/core/hook/wee-hook-command.h index ab56ee3b0..83ca8340e 100644 --- a/src/core/hook/wee-hook-command.h +++ b/src/core/hook/wee-hook-command.h @@ -76,6 +76,7 @@ struct t_hook_command_similar }; extern char *hook_command_get_description (struct t_hook *hook); +extern char *hook_command_format_args_description (const char *args_description); extern struct t_hook *hook_command (struct t_weechat_plugin *plugin, const char *command, const char *description, diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 6becca420..b4d7ce9bc 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -3006,7 +3006,7 @@ COMMAND_CALLBACK(help) struct t_weechat_plugin *ptr_plugin; struct t_config_option *ptr_option; int i, length, command_found, first_line_displayed, verbose; - char *string, *ptr_string, *pos_double_pipe, *pos_end; + char *string, *ptr_string, *pos_double_pipe, *pos_end, *args_desc; char empty_string[1] = { '\0' }, str_format[64]; /* make C compiler happy */ @@ -3121,12 +3121,13 @@ COMMAND_CALLBACK(help) gui_chat_printf (NULL, "%s", _(HOOK_COMMAND(ptr_hook, description))); } - if (HOOK_COMMAND(ptr_hook, args_description) - && HOOK_COMMAND(ptr_hook, args_description)[0]) + args_desc = hook_command_format_args_description ( + HOOK_COMMAND(ptr_hook, args_description)); + if (args_desc) { gui_chat_printf (NULL, ""); - gui_chat_printf (NULL, "%s", - _(HOOK_COMMAND(ptr_hook, args_description))); + gui_chat_printf (NULL, "%s", args_desc); + free (args_desc); } } } diff --git a/src/core/wee-command.h b/src/core/wee-command.h index 580c0eb1d..8cc04c6d8 100644 --- a/src/core/wee-command.h +++ b/src/core/wee-command.h @@ -82,6 +82,9 @@ struct t_gui_buffer; return WEECHAT_RC_ERROR; \ } +#define CMD_ARGS_DESC(args...) \ + STR_CONCAT("\n", WEECHAT_HOOK_COMMAND_STR_FORMATTED, ##args) + struct t_command_repeat { char *buffer_name; /* full buffer name */ diff --git a/src/core/wee-doc.c b/src/core/wee-doc.c index 942a41a03..c6f008b74 100644 --- a/src/core/wee-doc.c +++ b/src/core/wee-doc.c @@ -256,7 +256,7 @@ doc_gen_user_commands (const char *path, const char *lang) struct t_hook *ptr_hook; struct t_arraylist *list_hooks; int i, list_size, length, first_cmd_plugin, first_line; - char old_plugin[1024], format[32], *value; + char old_plugin[1024], format[32], *value, *args_desc; const char *ptr_args, *pos_pipes, *pos_next; file = doc_gen_open_file (path, "user", "commands", lang); @@ -365,12 +365,12 @@ doc_gen_user_commands (const char *path, const char *lang) } ptr_args = pos_next; } - if (HOOK_COMMAND(ptr_hook, args_description) - && HOOK_COMMAND(ptr_hook, args_description[0])) + args_desc = hook_command_format_args_description ( + HOOK_COMMAND(ptr_hook, args_description)); + if (args_desc) { - string_fprintf (file, - "\n%s\n", - TRANS(HOOK_COMMAND(ptr_hook, args_description))); + string_fprintf (file, "\n%s\n", args_desc); + free (args_desc); } } diff --git a/src/core/weechat.h b/src/core/weechat.h index af2ee8994..33551d37c 100644 --- a/src/core/weechat.h +++ b/src/core/weechat.h @@ -48,6 +48,7 @@ #define N_(string) (string) #define gettext(string) (string) #endif /* !defined(_) */ +#define AI(string) (string) #define WEECHAT_COPYRIGHT_DATE "(C) 2003-2023" diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index e976760bf..e7a1c10f9 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -221,6 +221,19 @@ struct timeval; weechat_string_concat (separator, ##argz, NULL) /* + * string used at beginning of arguments description to format the help text + * and translate it line by line + */ +#define WEECHAT_HOOK_COMMAND_STR_FORMATTED "[fmt]" + +/* macro to concatenate strings for description of command arguments */ +#define WEECHAT_CMD_ARGS_DESC(args...) \ + WEECHAT_STR_CONCAT( \ + "\n", \ + WEECHAT_HOOK_COMMAND_STR_FORMATTED, \ + ##args) + +/* * macro to return error in case of missing arguments in callback of * hook_command */ @@ -1248,6 +1261,7 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); #define NG_(single,plural,number) \ (weechat_plugin->ngettext)(single, plural, number) #endif /* NG_ */ +#define AI(string) (string) #endif /* WEECHAT_H */ #define weechat_gettext(string) (weechat_plugin->gettext)(string) #define weechat_ngettext(single,plural,number) \ |