diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2013-08-04 08:56:56 +0200 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2013-08-04 08:56:56 +0200 |
commit | dc878c5b69d498e3edb225e1997455510579deed (patch) | |
tree | 2c6dbd6bb5640ce17d23b937463310656ec7f126 /src/core | |
parent | b94a1ce59baa99e2076c83d82f25cbe5d9a7c19b (diff) | |
download | weechat-dc878c5b69d498e3edb225e1997455510579deed.zip |
api: add argument "options" in function string_eval_expression, add option "-c" for command /eval (to evaluate a condition)
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/wee-command.c | 111 | ||||
-rw-r--r-- | src/core/wee-eval.c | 114 | ||||
-rw-r--r-- | src/core/wee-eval.h | 3 | ||||
-rw-r--r-- | src/core/wee-hdata.c | 20 | ||||
-rw-r--r-- | src/core/wee-string.c | 8 |
5 files changed, 189 insertions, 67 deletions
diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 6e0b88140..05116261b 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -1471,8 +1471,9 @@ COMMAND_CALLBACK(debug) COMMAND_CALLBACK(eval) { - int print_only, i; - char *result, *ptr_args, **commands; + int i, print_only, condition; + char *result, *ptr_args, *expr, **commands; + struct t_hashtable *options; /* make C compiler happy */ (void) buffer; @@ -1480,42 +1481,74 @@ COMMAND_CALLBACK(eval) (void) argv; print_only = 0; + condition = 0; if (argc < 2) return WEECHAT_RC_OK; ptr_args = argv_eol[1]; - if (string_strcasecmp (argv[1], "-n") == 0) + for (i = 1; i < argc; i++) { - print_only = 1; - ptr_args = argv_eol[2]; + if (string_strcasecmp (argv[i], "-n") == 0) + { + print_only = 1; + ptr_args = argv_eol[i + 1]; + } + else if (string_strcasecmp (argv[i], "-c") == 0) + { + condition = 1; + ptr_args = argv_eol[i + 1]; + } + else + { + ptr_args = argv_eol[i]; + break; + } } if (ptr_args) { - result = eval_expression (ptr_args, NULL, NULL); + options = NULL; + if (condition) + { + options = hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, + NULL); + if (options) + hashtable_set (options, "type", "condition"); + } + if (print_only) { - gui_chat_printf_date_tags (NULL, 0, "no_log", ">> %s", ptr_args); - if (result) + expr = string_remove_quotes (ptr_args, "\""); + if (expr) { - gui_chat_printf_date_tags (NULL, 0, "no_log", "== %s[%s%s%s]", - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), - GUI_COLOR(GUI_COLOR_CHAT), - result, - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); - } - else - { - gui_chat_printf_date_tags (NULL, 0, "no_log", "== %s<%s%s%s>", - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), - GUI_COLOR(GUI_COLOR_CHAT), - _("error"), - GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); + result = eval_expression (expr, NULL, NULL, options); + gui_chat_printf_date_tags (NULL, 0, "no_log", ">> %s", ptr_args); + if (result) + { + gui_chat_printf_date_tags (NULL, 0, "no_log", "== %s[%s%s%s]", + GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), + GUI_COLOR(GUI_COLOR_CHAT), + result, + GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); + } + else + { + gui_chat_printf_date_tags (NULL, 0, "no_log", "== %s<%s%s%s>", + GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), + GUI_COLOR(GUI_COLOR_CHAT), + _("error"), + GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS)); + } + free (expr); } } else { + result = eval_expression (ptr_args, NULL, NULL, options); if (result) { commands = string_split_command (result, ';'); @@ -1537,6 +1570,8 @@ COMMAND_CALLBACK(eval) } if (result) free (result); + if (options) + hashtable_free (options); } return WEECHAT_RC_OK; @@ -6314,9 +6349,11 @@ command_init () hook_command (NULL, "eval", N_("evaluate expression and send result to buffer"), N_("[-n] <expression>" - " || [-n] <expression1> <operator> <expression2>"), + " || [-n] -c <expression1> <operator> <expression2>"), N_(" -n: display result without sending it to buffer " "(debug mode)\n" + " -c: evaluate as condition: use operators and " + "parentheses, return a boolean value (\"0\" or \"1\")\n" "expression: expression to evaluate, variables with format " "${variable} are replaced (see below)\n" " operator: a logical or comparison operator:\n" @@ -6360,20 +6397,20 @@ command_init () "For name of hdata and variables, please look at \"Plugin " "API reference\", function \"weechat_hdata_get\".\n\n" "Examples:\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 ${window.buffer.number} > 2 ==> 0\n" - " /eval -n ${window.win_width} > 100 ==> 1\n" - " /eval -n (8 > 12) || (5 > 2) ==> 1\n" - " /eval -n (8 > 12) && (5 > 2) ==> 0\n" - " /eval -n abcd =~ ^ABC ==> 1\n" - " /eval -n abcd =~ (?-i)^ABC ==> 0\n" - " /eval -n abcd =~ (?-i)^abc ==> 1\n" - " /eval -n abcd !~ abc ==> 0"), - "-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 -c ${window.buffer.number} > 2 ==> 0\n" + " /eval -n -c ${window.win_width} > 100 ==> 1\n" + " /eval -n -c (8 > 12) || (5 > 2) ==> 1\n" + " /eval -n -c (8 > 12) && (5 > 2) ==> 0\n" + " /eval -n -c abcd =~ ^ABC ==> 1\n" + " /eval -n -c abcd =~ (?-i)^ABC ==> 0\n" + " /eval -n -c abcd =~ (?-i)^abc ==> 1\n" + " /eval -n -c abcd !~ abc ==> 0"), + "-n|-c -n|-c", &command_eval, NULL); hook_command (NULL, "filter", N_("filter messages in buffers, to hide/show them according " @@ -7089,7 +7126,7 @@ command_exec_list (const char *command_list) if (!command_list || !command_list[0]) return; - command_list2 = eval_expression (command_list, NULL, NULL); + command_list2 = eval_expression (command_list, NULL, NULL, NULL); if (command_list2 && command_list2[0]) { commands = string_split_command (command_list2, ';'); diff --git a/src/core/wee-eval.c b/src/core/wee-eval.c index 866f44f8c..3db3cc8c2 100644 --- a/src/core/wee-eval.c +++ b/src/core/wee-eval.c @@ -343,11 +343,14 @@ end: /* * Replaces variables in a string. + * + * Note: result must be freed after use. */ char * eval_replace_vars (const char *expr, struct t_hashtable *pointers, - struct t_hashtable *extra_vars) + struct t_hashtable *extra_vars, + const char *prefix, const char *suffix) { int errors; void *ptr[2]; @@ -355,7 +358,7 @@ eval_replace_vars (const char *expr, struct t_hashtable *pointers, ptr[0] = pointers; ptr[1] = extra_vars; - return string_replace_with_callback (expr, "${", "}", + return string_replace_with_callback (expr, prefix, suffix, &eval_replace_vars_cb, ptr, &errors); @@ -463,19 +466,21 @@ end: } /* - * Evaluates an expression (this function must not be called directly). + * Evaluates a condition (this function must not be called directly). * * Argument keep_parentheses is almost always 0, it is 1 only if the expression * is a regex (to keep flags inside the parentheses). * * For return value, see function eval_expression(). - * Note: result must be freed after use. + * + * Note: result must be freed after use (if not NULL). */ char * -eval_expression_internal (const char *expr, struct t_hashtable *pointers, - struct t_hashtable *extra_vars, - int keep_parentheses) +eval_expression_condition (const char *expr, struct t_hashtable *pointers, + struct t_hashtable *extra_vars, + int keep_parentheses, + const char *prefix, const char *suffix) { int logic, comp, length, level, rc; const char *pos_end; @@ -535,7 +540,9 @@ eval_expression_internal (const char *expr, struct t_hashtable *pointers, sub_expr = string_strndup (expr2 + 1, pos - expr2 - 1); if (!sub_expr) goto end; - tmp_value = eval_expression_internal (sub_expr, pointers, extra_vars, 0); + tmp_value = eval_expression_condition (sub_expr, pointers, + extra_vars, + 0, prefix, suffix); free (sub_expr); if (!pos[1]) { @@ -577,7 +584,9 @@ eval_expression_internal (const char *expr, struct t_hashtable *pointers, sub_expr = string_strndup (expr2, pos_end + 1 - expr2); if (!sub_expr) goto end; - tmp_value = eval_expression_internal (sub_expr, pointers, extra_vars, 0); + tmp_value = eval_expression_condition (sub_expr, pointers, + extra_vars, + 0, prefix, suffix); free (sub_expr); rc = eval_is_true (tmp_value); if (tmp_value) @@ -597,7 +606,8 @@ eval_expression_internal (const char *expr, struct t_hashtable *pointers, { pos++; } - tmp_value = eval_expression_internal (pos, pointers, extra_vars, 0); + tmp_value = eval_expression_condition (pos, pointers, extra_vars, + 0, prefix, suffix); rc = eval_is_true (tmp_value); if (tmp_value) free (tmp_value); @@ -626,16 +636,19 @@ eval_expression_internal (const char *expr, struct t_hashtable *pointers, sub_expr = string_strndup (expr2, pos_end + 1 - expr2); if (!sub_expr) goto end; - tmp_value = eval_expression_internal (sub_expr, pointers, extra_vars, 0); + tmp_value = eval_expression_condition (sub_expr, pointers, + extra_vars, + 0, prefix, suffix); free (sub_expr); pos += strlen (comparisons[comp]); while (pos[0] == ' ') { pos++; } - tmp_value2 = eval_expression_internal (pos, pointers, extra_vars, - ((comp == EVAL_COMPARE_REGEX_MATCHING) - || (comp == EVAL_COMPARE_REGEX_NOT_MATCHING)) ? 1 : 0); + tmp_value2 = eval_expression_condition (pos, pointers, extra_vars, + ((comp == EVAL_COMPARE_REGEX_MATCHING) + || (comp == EVAL_COMPARE_REGEX_NOT_MATCHING)) ? 1 : 0, + prefix, suffix); value = eval_compare (tmp_value, comp, tmp_value2); if (tmp_value) free (tmp_value); @@ -649,7 +662,7 @@ eval_expression_internal (const char *expr, struct t_hashtable *pointers, * at this point, there is no more logical operator neither comparison, * so we just replace variables in string and return the result */ - value = eval_replace_vars (expr2, pointers, extra_vars); + value = eval_replace_vars (expr2, pointers, extra_vars, prefix, suffix); end: if (expr2) @@ -663,37 +676,50 @@ end: * * The hashtable "pointers" must have string for keys, pointer for values. * The hashtable "extra_vars" must have string for keys and values. + * The hashtable "options" must have string for keys and values. * - * The expression can contain: + * Supported options: + * - prefix: change the default prefix before variables to replace ("${") + * - suffix: change the default suffix after variables to replace ('}") + * - type: + * - condition: evaluate as a condition (use operators/parentheses, + * return a boolean) + * + * If the expression is a condition, it can contain: * - conditions: == != < <= > >= * - logical operators: && || * - parentheses for priority * - * Examples (the [ ] are NOT part of result): + * Examples of simple expression without condition (the [ ] are NOT part of + * result): * >> ${window.buffer.number} * == [2] * >> buffer:${window.buffer.full_name} * == [buffer:irc.freenode.#weechat] - * >> ${window.buffer.full_name} == irc.freenode.#weechat - * == [1] - * >> ${window.buffer.full_name} == irc.freenode.#test - * == [0] * >> ${window.win_width} * == [112] * >> ${window.win_height} * == [40] + * + * Examples of conditions: + * >> ${window.buffer.full_name} == irc.freenode.#weechat + * == [1] + * >> ${window.buffer.full_name} == irc.freenode.#test + * == [0] * >> ${window.win_width} >= 30 && ${window.win_height} >= 20 * == [1] * - * Note: result must be freed after use. + * Note: result must be freed after use (if not NULL). */ char * eval_expression (const char *expr, struct t_hashtable *pointers, - struct t_hashtable *extra_vars) + struct t_hashtable *extra_vars, struct t_hashtable *options) { - int pointers_created, extra_vars_created; + int condition, pointers_created, extra_vars_created, rc; char *value; + const char *prefix, *suffix, *default_prefix = "${", *default_suffix = "}"; + const char *ptr_value; struct t_gui_window *window; if (!expr) @@ -702,6 +728,10 @@ eval_expression (const char *expr, struct t_hashtable *pointers, pointers_created = 0; extra_vars_created = 0; + condition = 0; + prefix = default_prefix; + suffix = default_suffix; + /* create hashtable pointers if it's NULL */ if (!pointers) { @@ -744,7 +774,41 @@ eval_expression (const char *expr, struct t_hashtable *pointers, extra_vars_created = 1; } - value = eval_expression_internal (expr, pointers, extra_vars, 0); + /* read options */ + if (options) + { + /* check the type of evaluation */ + ptr_value = hashtable_get (options, "type"); + if (ptr_value && (strcmp (ptr_value, "condition") == 0)) + condition = 1; + + /* check for custom prefix */ + ptr_value = hashtable_get (options, "prefix"); + if (ptr_value && ptr_value[0]) + prefix = ptr_value; + + /* check for custom suffix */ + ptr_value = hashtable_get (options, "suffix"); + if (ptr_value && ptr_value[0]) + suffix = ptr_value; + } + + /* evaluate expression */ + if (condition) + { + /* evaluate as condition (return a boolean: "0" or "1") */ + value = eval_expression_condition (expr, pointers, extra_vars, + 0, prefix, suffix); + rc = eval_is_true (value); + if (value) + free (value); + value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE); + } + else + { + /* only replace variables in expression */ + value = eval_replace_vars (expr, pointers, extra_vars, prefix, suffix); + } if (pointers_created) hashtable_free (pointers); diff --git a/src/core/wee-eval.h b/src/core/wee-eval.h index d768ff2cb..a570b57e6 100644 --- a/src/core/wee-eval.h +++ b/src/core/wee-eval.h @@ -50,6 +50,7 @@ enum t_eval_comparison extern int eval_is_true (const char *value); extern char *eval_expression (const char *expr, struct t_hashtable *pointers, - struct t_hashtable *extra_vars); + struct t_hashtable *extra_vars, + struct t_hashtable *options); #endif /* __WEECHAT_EVAL_H */ diff --git a/src/core/wee-hdata.c b/src/core/wee-hdata.c index 2e8fc1dfd..6391676e4 100644 --- a/src/core/wee-hdata.c +++ b/src/core/wee-hdata.c @@ -40,6 +40,7 @@ struct t_hashtable *weechat_hdata = NULL; /* hashtables used in hdata_search() for evaluating expression */ struct t_hashtable *hdata_search_pointers = NULL; struct t_hashtable *hdata_search_extra_vars = NULL; +struct t_hashtable *hdata_search_options = NULL; char *hdata_type_string[8] = { "other", "char", "integer", "long", "string", "pointer", "time", @@ -508,6 +509,17 @@ hdata_search (struct t_hdata *hdata, void *pointer, const char *search, int move NULL); } + if (!hdata_search_options) + { + hdata_search_options = hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (hdata_search_options) + hashtable_set (hdata_search_options, "type", "condition"); + } + while (pointer) { /* set pointer in hashtable (used for evaluating expression) */ @@ -515,7 +527,8 @@ hdata_search (struct t_hdata *hdata, void *pointer, const char *search, int move /* evaluate expression */ result = eval_expression (search, hdata_search_pointers, - hdata_search_extra_vars); + hdata_search_extra_vars, + hdata_search_options); rc = eval_is_true (result); if (result) free (result); @@ -1138,4 +1151,9 @@ hdata_end () hashtable_free (hdata_search_extra_vars); hdata_search_extra_vars = NULL; } + if (hdata_search_options) + { + hashtable_free (hdata_search_options); + hdata_search_options = NULL; + } } diff --git a/src/core/wee-string.c b/src/core/wee-string.c index 34ad3b1bb..0c95dadca 100644 --- a/src/core/wee-string.c +++ b/src/core/wee-string.c @@ -1656,7 +1656,7 @@ string_iconv (int from_utf8, const char *from_code, const char *to_code, /* * Converts a string to WeeChat internal storage charset (UTF-8). * - * Note: result has to be freed after use. + * Note: result must be freed after use. */ char * @@ -1696,7 +1696,7 @@ string_iconv_to_internal (const char *charset, const char *string) /* * Converts internal string to terminal charset, for display. * - * Note: result has to be freed after use. + * Note: result must be freed after use. */ char * @@ -1762,7 +1762,7 @@ string_iconv_fprintf (FILE *file, const char *data, ...) /* * Formats a string with size and unit name (bytes, KB, MB, GB). * - * Note: result has to be freed after use. + * Note: result must be freed after use. */ char * @@ -2099,6 +2099,8 @@ string_input_for_buffer (const char *string) * must be newly allocated because it will be freed in this function). * * Argument "errors" is set with number of keys not found by callback. + * + * Note: result must be freed after use. */ char * |