diff options
-rw-r--r-- | src/plugins/trigger/trigger-callback.c | 119 | ||||
-rw-r--r-- | src/plugins/trigger/trigger-command.c | 14 | ||||
-rw-r--r-- | src/plugins/trigger/trigger-config.c | 7 | ||||
-rw-r--r-- | src/plugins/trigger/trigger.c | 206 | ||||
-rw-r--r-- | src/plugins/trigger/trigger.h | 6 |
5 files changed, 195 insertions, 157 deletions
diff --git a/src/plugins/trigger/trigger-callback.c b/src/plugins/trigger/trigger-callback.c index a40e83585..38dd3dc15 100644 --- a/src/plugins/trigger/trigger-callback.c +++ b/src/plugins/trigger/trigger-callback.c @@ -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; } diff --git a/src/plugins/trigger/trigger-command.c b/src/plugins/trigger/trigger-command.c index bfba7b064..5fef8e632 100644 --- a/src/plugins/trigger/trigger-command.c +++ b/src/plugins/trigger/trigger-command.c @@ -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)" diff --git a/src/plugins/trigger/trigger-config.c b/src/plugins/trigger/trigger-config.c index d78bbcb2a..3e5340bf5 100644 --- a/src/plugins/trigger/trigger-config.c +++ b/src/plugins/trigger/trigger-config.c @@ -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; diff --git a/src/plugins/trigger/trigger.c b/src/plugins/trigger/trigger.c index de1ee1797..315c58968 100644 --- a/src/plugins/trigger/trigger.c +++ b/src/plugins/trigger/trigger.c @@ -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; - - length_delimiter = strlen (delimiter); + if (delimiter) + { + free (delimiter); + delimiter = NULL; + } - /* 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++; - - /* search the start of next regex */ - pos = strstr (pos + length_delimiter, delimiter); - } - - /* at least one regex is needed */ - if (regex_count == 0) - goto format_error; + length_delimiter = strlen (delimiter); - /* allocate with array of regex/replacement */ - trigger->regex = malloc (regex_count * sizeof (trigger->regex[0])); - if (!trigger->regex) - goto memory_error; + ptr_option = pos; + if (!ptr_option[0]) + goto format_error; - /* 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; + /* search the start of replacement string */ + pos_replace = strstr (ptr_option, delimiter); + if (!pos_replace) + goto format_error; - /* allocate regex and replacement */ - i = 0; - pos = option_regex; - while (pos && pos[0]) - { - pos += length_delimiter; - if (!pos[0]) - break; + /* search the end of replacement string */ + pos_replace_end = strstr (pos_replace + length_delimiter, delimiter); - pos2 = strstr (pos + length_delimiter, delimiter); - if (!pos) - break; + new_regex = realloc (trigger->regex, + (trigger->regex_count + 1) * sizeof (trigger->regex[0])); + if (!new_regex) + goto memory_error; - trigger->regex[i].str_regex = weechat_strndup (pos, pos2 - pos); - if (!trigger->regex[i].str_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; - trigger->regex[i].regex = malloc (sizeof (*trigger->regex[i].regex)); - if (!trigger->regex[i].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[i].regex, - trigger->regex[i].str_regex, + 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; + + /* 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; - i++; + /* 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; diff --git a/src/plugins/trigger/trigger.h b/src/plugins/trigger/trigger.h index 8b3cffc51..ed7a05b54 100644 --- a/src/plugins/trigger/trigger.h +++ b/src/plugins/trigger/trigger.h @@ -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; |