diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc index 1435ec9d3..a3b06c23e 100644 --- a/doc/en/weechat_plugin_api.en.adoc +++ b/doc/en/weechat_plugin_api.en.adoc @@ -1955,7 +1955,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" ==== string_eval_expression -_WeeChat ≥ 0.4.0, updated in 0.4.2, 1.0, 1.1, 1.2 and 1.3._ +_WeeChat ≥ 0.4.0, updated in 0.4.2, 1.0, 1.1, 1.2, 1.3 and 1.8._ Evaluate an expression and return result as a string. Special variables with format `+${variable}+` are expanded (see table below). @@ -2079,6 +2079,16 @@ expanded to last): `+${env:HOME}+` | `+/home/user+` +| `+${if:condition}+` + + `+${if:condition?true}+` + `+${if:condition?true:false}+` + (_WeeChat ≥ 1.8_) | + Ternary operator with a condition, a value if the condition is true (optional) + and another value if the condition is false (optional). If values are not + given, "1" or "0" are returned, according to the result of the condition. | + `+${if:${info:term_width}>80?big:small}+` | + `+big+` + | `+${sec.data.name}+` | Value of the secured data `name`. | `+${sec.data.freenode_pass}+` | diff --git a/doc/fr/weechat_plugin_api.fr.adoc b/doc/fr/weechat_plugin_api.fr.adoc index b6f3163aa..e97bacc02 100644 --- a/doc/fr/weechat_plugin_api.fr.adoc +++ b/doc/fr/weechat_plugin_api.fr.adoc @@ -1991,7 +1991,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" ==== string_eval_expression -_WeeChat ≥ 0.4.0, mis à jour dans la 0.4.2, 1.0, 1.1, 1.2 et 1.3._ +_WeeChat ≥ 0.4.0, mis à jour dans la 0.4.2, 1.0, 1.1, 1.2, 1.3 et 1.8._ É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 @@ -2121,6 +2121,17 @@ première étendue à la dernière) : `+${env:HOME}+` | `+/home/user+` +| `+${if:condition}+` + + `+${if:condition?vrai}+` + `+${if:condition?vrai:faux}+` + + (_WeeChat ≥ 1.8_) | + Opérateur ternaire avec une condition, une valeur si la condition est vraie + (optionnelle) et une autre valeur si la condition est fausse (optionnelle). + Si les valeurs ne sont pas données, "1" ou "0" est retourné, selon le résultat + de la condition. | + `+${if:${info:term_width}>80?grand:petit}+` | + `+grand+` + | `+${sec.data.nom}+` | Valeur de la donnée sécurisée `nom`. | `+${sec.data.freenode_pass}+` | diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc index 1727ba6f5..0b208b799 100644 --- a/doc/it/weechat_plugin_api.it.adoc +++ b/doc/it/weechat_plugin_api.it.adoc @@ -2027,7 +2027,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" ==== string_eval_expression // TRANSLATION MISSING -_WeeChat ≥ 0.4.0, updated in 0.4.2, 1.0, 1.1, 1.2 and 1.3._ +_WeeChat ≥ 0.4.0, updated in 0.4.2, 1.0, 1.1, 1.2, 1.3 and 1.8._ // TRANSLATION MISSING Evaluate an expression and return result as a string. @@ -2098,7 +2098,6 @@ expanded to last): `+${name}+` | `+value+` -// TRANSLATION MISSING | `+${eval:xxx}+` + (_WeeChat ≥ 1.3_) | String to evaluate. | @@ -2141,7 +2140,6 @@ expanded to last): `+1.0+` + `+lightblue+` -// TRANSLATION MISSING | `+${date}+` + `+${date:xxx}+` + (_WeeChat ≥ 1.3_) | @@ -2158,6 +2156,16 @@ expanded to last): `+${env:HOME}+` | `+/home/user+` +| `+${if:condition}+` + + `+${if:condition?true}+` + `+${if:condition?true:false}+` + + (_WeeChat ≥ 1.8_) | + Ternary operator with a condition, a value if the condition is true (optional) + and another value if the condition is false (optional). If values are not + given, "1" or "0" are returned, according to the result of the condition. | + `+${if:${info:term_width}>80?big:small}+` | + `+big+` + | `+${sec.data.name}+` | Value of the secured data `name`. | `+${sec.data.freenode_pass}+` | diff --git a/doc/ja/weechat_plugin_api.ja.adoc b/doc/ja/weechat_plugin_api.ja.adoc index 452352b58..2746bc2c2 100644 --- a/doc/ja/weechat_plugin_api.ja.adoc +++ b/doc/ja/weechat_plugin_api.ja.adoc @@ -1961,7 +1961,7 @@ str3 = weechat.string_input_for_buffer("//test") # "/test" ==== string_eval_expression -_WeeChat バージョン 0.4.0 以上で利用可、バージョン 0.4.2、1.0、1.1、1.2、1.3 で更新。_ +_WeeChat バージョン 0.4.0 以上で利用可、バージョン 0.4.2、1.0、1.1、1.2、1.3、1.8 で更新。_ 式を評価して文字列として返す。`+${variable}+` という書式で書かれた特殊変数は展開されます (以下の表を参照)。 @@ -2085,6 +2085,17 @@ char *weechat_string_eval_expression (const char *expr, `+${env:HOME}+` | `+/home/user+` +// TRANSLATION MISSING +| `+${if:condition}+` + + `+${if:condition?true}+` + `+${if:condition?true:false}+` + + (_WeeChat ≥ 1.8_) | + Ternary operator with a condition, a value if the condition is true (optional) + and another value if the condition is false (optional). If values are not + given, "1" or "0" are returned, according to the result of the condition. | + `+${if:${info:term_width}>80?big:small}+` | + `+big+` + | `+${sec.data.name}+` | セキュアデータ `name` の値 | `+${sec.data.freenode_pass}+` | diff --git a/src/core/wee-command.c b/src/core/wee-command.c index be8e0f759..a6f03f3c0 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -7273,9 +7273,11 @@ command_init () "optional)\n" " 6. current date/time (format: \"date\" or \"date:format\")\n" " 7. an environment variable (format: \"env:XXX\")\n" - " 8. an option (format: \"file.section.option\")\n" - " 9. a local variable in buffer\n" - " 10. a hdata name/variable (the value is automatically converted " + " 8. a ternary operator (format: " + "if:condition?value_if_true:value_if_false)\n" + " 9. an option (format: \"file.section.option\")\n" + " 10. a local variable in buffer\n" + " 11. a hdata name/variable (the value is automatically converted " "to string), by default \"window\" and \"buffer\" point to current " "window/buffer.\n" "Format for hdata can be one of following:\n" @@ -7295,16 +7297,17 @@ command_init () "reference\", function \"weechat_hdata_get\".\n" "\n" "Examples (simple strings):\n" - " /eval -n ${info:version} ==> 0.4.3\n" - " /eval -n ${env:HOME} ==> /home/user\n" - " /eval -n ${weechat.look.scroll_amount} ==> 3\n" - " /eval -n ${window} ==> 0x2549aa0\n" - " /eval -n ${window.buffer} ==> 0x2549320\n" - " /eval -n ${window.buffer.full_name} ==> core.weechat\n" - " /eval -n ${window.buffer.number} ==> 1\n" - " /eval -n ${\\t} ==> \n" - " /eval -n ${hide:-,${relay.network.password}} ==> --------\n" - " /eval -n ${date:%H:%M:%S} ==> 07:46:40\n" + " /eval -n ${info:version} ==> 0.4.3\n" + " /eval -n ${env:HOME} ==> /home/user\n" + " /eval -n ${weechat.look.scroll_amount} ==> 3\n" + " /eval -n ${window} ==> 0x2549aa0\n" + " /eval -n ${window.buffer} ==> 0x2549320\n" + " /eval -n ${window.buffer.full_name} ==> core.weechat\n" + " /eval -n ${window.buffer.number} ==> 1\n" + " /eval -n ${\\t} ==> \n" + " /eval -n ${hide:-,${relay.network.password}} ==> --------\n" + " /eval -n ${date:%H:%M:%S} ==> 07:46:40\n" + " /eval -n ${if:${info:term_width}>80?big:small} ==> big\n" "\n" "Examples (conditions):\n" " /eval -n -c ${window.buffer.number} > 2 ==> 0\n" diff --git a/src/core/wee-eval.c b/src/core/wee-eval.c index 4a63b7ee4..eb332c8cd 100644 --- a/src/core/wee-eval.c +++ b/src/core/wee-eval.c @@ -49,10 +49,17 @@ char *logical_ops[EVAL_NUM_LOGICAL_OPS] = char *comparisons[EVAL_NUM_COMPARISONS] = { "=~", "!~", "==", "!=", "<=", "<", ">=", ">" }; + char *eval_replace_vars (const char *expr, struct t_hashtable *pointers, struct t_hashtable *extra_vars, int extra_vars_eval, const char *prefix, const char *suffix, struct t_eval_regex *eval_regex); +char *eval_expression_condition (const char *expr, + struct t_hashtable *pointers, + struct t_hashtable *extra_vars, + int extra_vars_eval, + const char *prefix, + const char *suffix); /* @@ -70,6 +77,66 @@ eval_is_true (const char *value) return (value && value[0] && (strcmp (value, "0") != 0)) ? 1 : 0; } +/* + * Searches a string in another at same level (skip sub-expressions between + * prefix/suffix). + * + * If escape is 1, the prefix can be escaped with '\' (and then is ignored). + * + * For example: eval_strstr_level ("(x || y) || z", "||") + * will return a pointer on "|| z" (because the first "||" is + * in a sub-expression, which is skipped). + * + * Returns pointer to string found, or NULL if not found. + */ + +const char * +eval_strstr_level (const char *string, const char *search, + const char *prefix, const char *suffix, int escape) +{ + const char *ptr_string; + int level, length_search, length_prefix, length_suffix; + + if (!string || !search) + return NULL; + + length_search = strlen (search); + length_prefix = strlen (prefix); + length_suffix = strlen (suffix); + + ptr_string = string; + level = 0; + while (ptr_string[0]) + { + if (escape && (ptr_string[0] == '\\') && (ptr_string[1] == prefix[0])) + { + ptr_string++; + } + else if (strncmp (ptr_string, prefix, length_prefix) == 0) + { + level++; + ptr_string += length_prefix; + } + else if (strncmp (ptr_string, suffix, length_suffix) == 0) + { + if (level > 0) + level--; + ptr_string += length_suffix; + } + else if ((level == 0) + && (strncmp (ptr_string, search, length_search) == 0)) + { + return ptr_string; + } + else + { + ptr_string++; + } + } + + return NULL; +} + /* * Gets value of hdata using "path" to a variable. * @@ -233,9 +300,10 @@ end: * 7. an info (format: info:name,arguments) * 8. current date/time (format: date or date:xxx) * 9. an environment variable (format: env:XXX) - * 10. an option (format: file.section.option) - * 11. a buffer local variable - * 12. a hdata variable (format: hdata.var1.var2 or hdata[list].var1.var2 + * 10. a ternary operator (format: if:condition?value_if_true:value_if_false) + * 11. an option (format: file.section.option) + * 12. a buffer local variable + * 13. a hdata variable (format: hdata.var1.var2 or hdata[list].var1.var2 * or hdata[ptr].var1.var2) * * See /help in WeeChat for examples. @@ -251,7 +319,7 @@ eval_replace_vars_cb (void *data, const char *text) struct t_config_option *ptr_option; struct t_gui_buffer *ptr_buffer; char str_value[512], *value, *pos, *pos1, *pos2, *hdata_name, *list_name; - char *tmp, *info_name, *hide_char, *hidden_string, *error; + char *tmp, *info_name, *hide_char, *hidden_string, *error, *condition; const char *prefix, *suffix, *ptr_value, *ptr_arguments, *ptr_string; struct t_hdata *hdata; void *pointer; @@ -410,7 +478,71 @@ eval_replace_vars_cb (void *data, const char *text) return strdup (ptr_value); } - /* 10. option: if found, return this value */ + /* 10: ternary operator: if:condition?value_if_true:value_if_false */ + if (strncmp (text, "if:", 3) == 0) + { + value = NULL; + pos = (char *)eval_strstr_level (text + 3, "?", prefix, suffix, 1); + pos2 = (pos) ? + (char *)eval_strstr_level (pos + 1, ":", prefix, suffix, 1) : NULL; + condition = (pos) ? + strndup (text + 3, pos - (text + 3)) : strdup (text + 3); + if (!condition) + return strdup (""); + tmp = eval_expression_condition (condition, pointers, + extra_vars, extra_vars_eval, + prefix, suffix); + rc = (tmp && strcmp (tmp, "1") == 0); + if (tmp) + free (tmp); + if (rc) + { + /* + * condition is true: return the "value_if_true" + * (or EVAL_STR_TRUE if value is missing) + */ + if (pos) + { + tmp = (pos2) ? + strndup (pos + 1, pos2 - pos - 1) : strdup (pos + 1); + if (tmp) + { + value = eval_replace_vars (tmp, pointers, + extra_vars, extra_vars_eval, + prefix, suffix, + eval_regex); + free (tmp); + } + } + else + { + value = strdup (EVAL_STR_TRUE); + } + } + else + { + /* + * condition is false: return the "value_if_false" + * (or EVAL_STR_FALSE if both values are missing) + */ + if (pos2) + { + value = eval_replace_vars (pos2 + 1, pointers, + extra_vars, extra_vars_eval, + prefix, suffix, + eval_regex); + } + else + { + if (!pos) + value = strdup (EVAL_STR_FALSE); + } + } + free (condition); + return (value) ? value : strdup (""); + } + + /* 11. option: if found, return this value */ if (strncmp (text, "sec.data.", 9) == 0) { ptr_value = hashtable_get (secure_hashtable_data, text + 9); @@ -443,7 +575,7 @@ eval_replace_vars_cb (void *data, const char *text) } } - /* 11. local variable in buffer */ + /* 12. local variable in buffer */ ptr_buffer = hashtable_get (pointers, "buffer"); if (ptr_buffer) { @@ -452,7 +584,7 @@ eval_replace_vars_cb (void *data, const char *text) return strdup (ptr_value); } - /* 12. hdata */ + /* 13. hdata */ value = NULL; hdata_name = NULL; list_name = NULL; @@ -536,6 +668,7 @@ eval_replace_vars (const char *expr, struct t_hashtable *pointers, struct t_eval_regex *eval_regex) { const void *ptr[6]; + const char *no_replace_prefix_list[] = { "if:", NULL }; ptr[0] = pointers; ptr[1] = extra_vars; @@ -545,6 +678,7 @@ eval_replace_vars (const char *expr, struct t_hashtable *pointers, ptr[5] = eval_regex; return string_replace_with_callback (expr, prefix, suffix, + no_replace_prefix_list, &eval_replace_vars_cb, ptr, NULL); } @@ -650,51 +784,6 @@ end: return strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE); } -/* - * Searches a string in another at same level (skip sub-expressions between - * parentheses). - * - * For example: eval_strstr_level ("(x || y) || z", "||") - * will return a pointer on "|| z" (because the first "||" is - * in a sub-expression, which is skipped). - * - * Returns pointer to string found, or NULL if not found. - */ - -const char * -eval_strstr_level (const char *string, const char *search) -{ - const char *ptr_string; - int level, length; - - if (!string || !search) - return NULL; - - length = strlen (search); - - ptr_string = string; - level = 0; - while (ptr_string[0]) - { - if (ptr_string[0] == '(') - { - level++; - } - else if (ptr_string[0] == ')') - { - if (level > 0) - level--; - } - - if ((level == 0) && (strncmp (ptr_string, search, length) == 0)) - return ptr_string; - - ptr_string++; - } - - return NULL; -} - /* * Evaluates a condition (this function must not be called directly). * @@ -751,7 +840,7 @@ eval_expression_condition (const char *expr, */ for (logic = 0; logic < EVAL_NUM_LOGICAL_OPS; logic++) { - pos = eval_strstr_level (expr2, logical_ops[logic]); + pos = eval_strstr_level (expr2, logical_ops[logic], "(", ")", 0); if (pos > expr2) { pos_end = pos - 1; @@ -804,7 +893,7 @@ eval_expression_condition (const char *expr, */ for (comp = 0; comp < EVAL_NUM_COMPARISONS; comp++) { - pos = eval_strstr_level (expr2, comparisons[comp]); + pos = eval_strstr_level (expr2, comparisons[comp], "(", ")", 0); if (pos > expr2) { pos_end = pos - 1; diff --git a/src/core/wee-string.c b/src/core/wee-string.c index 2c4711b09..cd21a94c7 100644 --- a/src/core/wee-string.c +++ b/src/core/wee-string.c @@ -2910,6 +2910,12 @@ string_input_for_buffer (const char *string) * * Nested variables are supported, for example: "${var1:${var2}}". * + * Argument "list_prefix_no_replace" is a list to prevent replacements in + * string if beginning with one of the prefixes. For example if the list is + * { "if:", NULL } and string is: "${if:cond?true:false}${test${abc}}" + * then the "if:cond?true:false" is NOT replaced (via a recursive call) but + * "test${abc}" will be replaced. + * * Argument "errors" (if not NULL) is set with number of keys not found by * callback. * @@ -2920,12 +2926,13 @@ char * string_replace_with_callback (const char *string, const char *prefix, const char *suffix, + const char **list_prefix_no_replace, char *(*callback)(void *data, const char *text), void *callback_data, int *errors) { int length_prefix, length_suffix, length, length_value, index_string; - int index_result, sub_count, sub_level, sub_errors; + int index_result, sub_count, sub_level, sub_errors, replace, i; char *result, *result2, *key, *key2, *value; const char *pos_end_name; @@ -2991,15 +2998,36 @@ string_replace_with_callback (const char *string, { if (sub_count > 0) { - sub_errors = 0; - key2 = string_replace_with_callback (key, prefix, - suffix, callback, - callback_data, - &sub_errors); - if (errors) - (*errors) += sub_errors; - free (key); - key = key2; + replace = 1; + if (list_prefix_no_replace) + { + for (i = 0; list_prefix_no_replace[i]; i++) + { + if (strncmp ( + key, list_prefix_no_replace[i], + strlen (list_prefix_no_replace[i])) == 0) + { + replace = 0; + break; + } + } + } + if (replace) + { + sub_errors = 0; + key2 = string_replace_with_callback ( + key, + prefix, + suffix, + list_prefix_no_replace, + callback, + callback_data, + &sub_errors); + if (errors) + (*errors) += sub_errors; + free (key); + key = key2; + } } value = (*callback) (callback_data, (key) ? key : ""); if (value) diff --git a/src/core/wee-string.h b/src/core/wee-string.h index bfed81411..c3d6b933e 100644 --- a/src/core/wee-string.h +++ b/src/core/wee-string.h @@ -110,6 +110,7 @@ extern const char *string_input_for_buffer (const char *string); extern char *string_replace_with_callback (const char *string, const char *prefix, const char *suffix, + const char **list_prefix_no_replace, char *(*callback)(void *data, const char *text), void *callback_data, int *errors); diff --git a/tests/unit/core/test-eval.cpp b/tests/unit/core/test-eval.cpp index b5bde750e..e2ecd401a 100644 --- a/tests/unit/core/test-eval.cpp +++ b/tests/unit/core/test-eval.cpp @@ -248,6 +248,17 @@ TEST(Eval, EvalExpression) LONGS_EQUAL(8, strlen (value)); free (value); + /* test ternary operator */ + WEE_CHECK_EVAL("1", "${if:5>2}"); + WEE_CHECK_EVAL("0", "${if:1>7}"); + WEE_CHECK_EVAL("yes", "${if:5>2?yes:no}"); + WEE_CHECK_EVAL("no", "${if:1>7?yes:no}"); + WEE_CHECK_EVAL("yes", "${if:5>2 && 6>3?yes:no}"); + WEE_CHECK_EVAL("yes-yes", "${if:5>2?${if:6>3?yes-yes:yes-no}:${if:9>4?no-yes:no-no}}"); + WEE_CHECK_EVAL("yes-no", "${if:5>2?${if:1>7?yes-yes:yes-no}:${if:9>4?no-yes:no-no}}"); + WEE_CHECK_EVAL("no-yes", "${if:1>7?${if:6>3?yes-yes:yes-no}:${if:9>4?no-yes:no-no}}"); + WEE_CHECK_EVAL("no-no", "${if:1>7?${if:1>7?yes-yes:yes-no}:${if:1>7?no-yes:no-no}}"); + /* test option */ snprintf (str_value, sizeof (str_value), "%d", CONFIG_INTEGER(config_look_scroll_amount)); diff --git a/tests/unit/core/test-string.cpp b/tests/unit/core/test-string.cpp index 4a9cab548..2a937b6a0 100644 --- a/tests/unit/core/test-string.cpp +++ b/tests/unit/core/test-string.cpp @@ -80,11 +80,12 @@ extern "C" #define WEE_REPLACE_CB(__result_replace, __result_errors, \ __str, __prefix, __suffix, \ + __list_prefix_no_replace, \ __callback, __callback_data, __errors) \ errors = -1; \ result = string_replace_with_callback ( \ - __str, __prefix, __suffix, __callback, __callback_data, \ - __errors); \ + __str, __prefix, __suffix, __list_prefix_no_replace, \ + __callback, __callback_data, __errors); \ if (__result_replace == NULL) \ { \ POINTERS_EQUAL(NULL, result); \ @@ -676,6 +677,9 @@ test_replace_cb (void *data, const char *text) if (strcmp (text, "xxx") == 0) return strdup (""); + if (strncmp (text, "no_replace:", 11) == 0) + return strdup (text); + return NULL; } @@ -734,48 +738,55 @@ TEST(String, ReplaceRegex) TEST(String, ReplaceWithCallback) { char *result; + const char *list_prefix_no_replace[] = { "no_replace:", NULL }; int errors; /* tests with invalid arguments */ - WEE_REPLACE_CB(NULL, -1, NULL, NULL, NULL, NULL, NULL, NULL); - WEE_REPLACE_CB(NULL, -1, "", NULL, NULL, NULL, NULL, NULL); - WEE_REPLACE_CB(NULL, -1, NULL, "", NULL, NULL, NULL, NULL); - WEE_REPLACE_CB(NULL, -1, NULL, NULL, "", NULL, NULL, NULL); - WEE_REPLACE_CB(NULL, -1, NULL, NULL, NULL, &test_replace_cb, NULL, NULL); - WEE_REPLACE_CB(NULL, 0, NULL, NULL, NULL, NULL, NULL, &errors); - WEE_REPLACE_CB(NULL, -1, "test", NULL, NULL, NULL, NULL, NULL); - WEE_REPLACE_CB(NULL, -1, "test", "${", NULL, NULL, NULL, NULL); - WEE_REPLACE_CB(NULL, -1, "test", NULL, "}", NULL, NULL, NULL); - WEE_REPLACE_CB(NULL, -1, "test", NULL, NULL, &test_replace_cb, NULL, NULL); - WEE_REPLACE_CB(NULL, 0, "test", NULL, NULL, NULL, NULL, &errors); - WEE_REPLACE_CB(NULL, -1, "test", "${", "}", NULL, NULL, NULL); + WEE_REPLACE_CB(NULL, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + WEE_REPLACE_CB(NULL, -1, "", NULL, NULL, NULL, NULL, NULL, NULL); + WEE_REPLACE_CB(NULL, -1, NULL, "", NULL, NULL, NULL, NULL, NULL); + WEE_REPLACE_CB(NULL, -1, NULL, NULL, "", NULL, NULL, NULL, NULL); + WEE_REPLACE_CB(NULL, -1, NULL, NULL, NULL, NULL, &test_replace_cb, NULL, NULL); + WEE_REPLACE_CB(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, &errors); + WEE_REPLACE_CB(NULL, -1, "test", NULL, NULL, NULL, NULL, NULL, NULL); + WEE_REPLACE_CB(NULL, -1, "test", "${", NULL, NULL, NULL, NULL, NULL); + WEE_REPLACE_CB(NULL, -1, "test", NULL, "}", NULL, NULL, NULL, NULL); + WEE_REPLACE_CB(NULL, -1, "test", NULL, NULL, NULL, &test_replace_cb, NULL, NULL); + WEE_REPLACE_CB(NULL, 0, "test", NULL, NULL, NULL, NULL, NULL, &errors); + WEE_REPLACE_CB(NULL, -1, "test", "${", "}", NULL, NULL, NULL, NULL); /* valid arguments */ - WEE_REPLACE_CB("test", -1, "test", "${", "}", + WEE_REPLACE_CB("test", -1, "test", "${", "}", NULL, &test_replace_cb, NULL, NULL); - WEE_REPLACE_CB("test", 0, "test", "${", "}", + WEE_REPLACE_CB("test", 0, "test", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("test def", 0, "test ${abc}", "${", "}", + WEE_REPLACE_CB("test def", 0, "test ${abc}", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("test ", 0, "test ${xxx}", "${", "}", + WEE_REPLACE_CB("test ", 0, "test ${xxx}", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("test ${aaa}", 1, "test ${aaa}", "${", "}", + WEE_REPLACE_CB("test ${aaa}", 1, "test ${aaa}", "${", "}", NULL, &test_replace_cb, NULL, &errors); WEE_REPLACE_CB("test def ${aaa}", 1, "test ${abc} ${xxx} ${aaa}", - "${", "}", &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("test ", 1, "test ${abc", "${", "}", + "${", "}", NULL, &test_replace_cb, NULL, &errors); + WEE_REPLACE_CB("test ", 1, "test ${abc", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("test abc}", 0, "test abc}", "${", "}", + WEE_REPLACE_CB("test abc}", 0, "test abc}", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("test ${}", 1, "test ${}", "${", "}", + WEE_REPLACE_CB("test ${}", 1, "test ${}", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("test ${ }", 1, "test ${ }", "${", "}", + WEE_REPLACE_CB("test ${ }", 1, "test ${ }", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("def", 0, "${abc}", "${", "}", + WEE_REPLACE_CB("def", 0, "${abc}", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("", 0, "${xxx}", "${", "}", + WEE_REPLACE_CB("", 0, "${xxx}", "${", "}", NULL, &test_replace_cb, NULL, &errors); - WEE_REPLACE_CB("${aaa}", 1, "${aaa}", "${", "}", + WEE_REPLACE_CB("${aaa}", 1, "${aaa}", "${", "}", NULL, + &test_replace_cb, NULL, &errors); + WEE_REPLACE_CB("no_replace:def", 0, "${no_replace:${abc}}", "${", "}", + NULL, + &test_replace_cb, NULL, &errors); + WEE_REPLACE_CB("no_replace:${abc}", 0, "${no_replace:${abc}}", "${", "}", + list_prefix_no_replace, &test_replace_cb, NULL, &errors); }