diff --git a/CHANGELOG.md b/CHANGELOG.md index 69b164a7a..af3eab441 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - relay: add option relay.network.websocket_permessage_deflate ([#1549](https://github.com/weechat/weechat/issues/1549)) - relay: add option relay.look.raw_messages_max_length ([#2122](https://github.com/weechat/weechat/issues/2122)) - relay: add infos "relay_api_version" and "relay_api_version_number" +- core: add hdata count in evaluation of expressions with `hdata_count:name[list]` or `hdata_count:name[pointer]` - core: add completion "bars_items" - api: add hashtable type "longlong" diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc index ab168ca69..353ea326c 100644 --- a/doc/en/weechat_plugin_api.en.adoc +++ b/doc/en/weechat_plugin_api.en.adoc @@ -2616,8 +2616,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" ==== string_eval_expression -_WeeChat ≥ 0.4.0, updated in 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, -2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.0.0, 4.2.0, 4.3.0._ +_WeeChat ≥ 0.4.0, updated in 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, 2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.0.0, 4.2.0, 4.3.0, 4.4.0._ Evaluate an expression and return result as a string. Special variables with format `+${variable}+` are expanded (see table below). @@ -3332,6 +3331,12 @@ expanded to last): | >> `+${define:len,${calc:5+3}}${len}x${len}+` + == `+8x8+` +| `+${hdata_count:name[list]}+` + + `+${hdata_count:name[pointer]}+` | 4.4.0 +| Number of items in a hdata list or starting at `pointer`. +| >> `+${hdata_count:buffer[gui_buffers]}+` + + == `+15+` + | `+${sec.data.name}+` | | Value of the secured data `name`. | >> `+${sec.data.libera_pass}+` + diff --git a/doc/fr/weechat_plugin_api.fr.adoc b/doc/fr/weechat_plugin_api.fr.adoc index f0ede7656..3d401eca7 100644 --- a/doc/fr/weechat_plugin_api.fr.adoc +++ b/doc/fr/weechat_plugin_api.fr.adoc @@ -2663,8 +2663,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" ==== string_eval_expression -_WeeChat ≥ 0.4.0, mis à jour dans la 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, -2.0, 2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.0.0, 4.2.0, 4.3.0._ +_WeeChat ≥ 0.4.0, mis à jour dans la 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, 2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.0.0, 4.2.0, 4.3.0, 4.4.0._ Évaluer l'expression et retourner le résultat sous forme de chaîne. Les variables spéciales avec le format `+${variable}+` sont étendues (voir le @@ -3390,6 +3389,12 @@ première étendue à la dernière) : | >> `+${define:len,${calc:5+3}}${len}x${len}+` + == `+8x8+` +| `+${hdata_count:name[list]}+` + + `+${hdata_count:name[pointer]}+` | 4.4.0 +| Nombre d'éléments dans la liste hdata ou en démarrant à `pointer`. +| >> `+${hdata_count:buffer[gui_buffers]}+` + + == `+15+` + | `+${sec.data.nom}+` | | Valeur de la donnée sécurisée `nom`. | >> `+${sec.data.libera_pass}+` + diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc index 5a064fceb..3e713489c 100644 --- a/doc/it/weechat_plugin_api.it.adoc +++ b/doc/it/weechat_plugin_api.it.adoc @@ -2772,8 +2772,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" // TRANSLATION MISSING ==== string_eval_expression -_WeeChat ≥ 0.4.0, updated in 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, -2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.0.0, 4.2.0, 4.3.0._ +_WeeChat ≥ 0.4.0, updated in 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, 2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.0.0, 4.2.0, 4.3.0, 4.4.0._ Evaluate an expression and return result as a string. Special variables with format `+${variable}+` are expanded (see table below). @@ -3487,6 +3486,12 @@ expanded to last): | >> `+${define:len,${calc:5+3}}${len}x${len}+` + == `+8x8+` +| `+${hdata_count:name[list]}+` + + `+${hdata_count:name[pointer]}+` | 4.4.0 +| Number of items in a hdata list or starting at `pointer`. +| >> `+${hdata_count:buffer[gui_buffers]}+` + + == `+15+` + | `+${sec.data.name}+` | | Value of the secured data `name`. | >> `+${sec.data.libera_pass}+` + diff --git a/doc/ja/weechat_plugin_api.ja.adoc b/doc/ja/weechat_plugin_api.ja.adoc index 7337c8d6a..779689848 100644 --- a/doc/ja/weechat_plugin_api.ja.adoc +++ b/doc/ja/weechat_plugin_api.ja.adoc @@ -2696,8 +2696,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" ==== string_eval_expression // TRANSLATION MISSING -_WeeChat ≥ 0.4.0, updated in 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, -2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.0.0, 4.2.0, 4.3.0._ +_WeeChat ≥ 0.4.0, updated in 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, 2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.0.0, 4.2.0, 4.3.0, 4.4.0._ 式を評価して文字列として返す。`+${variable}+` という書式で書かれた特殊変数は展開されます (以下の表を参照)。 @@ -3445,6 +3444,13 @@ str5 = weechat.string_eval_expression("password=abc password=def", {}, {}, optio | >> `+${define:len,${calc:5+3}}${len}x${len}+` + == `+8x8+` +// TRANSLATION MISSING +| `+${hdata_count:name[list]}+` + + `+${hdata_count:name[pointer]}+` | 4.4.0 +| Number of items in a hdata list or starting at `pointer`. +| >> `+${hdata_count:buffer[gui_buffers]}+` + + == `+15+` + | `+${sec.data.name}+` | | セキュアデータ `name` の値 | >> `+${sec.data.libera_pass}+` + diff --git a/doc/sr/weechat_plugin_api.sr.adoc b/doc/sr/weechat_plugin_api.sr.adoc index 6cbb5fb3c..bc0ac8f93 100644 --- a/doc/sr/weechat_plugin_api.sr.adoc +++ b/doc/sr/weechat_plugin_api.sr.adoc @@ -2529,7 +2529,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" ==== string_eval_expression -_WeeChat ≥ 0.4.0, ажурирано у верзијама 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, 2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6 и 3.8, 4.0.0, 4.2.0, 4.3.0._ +_WeeChat ≥ 0.4.0, ажурирано у верзијама 0.4.2, 0.4.3, 1.0, 1.1, 1.2, 1.3, 1.6, 1.8, 2.0, 2.2, 2.3, 2.7, 2.9, 3.1, 3.2, 3.3, 3.4, 3.6 и 3.8, 4.0.0, 4.2.0, 4.3.0, 4.4.0._ Израчунава израз и враћа вредност као стринг. Специјалне променљиве у формату `+${променљива}+` се развијају (погледајте табелу испод). @@ -3221,6 +3221,13 @@ str5 = weechat.string_eval_expression("password=abc password=def", {}, {}, optio | >> `+${define:len,${calc:5+3}}${len}x${len}+` + == `+8x8+` +// TRANSLATION MISSING +| `+${hdata_count:name[list]}+` + + `+${hdata_count:name[pointer]}+` | 4.4.0 +| Number of items in a hdata list or starting at `pointer`. +| >> `+${hdata_count:buffer[gui_buffers]}+` + + == `+15+` + | `+${sec.data.име}+` | | Вредност обезбеђених података `име`. | >> `+${sec.data.libera_pass}+` + diff --git a/src/core/core-completion.c b/src/core/core-completion.c index 3c2b7a2d8..af9b8c79e 100644 --- a/src/core/core-completion.c +++ b/src/core/core-completion.c @@ -2161,6 +2161,8 @@ completion_list_add_eval_variables_cb (const void *pointer, void *data, "${hdata[list].var1.var2}", "${hdata[ptr].var1.var2}", "${hdata[ptr_name].var1.var2}", + "${hdata_count:name[list]}", + "${hdata_count:name[ptr]}", "${hide:char,string}", "${hl:string}", "${if:condition?value_if_true:value_if_false}", diff --git a/src/core/core-eval.c b/src/core/core-eval.c index 01b215739..c653ab283 100644 --- a/src/core/core-eval.c +++ b/src/core/core-eval.c @@ -1134,6 +1134,87 @@ eval_string_define (const char *text, struct t_eval_context *eval_context) free (name); } +/* + * Returns count of items in a hdata, as a string. + * + * Note: result must be freed after use. + */ + +char * +eval_hdata_count (const char *text, struct t_eval_context *eval_context) +{ + struct t_hdata *hdata; + void *pointer; + char *pos1, *pos2, *value, *hdata_name, *pointer_name, str_count[64]; + int rc, count; + + value = NULL; + hdata_name = NULL; + pointer_name = NULL; + pointer = NULL; + + pos1 = strchr (text, '['); + if (!pos1) + goto end; + pos2 = strchr (pos1 + 1, ']'); + if (!pos2 || (pos2 == pos1 + 1)) + goto end; + + hdata_name = string_strndup (text, pos1 - text); + if (!hdata_name) + goto end; + + hdata = hook_hdata_get (NULL, hdata_name); + if (!hdata) + goto end; + + pointer_name = string_strndup (pos1 + 1, pos2 - pos1 - 1); + if (!pointer_name) + goto end; + + if (strncmp (pointer_name, "0x", 2) == 0) + { + rc = sscanf (pointer_name, "%p", &pointer); + if ((rc != EOF) && (rc != 0)) + { + if (!hdata_check_pointer (hdata, NULL, pointer)) + goto end; + } + else + goto end; + } + else + { + pointer = hdata_get_list (hdata, pointer_name); + if (!pointer) + { + pointer = hashtable_get (eval_context->pointers, pointer_name); + if (!pointer) + goto end; + if (!hdata_check_pointer (hdata, NULL, pointer)) + goto end; + } + } + + if (!pointer) + { + pointer = hashtable_get (eval_context->pointers, hdata_name); + if (!pointer) + goto end; + if (!hdata_check_pointer (hdata, NULL, pointer)) + goto end; + } + + count = hdata_count (hdata, pointer); + snprintf (str_count, sizeof (str_count), "%d", count); + value = strdup (str_count); + +end: + free (hdata_name); + free (pointer_name); + return (value) ? value : strdup ("0"); +} + /* * Gets value of hdata using "path" to a variable. * @@ -1588,6 +1669,8 @@ eval_syntax_highlight (const char *text, struct t_eval_context *eval_context) * - ${random:min,max}: a random integer number between "min" and "max" (inclusive) * - ${translate:string}: the translated string * - ${define:name,value}: declaration of a user variable (return an empty string) + * - ${hdata_count:name[list]}: number of items in this hdata with list + * - ${hdata_count:name[ptr]}: number of items in this hdata with pointer * - ${sec.data.xxx}: the value of the secured data "xxx" * - ${file.section.option}: the value of the config option * - ${name}: the local variable in buffer @@ -1930,6 +2013,13 @@ eval_replace_vars_cb (void *data, goto end; } + /* hdata count */ + if (strncmp (text, "hdata_count:", 12) == 0) + { + value = eval_hdata_count (text + 12, eval_context); + goto end; + } + /* option: if found, return this value */ if (strncmp (text, "sec.data.", 9) == 0) { diff --git a/tests/unit/core/test-core-eval.cpp b/tests/unit/core/test-core-eval.cpp index 1b9616d1e..2a2ad1f8d 100644 --- a/tests/unit/core/test-core-eval.cpp +++ b/tests/unit/core/test-core-eval.cpp @@ -454,6 +454,7 @@ TEST(CoreEval, EvalExpression) { struct t_hashtable *pointers, *extra_vars, *options; struct t_config_option *ptr_option; + struct t_gui_buffer *test_buffer; char *value, str_value[256], str_expr[256], *error; const char *ptr_debug_output; long number; @@ -996,6 +997,28 @@ TEST(CoreEval, EvalExpression) WEE_CHECK_EVAL("core", "${plugin}"); WEE_CHECK_EVAL("weechat", "${name}"); + /* test hdata count */ + WEE_CHECK_EVAL("0", "${hdata_count:}"); + WEE_CHECK_EVAL("0", "${hdata_count:xxx}"); + WEE_CHECK_EVAL("0", "${hdata_count:buffer[xxx]}"); + WEE_CHECK_EVAL("0", "${hdata_count:buffer[0x0]}"); + WEE_CHECK_EVAL("1", "${hdata_count:buffer[gui_buffers]}"); + snprintf (str_expr, sizeof (str_expr), + "${hdata_count:buffer[%p]}", gui_buffers); + WEE_CHECK_EVAL("1", str_expr); + test_buffer = gui_buffer_new (NULL, "test", + NULL, NULL, NULL, + NULL, NULL, NULL); + CHECK(test_buffer); + WEE_CHECK_EVAL("2", "${hdata_count:buffer[gui_buffers]}"); + snprintf (str_expr, sizeof (str_expr), + "${hdata_count:buffer[%p]}", gui_buffers); + WEE_CHECK_EVAL("2", "${hdata_count:buffer[gui_buffers]}"); + snprintf (str_expr, sizeof (str_expr), + "${hdata_count:buffer[%p]}", test_buffer); + WEE_CHECK_EVAL("1", str_expr); + gui_buffer_close (test_buffer); + /* test hdata */ hashtable_set (pointers, "my_null_pointer", (const void *)0x0); hashtable_set (pointers, "my_buffer_pointer", gui_buffers);