1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-04 16:53:14 +02:00

trigger: add support of variable in regex option

Examples with new format:
  /regex/text/
  /regex/text/var
  /regex1/text1/ /regex2/text2/
  /regex1/text1/var /regex2/text2/var
This commit is contained in:
Sebastien Helleu
2014-01-26 19:59:55 +01:00
parent bcff9162a7
commit be8e32dd1b
5 changed files with 196 additions and 158 deletions
+60 -59
View File
@@ -67,41 +67,66 @@ trigger_callback_check_conditions (struct t_trigger *trigger,
/*
* Replaces text using one or more regex in the trigger.
*
* Note: result must be freed after use.
*/
char *
trigger_callback_replace_regex (struct t_trigger *trigger, const char *name,
const char *value)
void
trigger_callback_replace_regex (struct t_trigger *trigger,
struct t_hashtable *extra_vars)
{
char *temp, *res;
char *value;
const char *ptr_key, *ptr_value;
int i;
if (trigger->regex_count == 0)
return strdup (value);
res = NULL;
return;
for (i = 0; i < trigger->regex_count; i++)
{
temp = weechat_string_replace_regex ((res) ? res : value,
trigger->regex[i].regex,
trigger->regex[i].replace_eval);
if (!temp)
return res;
res = temp;
ptr_key = (trigger->regex[i].variable) ?
trigger->regex[i].variable :
trigger_hook_regex_default_var[weechat_config_integer (trigger->options[TRIGGER_OPTION_HOOK])];
if (!ptr_key || !ptr_key[0])
{
if (trigger_buffer)
{
weechat_printf_tags (trigger_buffer, "no_trigger",
"\t regex %d: %s",
i + 1, _("no variable"));
}
continue;
}
ptr_value = weechat_hashtable_get (extra_vars, ptr_key);
if (!ptr_value)
{
if (trigger_buffer)
{
weechat_printf_tags (trigger_buffer, "no_trigger",
"\t regex %d (%s): %s",
i + 1, ptr_key, _("empty variable"));
}
continue;
}
value = weechat_string_replace_regex (ptr_value,
trigger->regex[i].regex,
trigger->regex[i].replace_eval);
if (!value)
continue;
/* display debug info on trigger buffer */
if (trigger_buffer)
{
weechat_printf_tags (trigger_buffer, "no_trigger",
"\t %s (regex %d): \"%s%s\"",
name, i + 1, res, weechat_color ("reset"));
"\t regex %d (%s): \"%s%s\"",
i + 1, ptr_key, value,
weechat_color ("reset"));
}
}
return res;
weechat_hashtable_set (extra_vars, ptr_key, value);
free (value);
}
}
/*
@@ -157,7 +182,7 @@ trigger_callback_signal_cb (void *data, const char *signal,
struct t_trigger *trigger;
struct t_hashtable *extra_vars;
const char *command, *ptr_signal_data;
char str_data[128], *signal_data2;
char str_data[128];
int rc;
/* get trigger pointer, return immediately if not found or trigger running */
@@ -234,17 +259,7 @@ trigger_callback_signal_cb (void *data, const char *signal,
goto end;
/* replace text with regex */
if (trigger->regex_count > 0)
{
signal_data2 = trigger_callback_replace_regex (trigger,
"tg_signal_data",
ptr_signal_data);
if (signal_data2)
{
weechat_hashtable_set (extra_vars, "tg_signal_data", signal_data2);
free (signal_data2);
}
}
trigger_callback_replace_regex (trigger, extra_vars);
/* execute command */
trigger_callback_run_command (trigger, NULL, NULL, extra_vars);
@@ -252,7 +267,9 @@ trigger_callback_signal_cb (void *data, const char *signal,
end:
if (extra_vars)
weechat_hashtable_free (extra_vars);
trigger->hook_running = 0;
return rc;
}
@@ -281,7 +298,7 @@ trigger_callback_modifier_cb (void *data, const char *modifier,
{
struct t_trigger *trigger;
struct t_hashtable *extra_vars;
const char *command;
const char *command, *ptr_string;
char *string_modified, *pos, *pos2, *plugin_name, *buffer_name;
char *buffer_full_name, *tags;
int no_trigger, length;
@@ -297,7 +314,6 @@ trigger_callback_modifier_cb (void *data, const char *modifier,
trigger->hook_running = 1;
extra_vars = NULL;
string_modified = NULL;
/*
* in a modifier, the only possible actions are regex or command;
@@ -400,29 +416,21 @@ trigger_callback_modifier_cb (void *data, const char *modifier,
goto end;
/* replace text with regex */
if (trigger->regex_count > 0)
{
string_modified = trigger_callback_replace_regex (trigger, "tg_string",
string);
if (string_modified)
{
weechat_hashtable_set (extra_vars, "tg_string", string_modified);
if (strcmp (string, string_modified) == 0)
{
/* regex did not change the string, ignore it */
free (string_modified);
string_modified = NULL;
}
}
}
trigger_callback_replace_regex (trigger, extra_vars);
/* execute command */
trigger_callback_run_command (trigger, NULL, NULL, extra_vars);
end:
ptr_string = weechat_hashtable_get (extra_vars, "tg_string");
string_modified = (ptr_string && (strcmp (ptr_string, string) != 0)) ?
strdup (ptr_string) : NULL;
if (extra_vars)
weechat_hashtable_free (extra_vars);
trigger->hook_running = 0;
return string_modified;
}
@@ -439,7 +447,7 @@ trigger_callback_print_cb (void *data, struct t_gui_buffer *buffer,
struct t_trigger *trigger;
struct t_hashtable *pointers, *extra_vars;
const char *command, *localvar_type;
char *message2, *str_tags, *str_tags2, str_temp[128];
char *str_tags, *str_tags2, str_temp[128];
int i, rc, length, tag_notify_private;
struct tm *date_tmp;
@@ -556,16 +564,7 @@ trigger_callback_print_cb (void *data, struct t_gui_buffer *buffer,
goto end;
/* replace text with regex */
if (trigger->regex_count > 0)
{
message2 = trigger_callback_replace_regex (trigger, "tg_message",
message);
if (message2)
{
weechat_hashtable_set (extra_vars, "tg_message", message2);
free (message2);
}
}
trigger_callback_replace_regex (trigger, extra_vars);
/* execute command */
trigger_callback_run_command (trigger, buffer, pointers, extra_vars);
@@ -575,7 +574,9 @@ end:
weechat_hashtable_free (pointers);
if (extra_vars)
weechat_hashtable_free (extra_vars);
trigger->hook_running = 0;
return rc;
}
+10 -4
View File
@@ -102,13 +102,19 @@ trigger_command_trigger (void *data, struct t_gui_buffer *buffer, int argc,
for (i = 0; i < ptr_trigger->regex_count; i++)
{
weechat_printf_tags (NULL, "no_trigger",
" regex %d: %s%s %s-->%s %s",
" regex %d%s%s%s: "
"%s\"%s%s%s\" --> \"%s%s%s\"",
i + 1,
(ptr_trigger->regex[i].variable) ? " (" : "",
(ptr_trigger->regex[i].variable) ? ptr_trigger->regex[i].variable : "",
(ptr_trigger->regex[i].variable) ? ")" : "",
weechat_color ("chat_delimiters"),
weechat_color (weechat_config_string (trigger_config_color_regex)),
ptr_trigger->regex[i].str_regex,
weechat_color ("chat_delimiters"),
weechat_color (weechat_config_string (trigger_config_color_replace)),
ptr_trigger->regex[i].replace);
ptr_trigger->regex[i].replace,
weechat_color ("chat_delimiters"));
}
option = weechat_config_string (ptr_trigger->options[TRIGGER_OPTION_COMMAND]);
if (option && option[0])
@@ -408,8 +414,8 @@ trigger_command_init ()
" add text attributes in *bold*, _underline_ and /italic/:\n"
" /trigger add effects modifier weechat_print\n"
" /trigger set effects regex "
"==\\*(\\S+)\\*==*${color:bold}\\1${color:-bold}*"
"==_(\\S+)_==_${color:underline}\\1${color:-underline}_"
"==\\*(\\S+)\\*==*${color:bold}\\1${color:-bold}*== "
"==_(\\S+)_==_${color:underline}\\1${color:-underline}_== "
"==/(\\S+)/==/${color:italic}\\1${color:-italic}/"),
"list"
" || add %(trigger_names) %(trigger_hooks)"
+6 -1
View File
@@ -173,7 +173,12 @@ trigger_config_create_option (const char *trigger_name, int index_option,
N_("replace text with a POSIX extended regular expression (it "
"is done only if conditions are OK, and before running the "
"command) (note: content is evaluated on trigger creation, "
"see /help eval)"),
"see /help eval); format is: \"/regex/replace/var\" (var "
"is the hashtable variable to replace, it is optional), "
"many regex can be separated by a space, for example: "
"\"/regex1/replace1/var1 /regex2/replace2/var2\"; the "
"separator \"/\" can be replaced by any char (one or more "
"identical chars), except '\\' and parentheses"),
NULL, 0, 0, value, NULL, 0,
NULL, NULL, &trigger_config_change_regex, NULL, NULL, NULL);
break;
+116 -92
View File
@@ -50,6 +50,9 @@ char *trigger_option_default[TRIGGER_NUM_OPTIONS] =
char *trigger_hook_type_string[TRIGGER_NUM_HOOK_TYPES] =
{ "signal", "hsignal", "modifier", "print", "timer" };
char *trigger_hook_regex_default_var[TRIGGER_NUM_HOOK_TYPES] =
{ "tg_signal_data", "", "tg_string", "tg_message", "" };
char *trigger_return_code_string[TRIGGER_NUM_RETURN_CODES] =
{ "ok", "ok_eat", "error" };
int trigger_return_code[TRIGGER_NUM_RETURN_CODES] =
@@ -199,6 +202,8 @@ trigger_free_regex (struct t_trigger *trigger)
{
for (i = 0; i < trigger->regex_count; i++)
{
if (trigger->regex[i].variable)
free (trigger->regex[i].variable);
if (trigger->regex[i].str_regex)
free (trigger->regex[i].str_regex);
if (trigger->regex[i].regex)
@@ -224,9 +229,11 @@ trigger_free_regex (struct t_trigger *trigger)
void
trigger_set_regex (struct t_trigger *trigger)
{
const char *option_regex, *pos, *pos2;
const char *option_regex, *ptr_option, *pos, *pos_replace, *pos_replace_end;
const char *pos_next_regex;
char *delimiter;
int i, length_delimiter, regex_count;
int index, length_delimiter;
struct t_trigger_regex *new_regex;
delimiter = NULL;
@@ -242,122 +249,133 @@ trigger_set_regex (struct t_trigger *trigger)
if (strlen (option_regex) < 3)
goto format_error;
/* search the delimiter (which can be more than one char) */
pos = weechat_utf8_next_char (option_regex);
while (pos[0] && weechat_utf8_charcmp (option_regex, pos) == 0)
/* parse regular expressions in the option */
ptr_option = option_regex;
while (ptr_option && ptr_option[0])
{
pos = weechat_utf8_next_char (pos);
}
if (!pos[0])
goto format_error;
delimiter = weechat_strndup (option_regex, pos - option_regex);
if (!delimiter)
goto memory_error;
if (strcmp (delimiter, "\\") == 0)
goto format_error;
if (delimiter)
{
free (delimiter);
delimiter = NULL;
}
length_delimiter = strlen (delimiter);
/* count the number of regex in the option */
regex_count = 0;
pos = option_regex;
while (pos && pos[0])
{
/*
* if option "regex" ends with a delimiter, just ignore it
* and exit the loop
*/
pos += length_delimiter;
/* search the delimiter (which can be more than one char) */
pos = weechat_utf8_next_char (ptr_option);
while (pos[0] && (weechat_utf8_charcmp (ptr_option, pos) == 0))
{
pos = weechat_utf8_next_char (pos);
}
if (!pos[0])
break;
/* search the start of replacement string */
pos = strstr (pos + length_delimiter, delimiter);
if (!pos)
goto format_error;
delimiter = weechat_strndup (ptr_option, pos - ptr_option);
if (!delimiter)
goto memory_error;
if ((strcmp (delimiter, "\\") == 0) || (strcmp (delimiter, "(") == 0))
goto format_error;
regex_count++;
length_delimiter = strlen (delimiter);
/* search the start of next regex */
pos = strstr (pos + length_delimiter, delimiter);
}
ptr_option = pos;
if (!ptr_option[0])
goto format_error;
/* at least one regex is needed */
if (regex_count == 0)
goto format_error;
/* search the start of replacement string */
pos_replace = strstr (ptr_option, delimiter);
if (!pos_replace)
goto format_error;
/* allocate with array of regex/replacement */
trigger->regex = malloc (regex_count * sizeof (trigger->regex[0]));
if (!trigger->regex)
goto memory_error;
/* search the end of replacement string */
pos_replace_end = strstr (pos_replace + length_delimiter, delimiter);
/* initialize regex */
for (i = 0; i < trigger->regex_count; i++)
{
trigger->regex[i].str_regex = NULL;
trigger->regex[i].regex = NULL;
trigger->regex[i].replace = NULL;
trigger->regex[i].replace_eval = NULL;
}
trigger->regex_count = regex_count;
/* allocate regex and replacement */
i = 0;
pos = option_regex;
while (pos && pos[0])
{
pos += length_delimiter;
if (!pos[0])
break;
pos2 = strstr (pos + length_delimiter, delimiter);
if (!pos)
break;
trigger->regex[i].str_regex = weechat_strndup (pos, pos2 - pos);
if (!trigger->regex[i].str_regex)
new_regex = realloc (trigger->regex,
(trigger->regex_count + 1) * sizeof (trigger->regex[0]));
if (!new_regex)
goto memory_error;
trigger->regex[i].regex = malloc (sizeof (*trigger->regex[i].regex));
if (!trigger->regex[i].regex)
trigger->regex = new_regex;
trigger->regex_count++;
index = trigger->regex_count - 1;
/* initialize new regex */
trigger->regex[index].variable = NULL;
trigger->regex[index].str_regex = NULL;
trigger->regex[index].regex = NULL;
trigger->regex[index].replace = NULL;
trigger->regex[index].replace_eval = NULL;
/* set string with regex */
trigger->regex[index].str_regex = weechat_strndup (ptr_option,
pos_replace - ptr_option);
if (!trigger->regex[index].str_regex)
goto memory_error;
if (weechat_string_regcomp (trigger->regex[i].regex,
trigger->regex[i].str_regex,
/* set regex */
trigger->regex[index].regex = malloc (sizeof (*trigger->regex[index].regex));
if (!trigger->regex[index].regex)
goto memory_error;
if (weechat_string_regcomp (trigger->regex[index].regex,
trigger->regex[index].str_regex,
REG_EXTENDED | REG_ICASE) != 0)
{
weechat_printf (NULL,
_("%s%s: error compiling regular expression \"%s\""),
weechat_prefix ("error"), TRIGGER_PLUGIN_NAME,
trigger->regex[i].str_regex);
free (trigger->regex[i].regex);
trigger->regex[i].regex = NULL;
trigger->regex[index].str_regex);
free (trigger->regex[index].regex);
trigger->regex[index].regex = NULL;
goto end;
}
pos = pos2 + length_delimiter;
pos2 = strstr (pos + length_delimiter, delimiter);
trigger->regex[i].replace = (pos2) ?
weechat_strndup (pos, pos2 - pos) : strdup (pos);
if (!trigger->regex[i].replace)
/* set replace and replace_eval */
trigger->regex[index].replace = (pos_replace_end) ?
weechat_strndup (pos_replace + length_delimiter,
pos_replace_end - pos_replace - length_delimiter) :
strdup (pos_replace + length_delimiter);
if (!trigger->regex[index].replace)
goto memory_error;
trigger->regex[i].replace_eval =
weechat_string_eval_expression (trigger->regex[i].replace,
trigger->regex[index].replace_eval =
weechat_string_eval_expression (trigger->regex[index].replace,
NULL, NULL, NULL);
if (!trigger->regex[index].replace_eval)
goto memory_error;
pos = pos2;
if (!pos_replace_end)
break;
i++;
/* set variable (optional) */
ptr_option = pos_replace_end + length_delimiter;
if (!ptr_option[0])
break;
if (ptr_option[0] == ' ')
pos_next_regex = ptr_option;
else
{
pos_next_regex = strchr (ptr_option, ' ');
trigger->regex[index].variable = (pos_next_regex) ?
weechat_strndup (ptr_option, pos_next_regex - ptr_option) :
strdup (ptr_option);
if (!trigger->regex[index].variable)
goto memory_error;
}
if (!pos_next_regex)
break;
/* skip spaces before next regex */
ptr_option = pos_next_regex + 1;
while (ptr_option[0] == ' ')
{
ptr_option++;
}
}
goto end;
format_error:
weechat_printf (NULL,
_("%s%s: invalid value for option \"replace\", format "
"is: \"/regex/replace\" (the char '/' can be "
"replaced by one or more identical chars, except '\\' "
"which is used for matching groups)"),
weechat_prefix ("error"), TRIGGER_PLUGIN_NAME);
_("%s%s: invalid value for option \"regex\", "
"see /help trigger.trigger.%s.regex"),
weechat_prefix ("error"), TRIGGER_PLUGIN_NAME,
trigger->name);
trigger_free_regex (trigger);
goto end;
@@ -792,10 +810,16 @@ trigger_print_log ()
weechat_log_printf (" regex . . . . . . . . . : 0x%lx", ptr_trigger->regex);
for (i = 0; i < ptr_trigger->regex_count; i++)
{
weechat_log_printf (" regex[%03d].regex. . . : 0x%lx",
weechat_log_printf (" regex[%03d].variable . . : '%s'",
i, ptr_trigger->regex[i].variable);
weechat_log_printf (" regex[%03d].str_regex. . : '%s'",
i, ptr_trigger->regex[i].str_regex);
weechat_log_printf (" regex[%03d].regex. . . . : 0x%lx",
i, ptr_trigger->regex[i].regex);
weechat_log_printf (" regex[%03d].replace. . : '%s'",
weechat_log_printf (" regex[%03d].replace. . . : '%s'",
i, ptr_trigger->regex[i].replace);
weechat_log_printf (" regex[%03d].replace_eval : '%s'",
i, ptr_trigger->regex[i].replace_eval);
}
weechat_log_printf (" hooks_count . . . . . . : %d", ptr_trigger->hooks_count);
weechat_log_printf (" hooks . . . . . . . . . : 0x%lx", ptr_trigger->hooks);
@@ -900,8 +924,8 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
(void) plugin;
trigger_config_write ();
trigger_free_all ();
trigger_config_free ();
trigger_callback_end ();
return WEECHAT_RC_OK;
+4 -2
View File
@@ -60,6 +60,7 @@ enum t_trigger_return_code
struct t_trigger_regex
{
char *variable; /* the hashtable key used */
char *str_regex; /* regex to search for replacement */
regex_t *regex; /* compiled regex */
char *replace; /* replacement text */
@@ -75,8 +76,8 @@ struct t_trigger
/* internal vars */
/* regular expressions with their replacement text */
int regex_count; /* number of regex/replacement */
struct t_trigger_regex *regex; /* array of regex/replacement */
int regex_count; /* number of regex */
struct t_trigger_regex *regex; /* array of regex */
/* hooks */
int hooks_count; /* number of hooks */
@@ -95,6 +96,7 @@ extern struct t_weechat_plugin *weechat_trigger_plugin;
extern char *trigger_option_string[];
extern char *trigger_option_default[];
extern char *trigger_hook_type_string[];
extern char *trigger_hook_regex_default_var[];
extern int trigger_return_code[];
extern struct t_trigger *triggers;
extern struct t_trigger *last_trigger;