summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2023-09-04 23:15:29 +0200
committerSébastien Helleu <flashcode@flashtux.org>2023-10-17 18:14:53 +0200
commitbbf42a5d09687155f73daf2ff7ba73aa2e925f1c (patch)
tree8c91d1ffc1a9df3adfd5b365eb205175818a42fe /src
parente34071131ec31b53c9dc4491f9eb2aa546a23ac7 (diff)
downloadweechat-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.c240
-rw-r--r--src/core/hook/wee-hook-command.h1
-rw-r--r--src/core/wee-command.c11
-rw-r--r--src/core/wee-command.h3
-rw-r--r--src/core/wee-doc.c12
-rw-r--r--src/core/weechat.h1
-rw-r--r--src/plugins/weechat-plugin.h14
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) \