summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/Makefile.am2
-rw-r--r--src/core/wee-command.c142
-rw-r--r--src/core/wee-config.c20
-rw-r--r--src/core/wee-eval.c717
-rw-r--r--src/core/wee-eval.h55
-rw-r--r--src/core/wee-string.c34
-rw-r--r--src/core/wee-string.h7
-rw-r--r--src/gui/gui-bar-item.c49
-rw-r--r--src/gui/gui-bar-item.h7
-rw-r--r--src/gui/gui-bar.c136
-rw-r--r--src/gui/gui-bar.h4
-rw-r--r--src/gui/gui-key.c30
-rw-r--r--src/plugins/guile/weechat-guile-api.c59
-rw-r--r--src/plugins/guile/weechat-guile.c38
-rw-r--r--src/plugins/guile/weechat-guile.h4
-rw-r--r--src/plugins/lua/weechat-lua-api.c57
-rw-r--r--src/plugins/lua/weechat-lua.c32
-rw-r--r--src/plugins/lua/weechat-lua.h4
-rw-r--r--src/plugins/perl/weechat-perl-api.c55
-rw-r--r--src/plugins/perl/weechat-perl.c25
-rw-r--r--src/plugins/perl/weechat-perl.h5
-rw-r--r--src/plugins/plugin-script.c2
-rw-r--r--src/plugins/plugin.c2
-rw-r--r--src/plugins/python/weechat-python-api.c58
-rw-r--r--src/plugins/python/weechat-python.c28
-rw-r--r--src/plugins/python/weechat-python.h4
-rw-r--r--src/plugins/ruby/weechat-ruby-api.c62
-rw-r--r--src/plugins/ruby/weechat-ruby.c31
-rw-r--r--src/plugins/ruby/weechat-ruby.h4
-rw-r--r--src/plugins/tcl/weechat-tcl-api.c60
-rw-r--r--src/plugins/tcl/weechat-tcl.c32
-rw-r--r--src/plugins/tcl/weechat-tcl.h4
-rw-r--r--src/plugins/weechat-plugin.h9
34 files changed, 1576 insertions, 203 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f5afb1803..984c5be15 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -27,6 +27,7 @@ wee-completion.c wee-completion.h
wee-config.c wee-config.h
wee-config-file.c wee-config-file.h
wee-debug.c wee-debug.h
+wee-eval.c wee-eval.h
wee-hashtable.c wee-hashtable.h
wee-hdata.c wee-hdata.h
wee-hook.c wee-hook.h
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index ae69f3ec0..6abf84b99 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -35,6 +35,8 @@ lib_weechat_core_a_SOURCES = weechat.c \
wee-config-file.h \
wee-debug.c \
wee-debug.h \
+ wee-eval.c \
+ wee-eval.h \
wee-hashtable.c \
wee-hashtable.h \
wee-hdata.c \
diff --git a/src/core/wee-command.c b/src/core/wee-command.c
index 99e26d7a4..c0fce2c86 100644
--- a/src/core/wee-command.c
+++ b/src/core/wee-command.c
@@ -39,6 +39,7 @@
#include "wee-config.h"
#include "wee-config-file.h"
#include "wee-debug.h"
+#include "wee-eval.h"
#include "wee-hashtable.h"
#include "wee-hdata.h"
#include "wee-hook.h"
@@ -1444,6 +1445,73 @@ COMMAND_CALLBACK(debug)
}
/*
+ * command_eval: evaluate expression and send result to buffer
+ */
+
+COMMAND_CALLBACK(eval)
+{
+ int print_only;
+ char *result, *ptr_args;
+
+ /* make C compiler happy */
+ (void) buffer;
+ (void) data;
+ (void) argv;
+
+ print_only = 0;
+
+ if (argc < 2)
+ return WEECHAT_RC_OK;
+
+ ptr_args = argv_eol[1];
+ if (string_strcasecmp (argv[1], "-n") == 0)
+ {
+ print_only = 1;
+ ptr_args = argv_eol[2];
+ }
+
+ if (ptr_args)
+ {
+ result = eval_expression (ptr_args, NULL, NULL);
+ if (print_only)
+ {
+ 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));
+ }
+ }
+ else
+ {
+ if (result)
+ input_data (buffer, result);
+ else
+ {
+ gui_chat_printf (NULL,
+ _("%sError in expression to evaluate"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]);
+ }
+ }
+ if (result)
+ free (result);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
* command_filter_display: display one filter
*/
@@ -5438,8 +5506,8 @@ command_init ()
hook_command (NULL, "bar",
N_("manage bars"),
N_("list|listfull|listitems"
- " || add <name> <type>[,<cond1>[,<cond2>...]] <position> "
- "<size> <separator> <item1>[,<item2>...]"
+ " || add <name> <type>[,<condition>] <position> <size> "
+ "<separator> <item1>[,<item2>...]"
" || default [input|title|status|nicklist]"
" || del <name>|-all"
" || set <name> <option> <value>"
@@ -5453,12 +5521,15 @@ command_init ()
" type: root: outside windows,\n"
" window: inside windows, with optional "
"conditions (see below)\n"
- " cond1,...: condition(s) for displaying bar (only for "
+ " condition: condition(s) for displaying bar (only for "
"type \"window\"):\n"
" active: on active window\n"
" inactive: on inactive windows\n"
" nicklist: on windows with nicklist\n"
- " without condition, bar is always displayed\n"
+ " other condition: see /help "
+ "weechat.bar.xxx.conditions and /help eval\n"
+ " without condition, the bar is always "
+ "displayed\n"
" position: bottom, top, left or right\n"
" size: size of bar (in chars)\n"
" separator: 1 for using separator (line), 0 or nothing "
@@ -5683,6 +5754,69 @@ command_init ()
" || term"
" || windows",
&command_debug, NULL);
+ hook_command (NULL, "eval",
+ N_("evaluate expression and send result to buffer"),
+ N_("[-n] <expression>"
+ " || [-n] <expression1> <operator> <expression2>"),
+ N_(" -n: display result without sending it to buffer "
+ "(debug mode)\n"
+ "expression: expression to evaluate, variables with format "
+ "${variable} are replaced (see below)\n"
+ " operator: a logical or comparison operator:\n"
+ " - logical operators:\n"
+ " && boolean \"and\"\n"
+ " || boolean \"or\"\n"
+ " - comparison operators:\n"
+ " == equal\n"
+ " != not equal\n"
+ " <= less or equal\n"
+ " < less\n"
+ " >= greater or equal\n"
+ " > greater\n"
+ " =~ is matching regex\n"
+ " !~ is NOT matching regex\n\n"
+ "An expression is considered as \"true\" if it is not NULL, "
+ "not empty, and different from \"0\".\n"
+ "The comparison is made using integers if the two "
+ "expressions are valid integers.\n"
+ "To force a string comparison, add double quotes around "
+ "each expression, for example:\n"
+ " 50 > 100 ==> 0\n"
+ " \"50\" > \"100\" ==> 1\n\n"
+ "Some variables are replaced in expression, using the "
+ "format ${variable}, variable can be, by order of prioity :\n"
+ " 1. the name of an option (file.section.option)\n"
+ " 2. 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"
+ " hdata.var1.var2...: start with a hdata (pointer must be "
+ "known), and ask variables one after one (other hdata can "
+ "be followed)\n"
+ " hdata(list).var1.var2...: start with a hdata using a "
+ "list, for example:\n"
+ " ${buffer[gui_buffers].full_name}: full name of first "
+ "buffer in linked list of buffers\n"
+ " ${plugin[weechat_plugins].name}: name of first plugin "
+ "in linked list of plugins\n"
+ "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",
+ &command_eval, NULL);
hook_command (NULL, "filter",
N_("filter messages in buffers, to hide/show them according "
"to tags or regex"),
diff --git a/src/core/wee-config.c b/src/core/wee-config.c
index 7070fe75f..390a75ba6 100644
--- a/src/core/wee-config.c
+++ b/src/core/wee-config.c
@@ -1163,6 +1163,16 @@ config_weechat_proxy_read_cb (void *data, struct t_config_file *config_file,
proxy_create_option_temp (ptr_temp_proxy, index_option,
value);
}
+ else
+ {
+ gui_chat_printf (NULL,
+ _("%sWarning: unknown option for "
+ "section \"%s\": %s (value: \"%s\")"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ section->name,
+ option_name,
+ value);
+ }
}
free (proxy_name);
@@ -1232,6 +1242,16 @@ config_weechat_bar_read_cb (void *data, struct t_config_file *config_file,
gui_bar_create_option_temp (ptr_temp_bar, index_option,
value);
}
+ else
+ {
+ gui_chat_printf (NULL,
+ _("%sWarning: unknown option for "
+ "section \"%s\": %s (value: \"%s\")"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ section->name,
+ option_name,
+ value);
+ }
}
free (bar_name);
diff --git a/src/core/wee-eval.c b/src/core/wee-eval.c
new file mode 100644
index 000000000..45b2e1f01
--- /dev/null
+++ b/src/core/wee-eval.c
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2012 Sebastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * wee-eval.c: evaluate expressions with references to internal vars
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+
+#include "weechat.h"
+#include "wee-eval.h"
+#include "wee-config-file.h"
+#include "wee-hashtable.h"
+#include "wee-hdata.h"
+#include "wee-hook.h"
+#include "wee-string.h"
+#include "../gui/gui-color.h"
+#include "../gui/gui-window.h"
+#include "../plugins/plugin.h"
+
+
+char *logical_ops[EVAL_NUM_LOGICAL_OPS] = { "&&", "||" };
+char *comparisons[EVAL_NUM_COMPARISONS] = { "==", "!=", "<=", "<", ">=", ">",
+ "=~", "!~" };
+
+
+/*
+ * eval_is_true: return 1 if value is true, 0 otherwise
+ * A value is true if string is non-NULL, non-empty and different
+ * from "0".
+ */
+
+int
+eval_is_true (const char *value)
+{
+ return (value && value[0] && (strcmp (value, "0") != 0)) ? 1 : 0;
+}
+
+/*
+ * eval_hdata_get_value: get value of hdata using "path" to a variable
+ * Note: result must be freed after use
+ */
+
+char *
+eval_hdata_get_value (struct t_hdata *hdata, void *pointer, const char *path)
+{
+ char *value, *old_value, *var_name, str_value[128], *pos;
+ const char *ptr_value, *hdata_name;
+ int type;
+ struct t_hashtable *hashtable;
+
+ value = NULL;
+ var_name = NULL;
+
+ /* NULL pointer? return empty string */
+ if (!pointer)
+ return strdup ("");
+
+ /* no path? just return current pointer as string */
+ if (!path || !path[0])
+ {
+ snprintf (str_value, sizeof (str_value),
+ "0x%lx", (long unsigned int)pointer);
+ return strdup (str_value);
+ }
+
+ /*
+ * look for name of hdata, for example in "window.buffer.full_name", the
+ * hdata name is "window"
+ */
+ pos = strchr (path, '.');
+ if (pos > path)
+ var_name = string_strndup (path, pos - path);
+ else
+ var_name = strdup (path);
+
+ if (!var_name)
+ goto end;
+
+ /* search type of variable in hdata */
+ type = hdata_get_var_type (hdata, var_name);
+ if (type < 0)
+ goto end;
+
+ /* build a string with the value or variable */
+ switch (type)
+ {
+ case WEECHAT_HDATA_CHAR:
+ snprintf (str_value, sizeof (str_value),
+ "%c", hdata_char (hdata, pointer, var_name));
+ value = strdup (str_value);
+ break;
+ case WEECHAT_HDATA_INTEGER:
+ snprintf (str_value, sizeof (str_value),
+ "%d", hdata_integer (hdata, pointer, var_name));
+ value = strdup (str_value);
+ break;
+ case WEECHAT_HDATA_LONG:
+ snprintf (str_value, sizeof (str_value),
+ "%ld", hdata_long (hdata, pointer, var_name));
+ value = strdup (str_value);
+ break;
+ case WEECHAT_HDATA_STRING:
+ value = strdup (hdata_string (hdata, pointer, var_name));
+ break;
+ case WEECHAT_HDATA_POINTER:
+ pointer = hdata_pointer (hdata, pointer, var_name);
+ snprintf (str_value, sizeof (str_value),
+ "0x%lx", (long unsigned int)pointer);
+ value = strdup (str_value);
+ break;
+ case WEECHAT_HDATA_TIME:
+ snprintf (str_value, sizeof (str_value),
+ "%ld", hdata_time (hdata, pointer, var_name));
+ value = strdup (str_value);
+ break;
+ case WEECHAT_HDATA_HASHTABLE:
+ pointer = hdata_hashtable (hdata, pointer, var_name);
+ if (pos)
+ {
+ /*
+ * for a hashtable, if there is a "." after name of hdata,
+ * get the value for this key in hashtable
+ */
+ hashtable = pointer;
+ ptr_value = hashtable_get (hashtable, pos + 1);
+ if (ptr_value)
+ {
+ switch (hashtable->type_values)
+ {
+ case HASHTABLE_INTEGER:
+ snprintf (str_value, sizeof (str_value),
+ "%d", *((int *)ptr_value));
+ value = strdup (str_value);
+ break;
+ case HASHTABLE_STRING:
+ value = strdup (ptr_value);
+ break;
+ case HASHTABLE_POINTER:
+ case HASHTABLE_BUFFER:
+ snprintf (str_value, sizeof (str_value),
+ "0x%lx", (long unsigned int)ptr_value);
+ value = strdup (str_value);
+ break;
+ case HASHTABLE_TIME:
+ snprintf (str_value, sizeof (str_value),
+ "%ld", *((time_t *)ptr_value));
+ value = strdup (str_value);
+ break;
+ case HASHTABLE_NUM_TYPES:
+ break;
+ }
+ }
+ }
+ else
+ {
+ snprintf (str_value, sizeof (str_value),
+ "0x%lx", (long unsigned int)pointer);
+ value = strdup (str_value);
+ }
+ break;
+ }
+
+ /*
+ * if we are on a pointer and that something else is in path (after "."),
+ * go on with this pointer and remaining path
+ */
+ if ((type == WEECHAT_HDATA_POINTER) && pos)
+ {
+ hdata_name = hdata_get_var_hdata (hdata, var_name);
+ if (!hdata_name)
+ goto end;
+
+ hdata = hook_hdata_get (NULL, hdata_name);
+ old_value = value;
+ value = eval_hdata_get_value (hdata, pointer, (pos) ? pos + 1 : NULL);
+ if (old_value)
+ free (old_value);
+ }
+
+end:
+ if (var_name)
+ free (var_name);
+
+ return value;
+}
+
+/*
+ * eval_replace_vars_cb: callback to replace variables, which can be,
+ * by order of priority:
+ * 1. an extra variable (from hashtable "extra_vars")
+ * 2. an name of option (file.section.option)
+ * 3. a hdata name/variable
+ * Examples:
+ * option: ${weechat.look.scroll_amount}
+ * hdata : ${window.buffer.full_name}
+ * ${window.buffer.local_variables.type}
+ */
+
+char *
+eval_replace_vars_cb (void *data, const char *text)
+{
+ struct t_hashtable *pointers, *extra_vars;
+ struct t_config_option *ptr_option;
+ char str_value[64], *value, *pos, *pos1, *pos2, *hdata_name, *list_name;
+ char *tmp;
+ const char *ptr_value;
+ struct t_hdata *hdata;
+ void *pointer;
+
+ pointers = (struct t_hashtable *)(((void **)data)[0]);
+ extra_vars = (struct t_hashtable *)(((void **)data)[1]);
+
+ /* first look for var in hashtable "extra_vars" */
+ ptr_value = hashtable_get (extra_vars, text);
+ if (ptr_value)
+ return strdup (ptr_value);
+
+ /* look for name of option: if found, return this value */
+ config_file_search_with_string (text, NULL, NULL, &ptr_option, NULL);
+ if (ptr_option)
+ {
+ switch (ptr_option->type)
+ {
+ case CONFIG_OPTION_TYPE_BOOLEAN:
+ return strdup (CONFIG_BOOLEAN(ptr_option) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
+ case CONFIG_OPTION_TYPE_INTEGER:
+ if (ptr_option->string_values)
+ return strdup (ptr_option->string_values[CONFIG_INTEGER(ptr_option)]);
+ snprintf (str_value, sizeof (str_value),
+ "%d", CONFIG_INTEGER(ptr_option));
+ return strdup (str_value);
+ case CONFIG_OPTION_TYPE_STRING:
+ return strdup (CONFIG_STRING(ptr_option));
+ case CONFIG_OPTION_TYPE_COLOR:
+ return strdup (gui_color_get_name (CONFIG_COLOR(ptr_option)));
+ case CONFIG_NUM_OPTION_TYPES:
+ return NULL;
+ }
+ }
+
+ /* look for hdata */
+ value = NULL;
+ hdata_name = NULL;
+ list_name = NULL;
+ pointer = NULL;
+
+ pos = strchr (text, '.');
+ if (pos > text)
+ hdata_name = string_strndup (text, pos - text);
+ else
+ hdata_name = strdup (text);
+
+ if (!hdata_name)
+ goto end;
+
+ pos1 = strchr (hdata_name, '[');
+ if (pos1 > hdata_name)
+ {
+ pos2 = strchr (pos1 + 1, ']');
+ if (pos2 > pos1 + 1)
+ {
+ list_name = string_strndup (pos1 + 1, pos2 - pos1 - 1);
+ }
+ tmp = string_strndup (hdata_name, pos1 - hdata_name);
+ if (tmp)
+ {
+ free (hdata_name);
+ hdata_name = tmp;
+ }
+ }
+
+ hdata = hook_hdata_get (NULL, hdata_name);
+ if (!hdata)
+ goto end;
+
+ if (list_name)
+ pointer = hdata_get_list (hdata, list_name);
+ if (!pointer)
+ {
+ pointer = hashtable_get (pointers, hdata_name);
+ if (!pointer)
+ goto end;
+ }
+
+ value = eval_hdata_get_value (hdata, pointer, (pos) ? pos + 1 : NULL);
+
+end:
+ if (hdata_name)
+ free (hdata_name);
+ if (list_name)
+ free (list_name);
+
+ return (value) ? value : strdup ("");
+}
+
+/*
+ * eval_replace_vars: replace variables in a string
+ */
+
+char *
+eval_replace_vars (const char *expr, struct t_hashtable *pointers,
+ struct t_hashtable *extra_vars)
+{
+ int errors;
+ void *ptr[2];
+
+ ptr[0] = pointers;
+ ptr[1] = extra_vars;
+
+ return string_replace_with_callback (expr,
+ &eval_replace_vars_cb,
+ ptr,
+ &errors);
+}
+
+/*
+ * eval_compare: compate two expressions
+ */
+
+char *
+eval_compare (const char *expr1, int comparison, const char *expr2)
+{
+ int rc, string_compare, length1, length2;
+ regex_t regex;
+ long value1, value2;
+ char *error;
+
+ rc = 0;
+ string_compare = 0;
+
+ if (!expr1 || !expr2)
+ goto end;
+
+ if ((comparison == EVAL_COMPARE_REGEX_MATCHING)
+ || (comparison == EVAL_COMPARE_REGEX_NOT_MATCHING))
+ {
+ if (string_regcomp (&regex, expr2,
+ REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
+ {
+ goto end;
+ }
+ rc = (regexec (&regex, expr1, 0, NULL, 0) == 0) ? 1 : 0;
+ if (comparison == EVAL_COMPARE_REGEX_NOT_MATCHING)
+ rc ^= 1;
+ goto end;
+ }
+
+ length1 = strlen (expr1);
+ length2 = strlen (expr2);
+
+ /*
+ * string comparison is forced if expr1 and expr2 have double quotes at
+ * beginning/end
+ */
+ if (((length1 == 0) || ((expr1[0] == '"') && expr1[length1 - 1] == '"'))
+ && ((length2 == 0) || ((expr2[0] == '"') && expr2[length2 - 1] == '"')))
+ {
+ string_compare = 1;
+ }
+
+ if (!string_compare)
+ {
+ value1 = strtol (expr1, &error, 10);
+ if (!error || error[0])
+ string_compare = 1;
+ else
+ {
+ value2 = strtol (expr2, &error, 10);
+ if (!error || error[0])
+ string_compare = 1;
+ }
+ }
+
+ if (string_compare)
+ rc = strcmp (expr1, expr2);
+ else
+ rc = (value1 < value2) ? -1 : ((value1 > value2) ? 1 : 0);
+
+ switch (comparison)
+ {
+ case EVAL_COMPARE_EQUAL:
+ rc = (rc == 0);
+ break;
+ case EVAL_COMPARE_NOT_EQUAL:
+ rc = (rc != 0);
+ break;
+ case EVAL_COMPARE_LESS_EQUAL:
+ rc = (rc <= 0);
+ break;
+ case EVAL_COMPARE_LESS:
+ rc = (rc < 0);
+ break;
+ case EVAL_COMPARE_GREATER_EQUAL:
+ rc = (rc >= 0);
+ break;
+ case EVAL_COMPARE_GREATER:
+ rc = (rc > 0);
+ break;
+ case EVAL_NUM_COMPARISONS:
+ break;
+ }
+
+end:
+ return strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
+}
+
+/*
+ * eval_expression_internal: evaluate an expression and return a string with
+ * the result (see function eval_expression())
+ * (should 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)
+ */
+
+char *
+eval_expression_internal (const char *expr, struct t_hashtable *pointers,
+ struct t_hashtable *extra_vars,
+ int keep_parentheses)
+{
+ int logic, comp, length, level, rc;
+ const char *pos_end;
+ char *expr2, *sub_expr, *pos, *value, *tmp_value, *tmp_value2;
+
+ value = NULL;
+
+ if (!expr)
+ return NULL;
+
+ if (!expr[0])
+ return strdup (expr);
+
+ /*
+ * skip spaces at beginning of string
+ */
+ while (expr[0] == ' ')
+ {
+ expr++;
+ }
+ if (!expr[0])
+ return strdup (expr);
+
+ /* skip spaces at end of string */
+ pos_end = expr + strlen (expr) - 1;
+ while ((pos_end > expr) && (pos_end[0] == ' '))
+ {
+ pos_end--;
+ }
+
+ expr2 = string_strndup (expr, pos_end + 1 - expr);
+ if (!expr2)
+ return NULL;
+
+ /* evaluate sub-expression in parentheses and replace it with value */
+ if (!keep_parentheses)
+ {
+ while (expr2[0] == '(')
+ {
+ level = 0;
+ pos = expr2 + 1;
+ while (pos[0])
+ {
+ if (pos[0] == '(')
+ level++;
+ else if (pos[0] == ')')
+ {
+ if (level == 0)
+ break;
+ level--;
+ }
+ pos++;
+ }
+ /* closing parenthese not found */
+ if (pos[0] != ')')
+ goto end;
+ 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);
+ free (sub_expr);
+ if (!pos[1])
+ {
+ /* nothing after ')', then return value of sub-expression as-is */
+ value = tmp_value;
+ goto end;
+ }
+ length = ((tmp_value) ? strlen (tmp_value) : 0) + 1 + strlen (pos + 1) + 1;
+ tmp_value2 = malloc (length);
+ if (!tmp_value2)
+ goto end;
+ tmp_value2[0] = '\0';
+ if (tmp_value)
+ strcat (tmp_value2, tmp_value);
+ strcat (tmp_value2, " ");
+ strcat (tmp_value2, pos + 1);
+ free (expr2);
+ expr2 = tmp_value2;
+ }
+ }
+
+ /*
+ * search for a logical operator, and if one is found:
+ * - split expression into two sub-expressions
+ * - evaluate first sub-expression
+ * - if needed, evaluate second sub-expression
+ * - return result
+ */
+ for (logic = 0; logic < EVAL_NUM_LOGICAL_OPS; logic++)
+ {
+ pos = strstr (expr2, logical_ops[logic]);
+ if (pos > expr2)
+ {
+ pos_end = pos - 1;
+ while ((pos_end > expr2) && (pos_end[0] == ' '))
+ {
+ pos_end--;
+ }
+ 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);
+ free (sub_expr);
+ rc = eval_is_true (tmp_value);
+ /*
+ * if rc == 0 with "&&" or rc == 1 with "||", no need to evaluate
+ * second sub-expression, just return the rc
+ */
+ if ((!rc && (logic == EVAL_LOGICAL_OP_AND))
+ || (rc && (logic == EVAL_LOGICAL_OP_OR)))
+ {
+ if (tmp_value)
+ free (tmp_value);
+ value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
+ goto end;
+ }
+ pos += strlen (logical_ops[logic]);
+ while (pos[0] == ' ')
+ {
+ pos++;
+ }
+ tmp_value = eval_expression_internal (pos, pointers, extra_vars, 0);
+ rc = eval_is_true (tmp_value);
+ if (tmp_value)
+ free (tmp_value);
+ value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
+ goto end;
+ }
+ }
+
+ /*
+ * search for a comparison, and if one is found:
+ * - split expression into two sub-expressions
+ * - evaluate the two sub-expressions
+ * - compare sub-expressions
+ * - return result
+ */
+ for (comp = 0; comp < EVAL_NUM_COMPARISONS; comp++)
+ {
+ pos = strstr (expr2, comparisons[comp]);
+ if (pos > expr2)
+ {
+ pos_end = pos - 1;
+ while ((pos_end > expr2) && (pos_end[0] == ' '))
+ {
+ pos_end--;
+ }
+ 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);
+ 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);
+ value = eval_compare (tmp_value, comp, tmp_value2);
+ if (tmp_value)
+ free (tmp_value);
+ if (tmp_value2)
+ free (tmp_value2);
+ goto end;
+ }
+ }
+
+ /*
+ * 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);
+
+end:
+ if (expr2)
+ free (expr2);
+
+ return value;
+}
+
+/*
+ * eval_expression: evaluate an expression and return a string with the result
+ * The hashtable "pointers" must have string for keys, pointer
+ * for values.
+ * The hashtable "extra_vars" must have string for keys and
+ * values.
+ * The expression can contain:
+ * - conditions: == != < <= > >=
+ * - logical operators: && ||
+ * - parentheses for priority
+ * Examples (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]
+ * >> ${window.win_width} >= 30 && ${window.win_height} >= 20
+ * == [1]
+ * Note: result must be freed after use
+ */
+
+char *
+eval_expression (const char *expr, struct t_hashtable *pointers,
+ struct t_hashtable *extra_vars)
+{
+ int pointers_created, extra_vars_created;
+ char *value;
+ struct t_gui_window *window;
+
+ if (!expr)
+ return NULL;
+
+ pointers_created = 0;
+ extra_vars_created = 0;
+
+ /* create hashtable pointers if it's NULL */
+ if (!pointers)
+ {
+ pointers = hashtable_new (16,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER,
+ NULL,
+ NULL);
+ if (!pointers)
+ return NULL;
+ pointers_created = 1;
+ }
+
+ /*
+ * set window/buffer with pointer to current window/buffer
+ * (if not already defined in the hashtable)
+ */
+ if (gui_current_window)
+ {
+ if (!hashtable_has_key (pointers, "window"))
+ hashtable_set (pointers, "window", gui_current_window);
+ if (!hashtable_has_key (pointers, "buffer"))
+ {
+ window = (struct t_gui_window *)hashtable_get (pointers, "window");
+ if (window)
+ hashtable_set (pointers, "buffer", window->buffer);
+ }
+ }
+
+ /* create hashtable extra_vars if it's NULL */
+ if (!extra_vars)
+ {
+ extra_vars = hashtable_new (16,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL,
+ NULL);
+ if (!extra_vars)
+ return NULL;
+ extra_vars_created = 1;
+ }
+
+ value = eval_expression_internal (expr, pointers, extra_vars, 0);
+
+ if (pointers_created)
+ hashtable_free (pointers);
+ if (extra_vars_created)
+ hashtable_free (extra_vars);
+
+ return value;
+}
diff --git a/src/core/wee-eval.h b/src/core/wee-eval.h
new file mode 100644
index 000000000..482de2e2e
--- /dev/null
+++ b/src/core/wee-eval.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Sebastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEECHAT_EVAL_H
+#define __WEECHAT_EVAL_H 1
+
+#define EVAL_STR_FALSE "0"
+#define EVAL_STR_TRUE "1"
+
+struct t_hashtable;
+
+enum t_eval_logical_op
+{
+ EVAL_LOGICAL_OP_AND = 0,
+ EVAL_LOGICAL_OP_OR,
+ /* number of comparison strings */
+ EVAL_NUM_LOGICAL_OPS,
+};
+
+enum t_eval_comparison
+{
+ EVAL_COMPARE_EQUAL = 0,
+ EVAL_COMPARE_NOT_EQUAL,
+ EVAL_COMPARE_LESS_EQUAL,
+ EVAL_COMPARE_LESS,
+ EVAL_COMPARE_GREATER_EQUAL,
+ EVAL_COMPARE_GREATER,
+ EVAL_COMPARE_REGEX_MATCHING,
+ EVAL_COMPARE_REGEX_NOT_MATCHING,
+ /* number of comparison strings */
+ EVAL_NUM_COMPARISONS,
+};
+
+extern int eval_is_true (const char *value);
+extern char *eval_expression (const char *expr,
+ struct t_hashtable *pointers,
+ struct t_hashtable *extra_vars);
+
+#endif /* __WEECHAT_EVAL_H */
diff --git a/src/core/wee-string.c b/src/core/wee-string.c
index 1d16d6d0f..269663cb8 100644
--- a/src/core/wee-string.c
+++ b/src/core/wee-string.c
@@ -49,7 +49,6 @@
#include "weechat.h"
#include "wee-string.h"
#include "wee-config.h"
-#include "wee-hashtable.h"
#include "wee-utf8.h"
#include "../gui/gui-color.h"
#include "../plugins/plugin.h"
@@ -1774,28 +1773,29 @@ string_input_for_buffer (const char *string)
}
/*
- * string_replace_with_hashtable: replace ${codes} with value from hashtable
- * "errors" is set with number of keys not found
- * in hashtable
+ * string_replace_with_callback: replace ${codes} using a callback that return
+ * replacement value (this value must be newly
+ * allocated because it will be freed in this
+ * function)
+ * "errors" is set with number of keys not found
+ * by callback
*/
char *
-string_replace_with_hashtable (const char *string,
- struct t_hashtable *hashtable,
- int *errors)
+string_replace_with_callback (const char *string,
+ char *(*callback)(void *data, const char *text),
+ void *callback_data,
+ int *errors)
{
int length, length_value, index_string, index_result;
- char *result, *result2, *key;
- const char *pos_end_name, *ptr_value;
+ char *result, *result2, *key, *value;
+ const char *pos_end_name;
*errors = 0;
if (!string)
return NULL;
- if (!hashtable)
- return strdup (string);
-
length = strlen (string) + 1;
result = malloc (length);
if (result)
@@ -1820,10 +1820,10 @@ string_replace_with_hashtable (const char *string,
pos_end_name - (string + index_string + 2));
if (key)
{
- ptr_value = (const char *)hashtable_get (hashtable, key);
- if (ptr_value)
+ value = (*callback) (callback_data, key);
+ if (value)
{
- length_value = strlen (ptr_value);
+ length_value = strlen (value);
length += length_value;
result2 = realloc (result, length);
if (!result2)
@@ -1831,13 +1831,15 @@ string_replace_with_hashtable (const char *string,
if (result)
free (result);
free (key);
+ free (value);
return NULL;
}
result = result2;
- strcpy (result + index_result, ptr_value);
+ strcpy (result + index_result, value);
index_result += length_value;
index_string += pos_end_name - string -
index_string + 1;
+ free (value);
}
else
{
diff --git a/src/core/wee-string.h b/src/core/wee-string.h
index a000e65f3..a9fc76ea8 100644
--- a/src/core/wee-string.h
+++ b/src/core/wee-string.h
@@ -75,8 +75,9 @@ extern void string_encode_base64 (const char *from, int length, char *to);
extern int string_decode_base64 (const char *from, char *to);
extern int string_is_command_char (const char *string);
extern const char *string_input_for_buffer (const char *string);
-extern char *string_replace_with_hashtable (const char *string,
- struct t_hashtable *hashtable,
- int *errors);
+extern char *string_replace_with_callback (const char *string,
+ char *(*callback)(void *data, const char *text),
+ void *callback_data,
+ int *errors);
#endif /* __WEECHAT_STRING_H */
diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c
index fade60939..43d5dbb53 100644
--- a/src/gui/gui-bar-item.c
+++ b/src/gui/gui-bar-item.c
@@ -176,13 +176,52 @@ gui_bar_item_search_with_plugin (struct t_weechat_plugin *plugin,
}
/*
- * gui_bar_item_used_in_a_bar: return 1 if an item is used in at least one bar
- * if partial_name == 1, then search a bar that
- * contains item beginning with "item_name"
+ * gui_bar_item_used_in_bar: return 1 if an item is used in the bar
+ * if partial_name == 1, then search if an item
+ * begins with "item_name"
*/
int
-gui_bar_item_used_in_a_bar (const char *item_name, int partial_name)
+gui_bar_item_used_in_bar (struct t_gui_bar *bar, const char *item_name,
+ int partial_name)
+{
+ int i, j, length;
+
+ length = strlen (item_name);
+
+ for (i = 0; i < bar->items_count; i++)
+ {
+ for (j = 0; j < bar->items_subcount[i]; j++)
+ {
+ if (bar->items_name[i][j])
+ {
+ if ((partial_name
+ && strncmp (bar->items_name[i][j],
+ item_name, length) == 0)
+ || (!partial_name
+ && strcmp (bar->items_name[i][j],
+ item_name) == 0))
+ {
+ return 1;
+ }
+ }
+ }
+ }
+
+ /* item not used in the bar */
+ return 0;
+}
+
+/*
+ * gui_bar_item_used_in_at_least_one_bar: return 1 if an item is used in at
+ * least one bar
+ * if partial_name == 1, then search a
+ * bar that contains item beginning with
+ * "item_name"
+ */
+
+int
+gui_bar_item_used_in_at_least_one_bar (const char *item_name, int partial_name)
{
struct t_gui_bar *ptr_bar;
int i, j, length;
@@ -211,7 +250,7 @@ gui_bar_item_used_in_a_bar (const char *item_name, int partial_name)
}
}
- /* item not used by any bar */
+ /* item not used in any bar */
return 0;
}
diff --git a/src/gui/gui-bar-item.h b/src/gui/gui-bar-item.h
index 2b7b92d6d..8e7ae338d 100644
--- a/src/gui/gui-bar-item.h
+++ b/src/gui/gui-bar-item.h
@@ -76,8 +76,11 @@ extern char *gui_bar_items_default_for_bars[][2];
extern int gui_bar_item_valid (struct t_gui_bar_item *bar_item);
extern struct t_gui_bar_item *gui_bar_item_search (const char *name);
-extern int gui_bar_item_used_in_a_bar (const char *item_name,
- int partial_name);
+extern int gui_bar_item_used_in_bar (struct t_gui_bar *bar,
+ const char *item_name,
+ int partial_name);
+extern int gui_bar_item_used_in_at_least_one_bar (const char *item_name,
+ int partial_name);
extern void gui_bar_item_set_prefix_name_suffix (const char *item_name,
char **prefix, char **name,
char **suffix);
diff --git a/src/gui/gui-bar.c b/src/gui/gui-bar.c
index 31ec7f677..eb2c4299c 100644
--- a/src/gui/gui-bar.c
+++ b/src/gui/gui-bar.c
@@ -32,6 +32,8 @@
#include "../core/weechat.h"
#include "../core/wee-config.h"
+#include "../core/wee-eval.h"
+#include "../core/wee-hashtable.h"
#include "../core/wee-hdata.h"
#include "../core/wee-hook.h"
#include "../core/wee-infolist.h"
@@ -372,27 +374,64 @@ int
gui_bar_check_conditions_for_window (struct t_gui_bar *bar,
struct t_gui_window *window)
{
- int i, rc;
- char str_modifier[256], str_window[128], *str_displayed;
+ int rc;
+ char str_modifier[256], str_window[128], *str_displayed, *result;
+ const char *conditions;
+ struct t_hashtable *pointers, *extra_vars;
- /* check bar conditions */
- for (i = 0; i < bar->conditions_count; i++)
+ /* check bar condition(s) */
+ conditions = CONFIG_STRING(bar->options[GUI_BAR_OPTION_CONDITIONS]);
+ if (string_strcasecmp (conditions, "active") == 0)
{
- if (string_strcasecmp (bar->conditions_array[i], "active") == 0)
- {
- if (gui_current_window && (gui_current_window != window))
- return 0;
- }
- else if (string_strcasecmp (bar->conditions_array[i], "inactive") == 0)
+ if (gui_current_window && (gui_current_window != window))
+ return 0;
+ }
+ else if (string_strcasecmp (conditions, "inactive") == 0)
+ {
+ if (!gui_current_window || (gui_current_window == window))
+ return 0;
+ }
+ else if (string_strcasecmp (conditions, "nicklist") == 0)
+ {
+ if (window->buffer && !window->buffer->nicklist)
+ return 0;
+ }
+ else if (conditions[0])
+ {
+ pointers = hashtable_new (16,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER,
+ NULL,
+ NULL);
+ if (pointers)
{
- if (!gui_current_window || (gui_current_window == window))
- return 0;
+ hashtable_set (pointers, "window", window);
+ hashtable_set (pointers, "buffer", window->buffer);
}
- else if (string_strcasecmp (bar->conditions_array[i], "nicklist") == 0)
+ extra_vars = hashtable_new (16,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER,
+ NULL,
+ NULL);
+ if (extra_vars)
{
- if (window->buffer && !window->buffer->nicklist)
- return 0;
+ hashtable_set (extra_vars, "active",
+ (gui_current_window && (gui_current_window == window)) ? "1" : "0");
+ hashtable_set (extra_vars, "inactive",
+ (gui_current_window && (gui_current_window != window)) ? "1" : "0");
+ hashtable_set (extra_vars, "nicklist",
+ (window->buffer && window->buffer->nicklist) ? "1" : "0");
}
+ result = eval_expression (conditions, pointers, extra_vars);
+ rc = eval_is_true (result);
+ if (result)
+ free (result);
+ if (pointers)
+ hashtable_free (pointers);
+ if (extra_vars)
+ hashtable_free (extra_vars);
+ if (!rc)
+ return 0;
}
/*
@@ -413,6 +452,7 @@ gui_bar_check_conditions_for_window (struct t_gui_bar *bar,
rc = 0;
else
rc = 1;
+
if (str_displayed)
free (str_displayed);
@@ -885,30 +925,9 @@ gui_bar_config_change_priority (void *data, struct t_config_option *option)
void
gui_bar_config_change_conditions (void *data, struct t_config_option *option)
{
- struct t_gui_bar *ptr_bar;
-
/* make C compiler happy */
(void) data;
-
- ptr_bar = gui_bar_search_with_option_name (option->name);
- if (ptr_bar)
- {
- if (ptr_bar->conditions_array)
- string_free_split (ptr_bar->conditions_array);
-
- if (CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_CONDITIONS])
- && CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_CONDITIONS])[0])
- {
- ptr_bar->conditions_array = string_split (CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_CONDITIONS]),
- ",", 0, 0,
- &ptr_bar->conditions_count);
- }
- else
- {
- ptr_bar->conditions_count = 0;
- ptr_bar->conditions_array = NULL;
- }
- }
+ (void) option;
gui_window_ask_refresh (1);
}
@@ -1343,9 +1362,13 @@ gui_bar_create_option (const char *bar_name, int index_option, const char *value
weechat_config_file, weechat_config_section_bar,
option_name, "string",
N_("condition(s) for displaying bar (for bars of type "
- "\"window\"): \"active\" = window must be active, "
- "\"inactive\" = window must be inactive, "
- "\"nicklist\" = buffer must have a nicklist"),
+ "\"window\"): a simple condition: \"active\", "
+ "\"inactive\", \"nicklist\" (window must be active/"
+ "inactive, buffer must have a nicklist), or an "
+ "expression with condition(s) (see /help eval), like: "
+ "\"${nicklist} && ${window.win_width} > 100\" "
+ "(local variables for expression are ${active}, "
+ "${inactive} and ${nicklist})"),
NULL, 0, 0, value, NULL, 0,
NULL, NULL, &gui_bar_config_change_conditions, NULL, NULL, NULL);
break;
@@ -1537,8 +1560,6 @@ gui_bar_alloc (const char *name)
{
new_bar->options[i] = NULL;
}
- new_bar->conditions_count = 0;
- new_bar->conditions_array = NULL;
new_bar->items_count = 0;
new_bar->items_array = NULL;
new_bar->items_prefix = NULL;
@@ -1585,17 +1606,6 @@ gui_bar_new_with_options (const char *name,
new_bar->options[GUI_BAR_OPTION_PRIORITY] = priority;
new_bar->options[GUI_BAR_OPTION_TYPE] = type;
new_bar->options[GUI_BAR_OPTION_CONDITIONS] = conditions;
- if (CONFIG_STRING(conditions) && CONFIG_STRING(conditions)[0])
- {
- new_bar->conditions_array = string_split (CONFIG_STRING(conditions),
- ",", 0, 0,
- &new_bar->conditions_count);
- }
- else
- {
- new_bar->conditions_count = 0;
- new_bar->conditions_array = NULL;
- }
new_bar->options[GUI_BAR_OPTION_POSITION] = position;
new_bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM] = filling_top_bottom;
new_bar->options[GUI_BAR_OPTION_FILLING_LEFT_RIGHT] = filling_left_right;
@@ -1832,7 +1842,7 @@ gui_bar_create_default_input ()
char *buf;
/* search an input_text item */
- if (!gui_bar_item_used_in_a_bar (gui_bar_item_names[GUI_BAR_ITEM_INPUT_TEXT], 1))
+ if (!gui_bar_item_used_in_at_least_one_bar (gui_bar_item_names[GUI_BAR_ITEM_INPUT_TEXT], 1))
{
ptr_bar = gui_bar_search (GUI_BAR_DEFAULT_NAME_INPUT);
if (ptr_bar)
@@ -1973,7 +1983,7 @@ gui_bar_create_default_nicklist ()
"0", /* hidden */
"200", /* priority */
"window", /* type */
- "nicklist", /* conditions */
+ "${nicklist}", /* conditions */
"right", /* position */
"columns_vertical", /* filling_top_bottom */
"vertical", /* filling_left_right */
@@ -2178,8 +2188,6 @@ gui_bar_free (struct t_gui_bar *bar)
if (bar->options[i])
config_file_option_free (bar->options[i]);
}
- if (bar->conditions_array)
- string_free_split (bar->conditions_array);
gui_bar_free_items_arrays (bar);
free (bar);
@@ -2249,8 +2257,6 @@ gui_bar_hdata_bar_cb (void *data, const char *hdata_name)
{
HDATA_VAR(struct t_gui_bar, name, STRING, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, options, POINTER, 0, NULL, NULL);
- HDATA_VAR(struct t_gui_bar, conditions_count, INTEGER, 0, NULL, NULL);
- HDATA_VAR(struct t_gui_bar, conditions_array, STRING, 0, "conditions_count", NULL);
HDATA_VAR(struct t_gui_bar, items_count, INTEGER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_subcount, POINTER, 0, NULL, NULL);
HDATA_VAR(struct t_gui_bar, items_array, POINTER, 0, NULL, NULL);
@@ -2297,16 +2303,6 @@ gui_bar_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!infolist_new_var_string (ptr_item, "conditions", CONFIG_STRING(bar->options[GUI_BAR_OPTION_CONDITIONS])))
return 0;
- if (!infolist_new_var_integer (ptr_item, "conditions_count", bar->conditions_count))
- return 0;
- for (i = 0; i < bar->conditions_count; i++)
- {
- snprintf (option_name, sizeof (option_name),
- "conditions_array_%05d", i + 1);
- if (!infolist_new_var_string (ptr_item, option_name,
- bar->conditions_array[i]))
- return 0;
- }
if (!infolist_new_var_integer (ptr_item, "position", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_POSITION])))
return 0;
if (!infolist_new_var_integer (ptr_item, "filling_top_bottom", CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_FILLING_TOP_BOTTOM])))
@@ -2377,8 +2373,6 @@ gui_bar_print_log ()
CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]),
gui_bar_type_string[CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE])]);
log_printf (" conditions . . . . . . : '%s'", CONFIG_STRING(ptr_bar->options[GUI_BAR_OPTION_CONDITIONS]));
- log_printf (" conditions_count . . . : %d", ptr_bar->conditions_count);
- log_printf (" conditions_array . . . : 0x%lx", ptr_bar->conditions_array);
log_printf (" position . . . . . . . : %d (%s)",
CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_POSITION]),
gui_bar_position_string[CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_POSITION])]);
diff --git a/src/gui/gui-bar.h b/src/gui/gui-bar.h
index aec264129..6743f9fc1 100644
--- a/src/gui/gui-bar.h
+++ b/src/gui/gui-bar.h
@@ -34,7 +34,7 @@ enum t_gui_bar_option
GUI_BAR_OPTION_HIDDEN = 0, /* true if bar is hidden */
GUI_BAR_OPTION_PRIORITY, /* bar priority */
GUI_BAR_OPTION_TYPE, /* type (root or window) */
- GUI_BAR_OPTION_CONDITIONS, /* conditions for display */
+ GUI_BAR_OPTION_CONDITIONS, /* condition(s) for display */
GUI_BAR_OPTION_POSITION, /* bottom, top, left, right */
GUI_BAR_OPTION_FILLING_TOP_BOTTOM, /* filling when pos. is top/bottom */
GUI_BAR_OPTION_FILLING_LEFT_RIGHT, /* filling when pos. is left/right */
@@ -84,8 +84,6 @@ struct t_gui_bar
struct t_config_option *options[GUI_BAR_NUM_OPTIONS];
/* internal vars */
- int conditions_count; /* number of conditions */
- char **conditions_array; /* bar conditions (after split) */
int items_count; /* number of bar items */
int *items_subcount; /* number of sub items */
char ***items_array; /* bar items (after split) */
diff --git a/src/gui/gui-key.c b/src/gui/gui-key.c
index 492e0d9e4..93938ec2a 100644
--- a/src/gui/gui-key.c
+++ b/src/gui/gui-key.c
@@ -950,6 +950,29 @@ gui_key_focus_matching (struct t_gui_key *key,
}
/*
+ * gui_key_focus_command_replace_cb: callback for replacing values in string
+ * with a hashtable
+ */
+
+char *
+gui_key_focus_command_replace_cb (void *data, const char *text)
+{
+ struct t_hashtable *ptr_hashtable;
+ const char *ptr_value;
+
+ ptr_hashtable = (struct t_hashtable *)data;
+
+ if (ptr_hashtable)
+ {
+ ptr_value = hashtable_get (ptr_hashtable, text);
+ if (ptr_value)
+ return strdup (ptr_value);
+ }
+
+ return NULL;
+}
+
+/*
* gui_key_focus_command: run command according to focus
* return 1 if a command was executed, otherwise 0
*/
@@ -1038,9 +1061,10 @@ gui_key_focus_command (const char *key, int context,
}
else
{
- command = string_replace_with_hashtable (commands[i],
- hashtable,
- &errors);
+ command = string_replace_with_callback (commands[i],
+ &gui_key_focus_command_replace_cb,
+ hashtable,
+ &errors);
if (command)
{
if (errors == 0)
diff --git a/src/plugins/guile/weechat-guile-api.c b/src/plugins/guile/weechat-guile-api.c
index 378fb7e0f..f2267b19d 100644
--- a/src/plugins/guile/weechat-guile-api.c
+++ b/src/plugins/guile/weechat-guile-api.c
@@ -421,6 +421,44 @@ weechat_guile_api_string_input_for_buffer (SCM string)
}
/*
+ * weechat_guile_api_string_eval_expression: evaluate an expression and return
+ * result
+ */
+
+SCM
+weechat_guile_api_string_eval_expression (SCM expr, SCM pointers,
+ SCM extra_vars)
+{
+ char *result;
+ SCM return_value;
+ struct t_hashtable *c_pointers, *c_extra_vars;
+
+ API_FUNC(1, "string_eval_expression", API_RETURN_EMPTY);
+ if (!scm_is_string (expr) || !scm_list_p (pointers)
+ || !scm_list_p (extra_vars))
+ API_WRONG_ARGS(API_RETURN_EMPTY);
+
+ c_pointers = weechat_guile_alist_to_hashtable (pointers,
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER);
+ c_extra_vars = weechat_guile_alist_to_hashtable (extra_vars,
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
+
+ result = weechat_string_eval_expression (scm_i_string_chars (expr),
+ c_pointers, c_extra_vars);
+
+ if (c_pointers)
+ weechat_hashtable_free (c_pointers);
+ if (c_extra_vars)
+ weechat_hashtable_free (c_extra_vars);
+
+ API_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat_guile_api_mkdir_home: create a directory in WeeChat home
*/
@@ -1933,7 +1971,9 @@ weechat_guile_api_key_bind (SCM context, SCM keys)
API_WRONG_ARGS(API_RETURN_INT(0));
c_keys = weechat_guile_alist_to_hashtable (keys,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
num_keys = weechat_key_bind (scm_i_string_chars (context), c_keys);
@@ -2454,7 +2494,9 @@ weechat_guile_api_hook_process_hashtable (SCM command, SCM options, SCM timeout,
API_WRONG_ARGS(API_RETURN_EMPTY);
c_options = weechat_guile_alist_to_hashtable (options,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
result = API_PTR2STR(plugin_script_api_hook_process_hashtable (weechat_guile_plugin,
guile_current_script,
@@ -2861,7 +2903,9 @@ weechat_guile_api_hook_hsignal_send (SCM signal, SCM hashtable)
API_WRONG_ARGS(API_RETURN_ERROR);
c_hashtable = weechat_guile_alist_to_hashtable (hashtable,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
weechat_hook_hsignal_send (scm_i_string_chars (signal), c_hashtable);
@@ -4462,7 +4506,9 @@ weechat_guile_api_info_get_hashtable (SCM info_name, SCM hash)
API_WRONG_ARGS(API_RETURN_EMPTY);
c_hashtable = weechat_guile_alist_to_hashtable (hash,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
result_hashtable = weechat_info_get_hashtable (scm_i_string_chars (info_name),
c_hashtable);
@@ -5160,7 +5206,9 @@ weechat_guile_api_hdata_update (SCM hdata, SCM pointer, SCM hashtable)
API_WRONG_ARGS(API_RETURN_INT(0));
c_hashtable = weechat_guile_alist_to_hashtable (hashtable,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
value = weechat_hdata_update (API_STR2PTR(scm_i_string_chars (hdata)),
API_STR2PTR(scm_i_string_chars (pointer)),
@@ -5358,6 +5406,7 @@ weechat_guile_api_module_init (void *data)
API_DEF_FUNC(string_remove_color, 2);
API_DEF_FUNC(string_is_command_char, 1);
API_DEF_FUNC(string_input_for_buffer, 1);
+ API_DEF_FUNC(string_eval_expression, 3);
API_DEF_FUNC(mkdir_home, 2);
API_DEF_FUNC(mkdir, 2);
API_DEF_FUNC(mkdir_parents, 2);
diff --git a/src/plugins/guile/weechat-guile.c b/src/plugins/guile/weechat-guile.c
index 7dbd5ce4b..a46093167 100644
--- a/src/plugins/guile/weechat-guile.c
+++ b/src/plugins/guile/weechat-guile.c
@@ -198,22 +198,21 @@ weechat_guile_hashtable_to_alist (struct t_hashtable *hashtable)
/*
* weechat_guile_alist_to_hashtable: get WeeChat hashtable with Guile alist
- * Hashtable returned has type string for
- * both keys and values
* Note: hashtable has to be released after
* use with call to weechat_hashtable_free()
*/
struct t_hashtable *
-weechat_guile_alist_to_hashtable (SCM alist, int hashtable_size)
+weechat_guile_alist_to_hashtable (SCM alist, int size, const char *type_keys,
+ const char *type_values)
{
struct t_hashtable *hashtable;
int length, i;
SCM pair;
- hashtable = weechat_hashtable_new (hashtable_size,
- WEECHAT_HASHTABLE_STRING,
- WEECHAT_HASHTABLE_STRING,
+ hashtable = weechat_hashtable_new (size,
+ type_keys,
+ type_values,
NULL,
NULL);
if (!hashtable)
@@ -223,11 +222,24 @@ weechat_guile_alist_to_hashtable (SCM alist, int hashtable_size)
for (i = 0; i < length; i++)
{
pair = scm_list_ref (alist, scm_from_int (i));
- weechat_hashtable_set (hashtable,
- scm_i_string_chars (scm_list_ref (pair,
- scm_from_int (0))),
- scm_i_string_chars (scm_list_ref (pair,
- scm_from_int (1))));
+ if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0)
+ {
+ weechat_hashtable_set (hashtable,
+ scm_i_string_chars (scm_list_ref (pair,
+ scm_from_int (0))),
+ scm_i_string_chars (scm_list_ref (pair,
+ scm_from_int (1))));
+ }
+ else if (strcmp (type_values, WEECHAT_HASHTABLE_POINTER) == 0)
+ {
+ weechat_hashtable_set (hashtable,
+ scm_i_string_chars (scm_list_ref (pair,
+ scm_from_int (0))),
+ plugin_script_str2ptr (weechat_guile_plugin,
+ NULL, NULL,
+ scm_i_string_chars (scm_list_ref (pair,
+ scm_from_int (1)))));
+ }
}
return hashtable;
@@ -305,7 +317,9 @@ weechat_guile_exec (struct t_plugin_script *script,
else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE)
{
ret_value = weechat_guile_alist_to_hashtable (rc,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
}
else
{
diff --git a/src/plugins/guile/weechat-guile.h b/src/plugins/guile/weechat-guile.h
index b868a4c10..03c104b64 100644
--- a/src/plugins/guile/weechat-guile.h
+++ b/src/plugins/guile/weechat-guile.h
@@ -37,7 +37,9 @@ extern SCM guile_port;
extern SCM weechat_guile_hashtable_to_alist (struct t_hashtable *hashtable);
extern struct t_hashtable *weechat_guile_alist_to_hashtable (SCM dict,
- int hashtable_size);
+ int size,
+ const char *type_keys,
+ const char *type_values);
extern void *weechat_guile_exec (struct t_plugin_script *script,
int ret_type, const char *function,
char *format, void **argv);
diff --git a/src/plugins/lua/weechat-lua-api.c b/src/plugins/lua/weechat-lua-api.c
index ce8a1e61f..6c1f83537 100644
--- a/src/plugins/lua/weechat-lua-api.c
+++ b/src/plugins/lua/weechat-lua-api.c
@@ -461,6 +461,42 @@ weechat_lua_api_string_input_for_buffer (lua_State *L)
}
/*
+ * weechat_lua_api_string_eval_expression: evaluate an expression and return
+ * result
+ */
+
+static int
+weechat_lua_api_string_eval_expression (lua_State *L)
+{
+ const char *expr;
+ struct t_hashtable *pointers, *extra_vars;
+ char *result;
+
+ API_FUNC(1, "string_eval_expression", API_RETURN_EMPTY);
+ if (lua_gettop (lua_current_interpreter) < 3)
+ API_WRONG_ARGS(API_RETURN_EMPTY);
+
+ expr = lua_tostring (lua_current_interpreter, -3);
+ pointers = weechat_lua_tohashtable (lua_current_interpreter, -2,
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER);
+ extra_vars = weechat_lua_tohashtable (lua_current_interpreter, -1,
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
+
+ result = weechat_string_eval_expression (expr, pointers, extra_vars);
+
+ if (pointers)
+ weechat_hashtable_free (pointers);
+ if (extra_vars)
+ weechat_hashtable_free (extra_vars);
+
+ API_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat_lua_api_mkdir_home: create a directory in WeeChat home
*/
@@ -2133,7 +2169,9 @@ weechat_lua_api_key_bind (lua_State *L)
context = lua_tostring (lua_current_interpreter, -2);
hashtable = weechat_lua_tohashtable (lua_current_interpreter, -1,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
num_keys = weechat_key_bind (context, hashtable);
@@ -2702,7 +2740,9 @@ weechat_lua_api_hook_process_hashtable (lua_State *L)
command = lua_tostring (lua_current_interpreter, -5);
options = weechat_lua_tohashtable (lua_current_interpreter, -4,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
timeout = lua_tonumber (lua_current_interpreter, -3);
function = lua_tostring (lua_current_interpreter, -2);
data = lua_tostring (lua_current_interpreter, -1);
@@ -3127,7 +3167,9 @@ weechat_lua_api_hook_hsignal_send (lua_State *L)
signal = lua_tostring (lua_current_interpreter, -2);
hashtable = weechat_lua_tohashtable (lua_current_interpreter, -1,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
weechat_hook_hsignal_send (signal, hashtable);
@@ -4899,7 +4941,9 @@ weechat_lua_api_info_get_hashtable (lua_State *L)
info_name = lua_tostring (lua_current_interpreter, -2);
table = weechat_lua_tohashtable (lua_current_interpreter, -1,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
result_hashtable = weechat_info_get_hashtable (info_name, table);
@@ -5695,7 +5739,9 @@ weechat_lua_api_hdata_update (lua_State *L)
hdata = lua_tostring (lua_current_interpreter, -3);
pointer = lua_tostring (lua_current_interpreter, -2);
hashtable = weechat_lua_tohashtable (lua_current_interpreter, -1,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
value = weechat_hdata_update (API_STR2PTR(hdata),
API_STR2PTR(pointer),
@@ -6296,6 +6342,7 @@ const struct luaL_Reg weechat_lua_api_funcs[] = {
API_DEF_FUNC(string_remove_color),
API_DEF_FUNC(string_is_command_char),
API_DEF_FUNC(string_input_for_buffer),
+ API_DEF_FUNC(string_eval_expression),
API_DEF_FUNC(mkdir_home),
API_DEF_FUNC(mkdir),
API_DEF_FUNC(mkdir_parents),
diff --git a/src/plugins/lua/weechat-lua.c b/src/plugins/lua/weechat-lua.c
index 89cede0b8..8711eead1 100644
--- a/src/plugins/lua/weechat-lua.c
+++ b/src/plugins/lua/weechat-lua.c
@@ -108,20 +108,19 @@ weechat_lua_pushhashtable (lua_State *interpreter, struct t_hashtable *hashtable
/*
* weechat_lua_hash_to_hashtable: get WeeChat hashtable with lua hash (on stack)
- * Hashtable returned has type string for
- * both keys and values
* Note: hashtable has to be released after use
* with call to weechat_hashtable_free()
*/
struct t_hashtable *
-weechat_lua_tohashtable (lua_State *interpreter, int index, int hashtable_size)
+weechat_lua_tohashtable (lua_State *interpreter, int index, int size,
+ const char *type_keys, const char *type_values)
{
struct t_hashtable *hashtable;
- hashtable = weechat_hashtable_new (hashtable_size,
- WEECHAT_HASHTABLE_STRING,
- WEECHAT_HASHTABLE_STRING,
+ hashtable = weechat_hashtable_new (size,
+ type_keys,
+ type_values,
NULL,
NULL);
if (!hashtable)
@@ -130,9 +129,20 @@ weechat_lua_tohashtable (lua_State *interpreter, int index, int hashtable_size)
lua_pushnil (interpreter);
while (lua_next (interpreter, index - 1) != 0)
{
- weechat_hashtable_set (hashtable,
- lua_tostring (interpreter, -2),
- lua_tostring (interpreter, -1));
+ if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0)
+ {
+ weechat_hashtable_set (hashtable,
+ lua_tostring (interpreter, -2),
+ lua_tostring (interpreter, -1));
+ }
+ else if (strcmp (type_values, WEECHAT_HASHTABLE_POINTER) == 0)
+ {
+ weechat_hashtable_set (hashtable,
+ lua_tostring (interpreter, -2),
+ plugin_script_str2ptr (weechat_lua_plugin,
+ NULL, NULL,
+ lua_tostring (interpreter, -1)));
+ }
/* remove value from stack (keep key for next iteration) */
lua_pop (interpreter, 1);
}
@@ -209,7 +219,9 @@ weechat_lua_exec (struct t_plugin_script *script, int ret_type,
else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE)
{
ret_value = weechat_lua_tohashtable (lua_current_interpreter, -1,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
}
else
{
diff --git a/src/plugins/lua/weechat-lua.h b/src/plugins/lua/weechat-lua.h
index 0512d2272..7f4de2085 100644
--- a/src/plugins/lua/weechat-lua.h
+++ b/src/plugins/lua/weechat-lua.h
@@ -40,7 +40,9 @@ extern void weechat_lua_pushhashtable (lua_State *interpreter,
struct t_hashtable *hashtable);
extern struct t_hashtable *weechat_lua_tohashtable (lua_State *interpreter,
int index,
- int hashtable_size);
+ int size,
+ const char *type_keys,
+ const char *type_values);
extern void *weechat_lua_exec (struct t_plugin_script *script, int ret_type,
const char *function,
const char *format, void **argv);
diff --git a/src/plugins/perl/weechat-perl-api.c b/src/plugins/perl/weechat-perl-api.c
index 3d0cb645e..d182bbb04 100644
--- a/src/plugins/perl/weechat-perl-api.c
+++ b/src/plugins/perl/weechat-perl-api.c
@@ -437,6 +437,40 @@ XS (XS_weechat_api_string_input_for_buffer)
}
/*
+ * weechat::string_eval_expression: evaluate expression and return result
+ */
+
+XS (XS_weechat_api_string_eval_expression)
+{
+ char *expr, *result;
+ struct t_hashtable *pointers, *extra_vars;
+ dXSARGS;
+
+ API_FUNC(1, "string_eval_expression", API_RETURN_EMPTY);
+ if (items < 3)
+ API_WRONG_ARGS(API_RETURN_EMPTY);
+
+ expr = SvPV_nolen (ST (0));
+ pointers = weechat_perl_hash_to_hashtable (ST (1),
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER);
+ extra_vars = weechat_perl_hash_to_hashtable (ST (2),
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
+
+ result = weechat_string_eval_expression (expr, pointers, extra_vars);
+
+ if (pointers)
+ weechat_hashtable_free (pointers);
+ if (extra_vars)
+ weechat_hashtable_free (extra_vars);
+
+ API_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat::mkdir_home: create a directory in WeeChat home
*/
@@ -2003,7 +2037,9 @@ XS (XS_weechat_api_key_bind)
context = SvPV_nolen (ST (0));
hashtable = weechat_perl_hash_to_hashtable (ST (1),
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
num_keys = weechat_key_bind (context, hashtable);
@@ -2537,7 +2573,9 @@ XS (XS_weechat_api_hook_process_hashtable)
command = SvPV_nolen (ST (0));
options = weechat_perl_hash_to_hashtable (ST (1),
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
function = SvPV_nolen (ST (3));
data = SvPV_nolen (ST (4));
@@ -2951,7 +2989,9 @@ XS (XS_weechat_api_hook_hsignal_send)
signal = SvPV_nolen (ST (0));
hashtable = weechat_perl_hash_to_hashtable (ST (1),
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
weechat_hook_hsignal_send (signal, hashtable);
@@ -4663,7 +4703,9 @@ XS (XS_weechat_api_info_get_hashtable)
info_name = SvPV_nolen (ST (0));
hashtable = weechat_perl_hash_to_hashtable (ST (1),
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
result_hashtable = weechat_info_get_hashtable (info_name, hashtable);
result_hash = weechat_perl_hashtable_to_hash (result_hashtable);
@@ -5428,7 +5470,9 @@ XS (XS_weechat_api_hdata_update)
hdata = SvPV_nolen (ST (0));
pointer = SvPV_nolen (ST (1));
hashtable = weechat_perl_hash_to_hashtable (ST (2),
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
value = weechat_hdata_update (API_STR2PTR(hdata),
API_STR2PTR(pointer),
@@ -5630,6 +5674,7 @@ weechat_perl_api_init (pTHX)
API_DEF_FUNC(string_remove_color);
API_DEF_FUNC(string_is_command_char);
API_DEF_FUNC(string_input_for_buffer);
+ API_DEF_FUNC(string_eval_expression);
API_DEF_FUNC(mkdir_home);
API_DEF_FUNC(mkdir);
API_DEF_FUNC(mkdir_parents);
diff --git a/src/plugins/perl/weechat-perl.c b/src/plugins/perl/weechat-perl.c
index f889aa6be..63ab186bd 100644
--- a/src/plugins/perl/weechat-perl.c
+++ b/src/plugins/perl/weechat-perl.c
@@ -169,14 +169,13 @@ weechat_perl_hashtable_to_hash (struct t_hashtable *hashtable)
/*
* weechat_perl_hash_to_hashtable: get WeeChat hashtable with perl hash
- * Hashtable returned has type string for
- * both keys and values
* Note: hashtable has to be released after use
* with call to weechat_hashtable_free()
*/
struct t_hashtable *
-weechat_perl_hash_to_hashtable (SV *hash, int hashtable_size)
+weechat_perl_hash_to_hashtable (SV *hash, int size, const char *type_keys,
+ const char *type_values)
{
struct t_hashtable *hashtable;
HV *hash2;
@@ -184,9 +183,9 @@ weechat_perl_hash_to_hashtable (SV *hash, int hashtable_size)
char *str_key;
I32 retlen;
- hashtable = weechat_hashtable_new (hashtable_size,
- WEECHAT_HASHTABLE_STRING,
- WEECHAT_HASHTABLE_STRING,
+ hashtable = weechat_hashtable_new (size,
+ type_keys,
+ type_values,
NULL,
NULL);
if (!hashtable)
@@ -198,7 +197,15 @@ weechat_perl_hash_to_hashtable (SV *hash, int hashtable_size)
hv_iterinit (hash2);
while ((value = hv_iternextsv (hash2, &str_key, &retlen)))
{
- weechat_hashtable_set (hashtable, str_key, SvPV (value, PL_na));
+ if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0)
+ weechat_hashtable_set (hashtable, str_key, SvPV (value, PL_na));
+ else if (strcmp (type_values, WEECHAT_HASHTABLE_POINTER) == 0)
+ {
+ weechat_hashtable_set (hashtable, str_key,
+ plugin_script_str2ptr (weechat_perl_plugin,
+ NULL, NULL,
+ SvPV (value, PL_na)));
+ }
}
}
@@ -316,7 +323,9 @@ weechat_perl_exec (struct t_plugin_script *script,
else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE)
{
ret_value = weechat_perl_hash_to_hashtable (POPs,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
}
else
{
diff --git a/src/plugins/perl/weechat-perl.h b/src/plugins/perl/weechat-perl.h
index 87a601aac..5e1eabe48 100644
--- a/src/plugins/perl/weechat-perl.h
+++ b/src/plugins/perl/weechat-perl.h
@@ -35,8 +35,9 @@ extern struct t_plugin_script *perl_registered_script;
extern const char *perl_current_script_filename;
extern HV *weechat_perl_hashtable_to_hash (struct t_hashtable *hashtable);
-extern struct t_hashtable *weechat_perl_hash_to_hashtable (SV *hash,
- int hashtable_size);
+extern struct t_hashtable *weechat_perl_hash_to_hashtable (SV *hash, int size,
+ const char *type_keys,
+ const char *type_values);
extern void *weechat_perl_exec (struct t_plugin_script *script,
int ret_type, const char *function,
const char *format, void **argv);
diff --git a/src/plugins/plugin-script.c b/src/plugins/plugin-script.c
index b1df0f49d..bc2babc49 100644
--- a/src/plugins/plugin-script.c
+++ b/src/plugins/plugin-script.c
@@ -286,7 +286,7 @@ plugin_script_str2ptr (struct t_weechat_plugin *weechat_plugin,
return (void *)value;
invalid:
- if (weechat_plugin->debug >= 1)
+ if ((weechat_plugin->debug >= 1) && script_name && function_name)
{
ptr_buffer = weechat_buffer_search_main ();
if (ptr_buffer)
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 323e5068b..dfec3a14c 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -39,6 +39,7 @@
#include "../core/weechat.h"
#include "../core/wee-config.h"
+#include "../core/wee-eval.h"
#include "../core/wee-hashtable.h"
#include "../core/wee-hdata.h"
#include "../core/wee-hook.h"
@@ -521,6 +522,7 @@ plugin_load (const char *filename, int argc, char **argv)
new_plugin->string_decode_base64 = &string_decode_base64;
new_plugin->string_is_command_char = &string_is_command_char;
new_plugin->string_input_for_buffer = &string_input_for_buffer;
+ new_plugin->string_eval_expression = &eval_expression;
new_plugin->utf8_has_8bits = &utf8_has_8bits;
new_plugin->utf8_is_valid = &utf8_is_valid;
diff --git a/src/plugins/python/weechat-python-api.c b/src/plugins/python/weechat-python-api.c
index cc8f2a4e1..f450f556b 100644
--- a/src/plugins/python/weechat-python-api.c
+++ b/src/plugins/python/weechat-python-api.c
@@ -444,6 +444,43 @@ weechat_python_api_string_input_for_buffer (PyObject *self, PyObject *args)
}
/*
+ * weechat_python_api_string_eval_expression: evaluate expression and return
+ * result
+ */
+
+static PyObject *
+weechat_python_api_string_eval_expression (PyObject *self, PyObject *args)
+{
+ char *expr, *result;
+ struct t_hashtable *pointers, *extra_vars;
+ PyObject *dict, *dict2, *return_value;
+
+ API_FUNC(1, "string_eval_expression", API_RETURN_EMPTY);
+ expr = NULL;
+ pointers = NULL;
+ extra_vars = NULL;
+ if (!PyArg_ParseTuple (args, "sOO", &expr, &dict, &dict2))
+ API_WRONG_ARGS(API_RETURN_EMPTY);
+ pointers = weechat_python_dict_to_hashtable (dict,
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER);
+ extra_vars = weechat_python_dict_to_hashtable (dict2,
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
+
+ result = weechat_string_eval_expression (expr, pointers, extra_vars);
+
+ if (pointers)
+ weechat_hashtable_free (pointers);
+ if (extra_vars)
+ weechat_hashtable_free (extra_vars);
+
+ API_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat_python_api_mkdir_home: create a directory in WeeChat home
*/
@@ -2081,7 +2118,9 @@ weechat_python_api_key_bind (PyObject *self, PyObject *args)
API_WRONG_ARGS(API_RETURN_INT(0));
hashtable = weechat_python_dict_to_hashtable (dict,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
num_keys = weechat_key_bind (context, hashtable);
@@ -2652,7 +2691,9 @@ weechat_python_api_hook_process_hashtable (PyObject *self, PyObject *args)
&data))
API_WRONG_ARGS(API_RETURN_EMPTY);
options = weechat_python_dict_to_hashtable (dict,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
result = API_PTR2STR(plugin_script_api_hook_process_hashtable (weechat_python_plugin,
python_current_script,
@@ -3077,7 +3118,9 @@ weechat_python_api_hook_hsignal_send (PyObject *self, PyObject *args)
API_WRONG_ARGS(API_RETURN_ERROR);
hashtable = weechat_python_dict_to_hashtable (dict,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
weechat_hook_hsignal_send (signal, hashtable);
@@ -4840,7 +4883,9 @@ weechat_python_api_info_get_hashtable (PyObject *self, PyObject *args)
if (!PyArg_ParseTuple (args, "sO", &info_name, &dict))
API_WRONG_ARGS(API_RETURN_EMPTY);
hashtable = weechat_python_dict_to_hashtable (dict,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
result_hashtable = weechat_info_get_hashtable (info_name, hashtable);
result_dict = weechat_python_hashtable_to_dict (result_hashtable);
@@ -5613,7 +5658,9 @@ weechat_python_api_hdata_update (PyObject *self, PyObject *args)
if (!PyArg_ParseTuple (args, "ssO", &hdata, &pointer, &dict))
API_WRONG_ARGS(API_RETURN_INT(0));
hashtable = weechat_python_dict_to_hashtable (dict,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
value = weechat_hdata_update (API_STR2PTR(hdata),
API_STR2PTR(pointer),
@@ -5807,6 +5854,7 @@ PyMethodDef weechat_python_funcs[] =
API_DEF_FUNC(string_remove_color),
API_DEF_FUNC(string_is_command_char),
API_DEF_FUNC(string_input_for_buffer),
+ API_DEF_FUNC(string_eval_expression),
API_DEF_FUNC(mkdir_home),
API_DEF_FUNC(mkdir),
API_DEF_FUNC(mkdir_parents),
diff --git a/src/plugins/python/weechat-python.c b/src/plugins/python/weechat-python.c
index 2eba42de4..d1a6d4185 100644
--- a/src/plugins/python/weechat-python.c
+++ b/src/plugins/python/weechat-python.c
@@ -232,23 +232,23 @@ weechat_python_hashtable_to_dict (struct t_hashtable *hashtable)
/*
* weechat_python_dict_to_hashtable: get WeeChat hashtable with python
* dictionary
- * Hashtable returned has type string for
- * both keys and values
* Note: hashtable has to be released after
* use with call to weechat_hashtable_free()
*/
struct t_hashtable *
-weechat_python_dict_to_hashtable (PyObject *dict, int hashtable_size)
+weechat_python_dict_to_hashtable (PyObject *dict, int size,
+ const char *type_keys,
+ const char *type_values)
{
struct t_hashtable *hashtable;
PyObject *key, *value;
Py_ssize_t pos;
char *str_key, *str_value;
- hashtable = weechat_hashtable_new (hashtable_size,
- WEECHAT_HASHTABLE_STRING,
- WEECHAT_HASHTABLE_STRING,
+ hashtable = weechat_hashtable_new (size,
+ type_keys,
+ type_values,
NULL,
NULL);
if (!hashtable)
@@ -275,7 +275,17 @@ weechat_python_dict_to_hashtable (PyObject *dict, int hashtable_size)
str_value = weechat_python_unicode_to_string (value);
if (str_key)
- weechat_hashtable_set (hashtable, str_key, str_value);
+ {
+ if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0)
+ weechat_hashtable_set (hashtable, str_key, str_value);
+ else if (strcmp (type_values, WEECHAT_HASHTABLE_POINTER) == 0)
+ {
+ weechat_hashtable_set (hashtable, str_key,
+ plugin_script_str2ptr (weechat_python_plugin,
+ NULL, NULL,
+ str_value));
+ }
+ }
if (str_key)
free (str_key);
@@ -388,7 +398,9 @@ weechat_python_exec (struct t_plugin_script *script,
else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE)
{
ret_value = weechat_python_dict_to_hashtable (rc,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
Py_XDECREF(rc);
}
else
diff --git a/src/plugins/python/weechat-python.h b/src/plugins/python/weechat-python.h
index 1a522603a..0a1aa2fe5 100644
--- a/src/plugins/python/weechat-python.h
+++ b/src/plugins/python/weechat-python.h
@@ -45,7 +45,9 @@ extern const char *python_current_script_filename;
extern PyObject *weechat_python_hashtable_to_dict (struct t_hashtable *hashtable);
extern struct t_hashtable *weechat_python_dict_to_hashtable (PyObject *dict,
- int hashtable_size);
+ int size,
+ const char *type_keys,
+ const char *type_values);
extern void *weechat_python_exec (struct t_plugin_script *script,
int ret_type, const char *function,
char *format, void **argv);
diff --git a/src/plugins/ruby/weechat-ruby-api.c b/src/plugins/ruby/weechat-ruby-api.c
index 23420282e..a0911bfe9 100644
--- a/src/plugins/ruby/weechat-ruby-api.c
+++ b/src/plugins/ruby/weechat-ruby-api.c
@@ -508,6 +508,47 @@ weechat_ruby_api_string_input_for_buffer (VALUE class, VALUE string)
}
/*
+ * weechat_ruby_api_string_eval_expression: evaluate an expression and return
+ * result
+ */
+
+static VALUE
+weechat_ruby_api_string_eval_expression (VALUE class, VALUE expr,
+ VALUE pointers, VALUE extra_vars)
+{
+ char *c_expr, *result;
+ struct t_hashtable *c_pointers, *c_extra_vars;
+ VALUE return_value;
+
+ API_FUNC(1, "string_eval_expression", API_RETURN_EMPTY);
+ if (NIL_P (expr) || NIL_P (pointers) || NIL_P (extra_vars))
+ API_WRONG_ARGS(API_RETURN_EMPTY);
+
+ Check_Type (expr, T_STRING);
+ Check_Type (pointers, T_HASH);
+ Check_Type (extra_vars, T_HASH);
+
+ c_expr = StringValuePtr (expr);
+ c_pointers = weechat_ruby_hash_to_hashtable (pointers,
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER);
+ c_extra_vars = weechat_ruby_hash_to_hashtable (extra_vars,
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
+
+ result = weechat_string_eval_expression (c_expr, c_pointers, c_extra_vars);
+
+ if (c_pointers)
+ weechat_hashtable_free (c_pointers);
+ if (c_extra_vars)
+ weechat_hashtable_free (c_extra_vars);
+
+ API_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat_ruby_api_mkdir_home: create a directory in WeeChat home
*/
@@ -2389,7 +2430,9 @@ weechat_ruby_api_key_bind (VALUE class, VALUE context, VALUE keys)
c_context = StringValuePtr (context);
c_keys = weechat_ruby_hash_to_hashtable (keys,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
num_keys = weechat_key_bind (c_context, c_keys);
@@ -3031,7 +3074,9 @@ weechat_ruby_api_hook_process_hashtable (VALUE class, VALUE command,
c_command = StringValuePtr (command);
c_options = weechat_ruby_hash_to_hashtable (options,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
c_timeout = FIX2INT (timeout);
c_function = StringValuePtr (function);
c_data = StringValuePtr (data);
@@ -3498,7 +3543,9 @@ weechat_ruby_api_hook_hsignal_send (VALUE class, VALUE signal, VALUE hashtable)
c_signal = StringValuePtr (signal);
c_hashtable = weechat_ruby_hash_to_hashtable (hashtable,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
weechat_hook_hsignal_send (c_signal, c_hashtable);
@@ -5543,7 +5590,9 @@ weechat_ruby_api_info_get_hashtable (VALUE class, VALUE info_name,
c_info_name = StringValuePtr (info_name);
c_hashtable = weechat_ruby_hash_to_hashtable (hash,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
result_hashtable = weechat_info_get_hashtable (c_info_name, c_hashtable);
result_hash = weechat_ruby_hashtable_to_hash (result_hashtable);
@@ -6465,7 +6514,9 @@ weechat_ruby_api_hdata_update (VALUE class, VALUE hdata, VALUE pointer,
c_hdata = StringValuePtr (hdata);
c_pointer = StringValuePtr (pointer);
c_hashtable = weechat_ruby_hash_to_hashtable (hashtable,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
value = weechat_hdata_update (API_STR2PTR(c_hdata),
API_STR2PTR(c_pointer),
@@ -6732,6 +6783,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat)
API_DEF_FUNC(string_remove_color, 2);
API_DEF_FUNC(string_is_command_char, 1);
API_DEF_FUNC(string_input_for_buffer, 1);
+ API_DEF_FUNC(string_eval_expression, 3);
API_DEF_FUNC(mkdir_home, 2);
API_DEF_FUNC(mkdir, 2);
API_DEF_FUNC(mkdir_parents, 2);
diff --git a/src/plugins/ruby/weechat-ruby.c b/src/plugins/ruby/weechat-ruby.c
index 882796d7d..e2b68db58 100644
--- a/src/plugins/ruby/weechat-ruby.c
+++ b/src/plugins/ruby/weechat-ruby.c
@@ -147,32 +147,43 @@ int
weechat_ruby_hash_foreach_cb (VALUE key, VALUE value, void *arg)
{
struct t_hashtable *hashtable;
+ const char *type_values;
hashtable = (struct t_hashtable *)arg;
if ((TYPE(key) == T_STRING) && (TYPE(value) == T_STRING))
{
- weechat_hashtable_set (hashtable, StringValuePtr(key),
- StringValuePtr(value));
+ type_values = weechat_hashtable_get_string (hashtable, "type_values");
+ if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0)
+ {
+ weechat_hashtable_set (hashtable, StringValuePtr(key),
+ StringValuePtr(value));
+ }
+ else if (strcmp (type_values, WEECHAT_HASHTABLE_POINTER) == 0)
+ {
+ weechat_hashtable_set (hashtable, StringValuePtr(key),
+ plugin_script_str2ptr (weechat_ruby_plugin,
+ NULL, NULL,
+ StringValuePtr(value)));
+ }
}
return 0;
}
/*
* weechat_ruby_hash_to_hashtable: get WeeChat hashtable with ruby hashtable
- * Hashtable returned has type string for
- * both keys and values
* Note: hashtable has to be released after use
* with call to weechat_hashtable_free()
*/
struct t_hashtable *
-weechat_ruby_hash_to_hashtable (VALUE hash, int hashtable_size)
+weechat_ruby_hash_to_hashtable (VALUE hash, int size, const char *type_keys,
+ const char *type_values)
{
struct t_hashtable *hashtable;
- hashtable = weechat_hashtable_new (hashtable_size,
- WEECHAT_HASHTABLE_STRING,
- WEECHAT_HASHTABLE_STRING,
+ hashtable = weechat_hashtable_new (size,
+ type_keys,
+ type_values,
NULL,
NULL);
if (!hashtable)
@@ -375,7 +386,9 @@ weechat_ruby_exec (struct t_plugin_script *script,
else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE)
{
ret_value = weechat_ruby_hash_to_hashtable (rc,
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
}
else
{
diff --git a/src/plugins/ruby/weechat-ruby.h b/src/plugins/ruby/weechat-ruby.h
index cf3e7a1b2..398616afa 100644
--- a/src/plugins/ruby/weechat-ruby.h
+++ b/src/plugins/ruby/weechat-ruby.h
@@ -37,7 +37,9 @@ extern const char *ruby_current_script_filename;
extern VALUE weechat_ruby_hashtable_to_hash (struct t_hashtable *hashtable);
extern struct t_hashtable *weechat_ruby_hash_to_hashtable (VALUE dict,
- int hashtable_size);
+ int size,
+ const char *type_keys,
+ const char *type_values);
void *weechat_ruby_exec (struct t_plugin_script *script,
int ret_type, const char *function,
const char *format, void **argv);
diff --git a/src/plugins/tcl/weechat-tcl-api.c b/src/plugins/tcl/weechat-tcl-api.c
index 0738fc39e..5e89aa3f3 100644
--- a/src/plugins/tcl/weechat-tcl-api.c
+++ b/src/plugins/tcl/weechat-tcl-api.c
@@ -612,6 +612,45 @@ weechat_tcl_api_string_input_for_buffer (ClientData clientData, Tcl_Interp *inte
}
/*
+ * weechat_tcl_api_string_eval_expression: evaluate an expression and return
+ * result
+ */
+
+static int
+weechat_tcl_api_string_eval_expression (ClientData clientData,
+ Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ Tcl_Obj *objp;
+ char *expr, *result;
+ struct t_hashtable *pointers, *extra_vars;
+ int i;
+
+ API_FUNC(1, "string_eval_expression", API_RETURN_EMPTY);
+ if (objc < 4)
+ API_WRONG_ARGS(API_RETURN_EMPTY);
+
+ expr = Tcl_GetStringFromObj (objv[1], &i);
+ pointers = weechat_tcl_dict_to_hashtable (interp, objv[2],
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_POINTER);
+ extra_vars = weechat_tcl_dict_to_hashtable (interp, objv[3],
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
+
+ result = weechat_string_eval_expression (expr, pointers, extra_vars);
+
+ if (pointers)
+ weechat_hashtable_free (pointers);
+ if (extra_vars)
+ weechat_hashtable_free (extra_vars);
+
+ API_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat_tcl_api_mkdir_home: create a directory in WeeChat home
*/
@@ -2372,7 +2411,9 @@ weechat_tcl_api_key_bind (ClientData clientData, Tcl_Interp *interp,
context = Tcl_GetStringFromObj (objv[1], &i);
hashtable = weechat_tcl_dict_to_hashtable (interp, objv[2],
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
num_keys = weechat_key_bind (context, hashtable);
@@ -2973,7 +3014,9 @@ weechat_tcl_api_hook_process_hashtable (ClientData clientData,
command = Tcl_GetStringFromObj (objv[1], &i);
options = weechat_tcl_dict_to_hashtable (interp, objv[2],
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
function = Tcl_GetStringFromObj (objv[4], &i);
data = Tcl_GetStringFromObj (objv[5], &i);
@@ -3416,7 +3459,9 @@ weechat_tcl_api_hook_hsignal_send (ClientData clientData, Tcl_Interp *interp,
signal = Tcl_GetStringFromObj (objv[1], &i);
hashtable = weechat_tcl_dict_to_hashtable (interp, objv[2],
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
weechat_hook_hsignal_send (signal, hashtable);
@@ -5320,7 +5365,9 @@ weechat_tcl_api_info_get_hashtable (ClientData clientData, Tcl_Interp *interp,
API_WRONG_ARGS(API_RETURN_EMPTY);
hashtable = weechat_tcl_dict_to_hashtable (interp, objv[2],
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
result_hashtable = weechat_info_get_hashtable (Tcl_GetStringFromObj (objv[1], &i),
hashtable);
@@ -6178,7 +6225,9 @@ weechat_tcl_api_hdata_update (ClientData clientData, Tcl_Interp *interp,
hdata = Tcl_GetStringFromObj (objv[1], &i);
pointer = Tcl_GetStringFromObj (objv[2], &i);
hashtable = weechat_tcl_dict_to_hashtable (interp, objv[3],
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
value = weechat_hdata_update (API_STR2PTR(hdata),
API_STR2PTR(pointer),
@@ -6495,6 +6544,7 @@ void weechat_tcl_api_init (Tcl_Interp *interp)
API_DEF_FUNC(string_remove_color);
API_DEF_FUNC(string_is_command_char);
API_DEF_FUNC(string_input_for_buffer);
+ API_DEF_FUNC(string_eval_expression);
API_DEF_FUNC(mkdir_home);
API_DEF_FUNC(mkdir);
API_DEF_FUNC(mkdir_parents);
diff --git a/src/plugins/tcl/weechat-tcl.c b/src/plugins/tcl/weechat-tcl.c
index 26095c467..95a55fe71 100644
--- a/src/plugins/tcl/weechat-tcl.c
+++ b/src/plugins/tcl/weechat-tcl.c
@@ -125,24 +125,23 @@ weechat_tcl_hashtable_to_dict (Tcl_Interp *interp,
/*
* weechat_tcl_dict_to_hashtable: get WeeChat hashtable with tcl dict
- * Hashtable returned has type string for
- * both keys and values
* Note: hashtable has to be released after
* use with call to weechat_hashtable_free()
*/
struct t_hashtable *
weechat_tcl_dict_to_hashtable (Tcl_Interp *interp, Tcl_Obj *dict,
- int hashtable_size)
+ int size, const char *type_keys,
+ const char *type_values)
{
struct t_hashtable *hashtable;
Tcl_DictSearch search;
Tcl_Obj *key, *value;
int done;
- hashtable = weechat_hashtable_new (hashtable_size,
- WEECHAT_HASHTABLE_STRING,
- WEECHAT_HASHTABLE_STRING,
+ hashtable = weechat_hashtable_new (size,
+ type_keys,
+ type_values,
NULL,
NULL);
if (!hashtable)
@@ -152,9 +151,20 @@ weechat_tcl_dict_to_hashtable (Tcl_Interp *interp, Tcl_Obj *dict,
{
for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done))
{
- weechat_hashtable_set (hashtable,
- Tcl_GetString (key),
- Tcl_GetString (value));
+ if (strcmp (type_values, WEECHAT_HASHTABLE_STRING) == 0)
+ {
+ weechat_hashtable_set (hashtable,
+ Tcl_GetString (key),
+ Tcl_GetString (value));
+ }
+ else if (strcmp (type_values, WEECHAT_HASHTABLE_POINTER) == 0)
+ {
+ weechat_hashtable_set (hashtable,
+ Tcl_GetString (key),
+ plugin_script_str2ptr (weechat_tcl_plugin,
+ NULL, NULL,
+ Tcl_GetString (value)));
+ }
}
}
Tcl_DictObjDone(&search);
@@ -246,7 +256,9 @@ weechat_tcl_exec (struct t_plugin_script *script,
{
ret_val = weechat_tcl_dict_to_hashtable (interp,
Tcl_GetObjResult (interp),
- WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE);
+ WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING);
}
tcl_current_script = old_tcl_script;
diff --git a/src/plugins/tcl/weechat-tcl.h b/src/plugins/tcl/weechat-tcl.h
index 62a258885..65453fc83 100644
--- a/src/plugins/tcl/weechat-tcl.h
+++ b/src/plugins/tcl/weechat-tcl.h
@@ -39,7 +39,9 @@ extern Tcl_Obj *weechat_tcl_hashtable_to_dict (Tcl_Interp *interp,
struct t_hashtable *hashtable);
extern struct t_hashtable *weechat_tcl_dict_to_hashtable (Tcl_Interp *interp,
Tcl_Obj *dict,
- int hashtable_size);
+ int size,
+ const char *type_keys,
+ const char *type_values);
extern void *weechat_tcl_exec (struct t_plugin_script *script,
int ret_type, const char *function,
const char *format, void **argv);
diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h
index b70c75de4..8b55e560c 100644
--- a/src/plugins/weechat-plugin.h
+++ b/src/plugins/weechat-plugin.h
@@ -50,7 +50,7 @@ struct timeval;
* please change the date with current one; for a second change at same
* date, increment the 01, otherwise please keep 01.
*/
-#define WEECHAT_PLUGIN_API_VERSION "20121014-01"
+#define WEECHAT_PLUGIN_API_VERSION "20121102-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -251,6 +251,9 @@ struct t_weechat_plugin
int (*string_decode_base64) (const char *from, char *to);
int (*string_is_command_char) (const char *string);
const char *(*string_input_for_buffer) (const char *string);
+ char *(*string_eval_expression )(const char *expr,
+ struct t_hashtable *pointers,
+ struct t_hashtable *extra_vars);
/* UTF-8 strings */
int (*utf8_has_8bits) (const char *string);
@@ -1009,6 +1012,10 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
weechat_plugin->string_is_command_char(__string)
#define weechat_string_input_for_buffer(__string) \
weechat_plugin->string_input_for_buffer(__string)
+#define weechat_string_eval_expression(__expr, __pointers, \
+ __extra_vars) \
+ weechat_plugin->string_eval_expression(__expr, __pointers, \
+ __extra_vars) \
/* UTF-8 strings */
#define weechat_utf8_has_8bits(__string) \