summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2013-08-04 08:56:56 +0200
committerSebastien Helleu <flashcode@flashtux.org>2013-08-04 08:56:56 +0200
commitdc878c5b69d498e3edb225e1997455510579deed (patch)
tree2c6dbd6bb5640ce17d23b937463310656ec7f126 /src/core
parentb94a1ce59baa99e2076c83d82f25cbe5d9a7c19b (diff)
downloadweechat-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.c111
-rw-r--r--src/core/wee-eval.c114
-rw-r--r--src/core/wee-eval.h3
-rw-r--r--src/core/wee-hdata.c20
-rw-r--r--src/core/wee-string.c8
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 *