summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.adoc1
-rw-r--r--doc/de/weechat_user.de.adoc151
-rw-r--r--doc/en/weechat_user.en.adoc131
-rw-r--r--doc/fr/weechat_user.fr.adoc132
-rw-r--r--doc/it/weechat_user.it.adoc127
-rw-r--r--doc/ja/weechat_user.ja.adoc149
-rw-r--r--doc/pl/weechat_user.pl.adoc147
-rw-r--r--doc/sr/weechat_user.sr.adoc139
-rw-r--r--src/plugins/trigger/trigger-callback.c140
-rw-r--r--src/plugins/trigger/trigger-callback.h2
-rw-r--r--src/plugins/trigger/trigger.c90
-rw-r--r--src/plugins/trigger/trigger.h13
-rw-r--r--tests/unit/plugins/trigger/test-trigger.cpp160
13 files changed, 1075 insertions, 307 deletions
diff --git a/ChangeLog.adoc b/ChangeLog.adoc
index 79ace8088..1ab59c1a8 100644
--- a/ChangeLog.adoc
+++ b/ChangeLog.adoc
@@ -21,6 +21,7 @@ https://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes]
New features::
* core: allow command `/toggle` to create option before setting the value, if allowed in the section (issue #1837)
+ * trigger: add regex command "y" to translate chars, set default regex command to "s" (regex replace) (issue #1510)
Bug fixes::
diff --git a/doc/de/weechat_user.de.adoc b/doc/de/weechat_user.de.adoc
index f7c86c5cf..305a3dd6e 100644
--- a/doc/de/weechat_user.de.adoc
+++ b/doc/de/weechat_user.de.adoc
@@ -4942,19 +4942,120 @@ zu werden:
${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})
----
+// TRANSLATION MISSING
[[trigger_regex]]
-=== reguläre Ausdrücke
+=== Regular expression
-Reguläre Ausdrücke werden verwendet um Variablen in einem Callback Hashtable zu ändern.
+The regular expression is used to change variables in callback hashtable.
-Das Format ist: "/regex/replace" oder "/regex/replace/var" (wobei _var_ eine
-Variable eines Hashtable darstellt).
+Format is one of the following:
-Falls _var_ in der Hashtabelle nicht existieren sollte, wird diese automatisch mit einem
-leeren Wert angelegt. Damit kann man temporär benutzerspezifische Variablen erstellen.
+----
+/string1/string2
+s/string1/string2
+s/string1/string2/var
+y/string1/string2
+y/string1/string2/var
+----
+
+Fields:
+
+* `s` or `y`: a letter with the command; if missing, default command is `s`
+ and the first char is then used as the delimiter:
+** `s`: regex replacement: first string is a regular expression, second string
+ is the replacement for every matching string
+** `y`: chars translation: first string is a set of characters that are replaced
+ by the characters in the second string; once evaluated, each string must have
+ exactly the same number of UTF-8 chars
+* `/`: the regex delimiter; the char "/" can be replaced by any char
+ (one or more identical chars)
+* `string1`: the first string (use depends on the command)
+* `string2`: the second string (use depends on the command)
+* `var`: the hashtable variable to update
+
+Many regular expressions can be separated by a space, for example:
+
+----
+s/regex1/replace1/var1 y/abcdef/ABDDEF/var2
+----
+
+// TRANSLATION MISSING
+[[trigger_regex_replace]]
+==== Regex replace
+
+For the command `s`, the format is: `s/regex/replace` or `s/regex/replace/var`
+(where _var_ is a variable of the hashtable).
+
+As `s` is the default command, it can be omitted, so `/regex/replace` is also
+valid (but the first char, which is the delimiter, must not be a letter).
+
+Matching groups can be used in _replace_:
+
+* `+${re:0}+` to `+${re:99}+`: `+${re:0}+` is the whole match, `+${re:1}+` to
+ `+${re:99}+` are groups captured
+* `+${re:+}+`: the last match (with highest number)
+* `+${hide:c,${re:N}}+`: match "N" with all chars replaced by "c"
+ (example: `+${hide:*,${re:2}}+` is the group #2 with all chars replaced by
+ `+*+`).
+
+Example: use bold for words between `+*+`:
+
+----
+s/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
+----
+
+Example: default trigger _server_pass_ uses this regular expression to hide
+password in commands `/server` and `/connect` (chars in passwords are replaced
+by `+*+`):
+
+----
+s==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
+----
+
+[NOTE]
+In this example, the delimiter used is "==" because there is a "/" in the
+regular expression.
+
+// TRANSLATION MISSING
+[[trigger_regex_translate_chars]]
+==== Translate chars
+
+For the command `y`, the format is: `y/chars1/chars2` or `y/chars1/chars2/var`
+(where _var_ is a variable of the hashtable).
+
+Example: replace "a", "b" and "c" by upper case letter:
+
+----
+y/abc/ABC/
+----
-Sollte _var_ nicht näher spezifiziert sein, wird die Standard-Variable genutzt,
-welche abhängig von dem genutzten Hook ist:
+Example: rotate arrows clockwise:
+
+----
+y/←↑→↓/↑→↓←/
+----
+
+Example: convert all letters to lower case:
+
+----
+y/${chars:upper}/${chars:lower}/
+----
+
+Example: shift each letter by one position, preserving case: a→b, b→c … y→z, z→a:
+
+----
+y/${chars:a-z}${chars:A-Z}/${chars:b-z}a${chars:B-Z}A/
+----
+
+// TRANSLATION MISSING
+[[trigger_regex_variable]]
+==== Variable
+
+If _var_ does not exist in the hashtable, it is created automatically with an
+empty value. This allows to create custom temporary variables.
+
+If _var_ is not specified, the default variable is used, it depends on hook
+type:
[width="100%",cols="2,3,7",options="header"]
|===
@@ -4978,40 +5079,6 @@ welche abhängig von dem genutzten Hook ist:
haben einen Einfluss auf den Wert der vom Trigger zurückgegeben wird und dann von
WeeChat genutzt wird.
-Mehrere reguläre Ausdrücke können durch ein Leerzeichen voneinander
-getrennt werden, zum Beispiel:
-"/regex1/replace1/var1 /regex2/replace2/var2".
-
-Das Zeichen "/" kann durch jedes andere Zeichen ersetzt werden (ein
-oder mehrere identische Zeichen).
-
-Matching groups können in "replace" genutzt werden:
-
-* `+${re:0}+` bis `+${re:99}+`: `+${re:0}+` um alles zu matchen, `+${re:1}+` bis
- `+${re:99}+` um Gruppen zu fangen
-* `+${re:+}+`: der letzte match (mit der höchsten Nummer)
-* `+${hide:c,${re:N}}+`: match "N" mit allen Zeichen die durch "c" ersetzt wurden
- (Beispiel: `+${hide:*,${re:2}}+` ist die group #2 mit allen Zeichen die durch
- `+*+` ersetzt wurden).
-
-Beispiel: nutzte Fettschrift zwischen dem Zeichen `+*+`:
-
-----
-/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
-----
-
-Beispiel: der Standard-Trigger _server_pass_ nutzt folgenden regulären Ausdruck
-um ein Passwort in den Befehlen `/server` und `/connect` zu verbergen (die
-einzelnen Zeichen des Passwortes werden durch `+*+` ersetzt):
-
-----
-==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
-----
-
-[NOTE]
-In diesem Beispiel wird "==" als Trennzeichen verwendet, da ein "/" in
-dem regulären Ausdruck genutzt wird.
-
[[trigger_command]]
=== Befehl
diff --git a/doc/en/weechat_user.en.adoc b/doc/en/weechat_user.en.adoc
index 10f23bc78..afe02e2fe 100644
--- a/doc/en/weechat_user.en.adoc
+++ b/doc/en/weechat_user.en.adoc
@@ -4660,8 +4660,8 @@ A trigger has the following options (names are
<<command_weechat_eval,/eval>>).
| regex | string
-| One or more POSIX extended regular expressions, to change data received in the
- hook callback (and some stuff added by trigger plugin), see
+| One or more regex "commands" (similar to the `sed` command) to change data
+ received in the hook callback (and some stuff added by trigger plugin), see
<<trigger_regex,regular expression>>.
| command | string
@@ -4834,42 +4834,47 @@ ${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})
The regular expression is used to change variables in callback hashtable.
-The format is: "/regex/replace" or "/regex/replace/var" (where _var_ is a
-variable of the hashtable).
+Format is one of the following:
-If _var_ does not exist in the hashtable, it is created automatically with an
-empty value. This allows to create custom temporary variables.
+----
+/string1/string2
+s/string1/string2
+s/string1/string2/var
+y/string1/string2
+y/string1/string2/var
+----
-If _var_ is not specified, the default variable is used, it depends on hook
-type:
+Fields:
-[width="100%",cols="2,3,7",options="header"]
-|===
-| Hook | Default variable | Update allowed ^(1)^
-| signal | tg_signal_data |
-| hsignal | |
-| modifier | tg_string | tg_string
-| line | message | buffer, buffer_name, y, date, date_printed, str_time, tags, notify_level, highlight, prefix, message
-| print | tg_message |
-| command | tg_argv_eol1 |
-| command_run | tg_command |
-| timer | tg_remaining_calls |
-| config | tg_value |
-| focus | |
-| info | tg_info | tg_info
-| info_hashtable | | all variables received in hashtable
-|===
-
-[NOTE]
-^(1)^ All variables can be updated in the trigger, but only these variables
-have an effect on the value returned by the trigger and used by WeeChat.
+* `s` or `y`: a letter with the command; if missing, default command is `s`
+ and the first char is then used as the delimiter:
+** `s`: regex replacement: first string is a regular expression, second string
+ is the replacement for every matching string
+** `y`: chars translation: first string is a set of characters that are replaced
+ by the characters in the second string; once evaluated, each string must have
+ exactly the same number of UTF-8 chars
+* `/`: the regex delimiter; the char "/" can be replaced by any char
+ (one or more identical chars)
+* `string1`: the first string (use depends on the command)
+* `string2`: the second string (use depends on the command)
+* `var`: the hashtable variable to update
Many regular expressions can be separated by a space, for example:
-"/regex1/replace1/var1 /regex2/replace2/var2".
-The char "/" can be replaced by any char (one or more identical chars).
+----
+s/regex1/replace1/var1 y/abcdef/ABDDEF/var2
+----
+
+[[trigger_regex_replace]]
+==== Regex replace
+
+For the command `s`, the format is: `s/regex/replace` or `s/regex/replace/var`
+(where _var_ is a variable of the hashtable).
-Matching groups can be used in "replace":
+As `s` is the default command, it can be omitted, so `/regex/replace` is also
+valid (but the first char, which is the delimiter, must not be a letter).
+
+Matching groups can be used in _replace_:
* `+${re:0}+` to `+${re:99}+`: `+${re:0}+` is the whole match, `+${re:1}+` to
`+${re:99}+` are groups captured
@@ -4881,7 +4886,7 @@ Matching groups can be used in "replace":
Example: use bold for words between `+*+`:
----
-/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
+s/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
----
Example: default trigger _server_pass_ uses this regular expression to hide
@@ -4889,13 +4894,73 @@ password in commands `/server` and `/connect` (chars in passwords are replaced
by `+*+`):
----
-==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
+s==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
----
[NOTE]
In this example, the delimiter used is "==" because there is a "/" in the
regular expression.
+[[trigger_regex_translate_chars]]
+==== Translate chars
+
+For the command `y`, the format is: `y/chars1/chars2` or `y/chars1/chars2/var`
+(where _var_ is a variable of the hashtable).
+
+Example: replace "a", "b" and "c" by upper case letter:
+
+----
+y/abc/ABC/
+----
+
+Example: rotate arrows clockwise:
+
+----
+y/←↑→↓/↑→↓←/
+----
+
+Example: convert all letters to lower case:
+
+----
+y/${chars:upper}/${chars:lower}/
+----
+
+Example: shift each letter by one position, preserving case: a→b, b→c … y→z, z→a:
+
+----
+y/${chars:a-z}${chars:A-Z}/${chars:b-z}a${chars:B-Z}A/
+----
+
+[[trigger_regex_variable]]
+==== Variable
+
+If _var_ does not exist in the hashtable, it is created automatically with an
+empty value. This allows to create custom temporary variables.
+
+If _var_ is not specified, the default variable is used, it depends on hook
+type:
+
+[width="100%",cols="2,3,7",options="header"]
+|===
+| Hook | Default variable | Update allowed ^(1)^
+| signal | tg_signal_data |
+| hsignal | |
+| modifier | tg_string | tg_string
+| line | message | buffer, buffer_name, y, date, date_printed, str_time, tags, notify_level, highlight, prefix, message
+| print | tg_message |
+| command | tg_argv_eol1 |
+| command_run | tg_command |
+| timer | tg_remaining_calls |
+| config | tg_value |
+| focus | |
+| info | tg_info | tg_info
+| info_hashtable | | all variables received in hashtable
+|===
+
+[NOTE]
+^(1)^ All variables can be updated in the trigger, but only these variables
+have an effect on the value returned by the trigger and used by WeeChat.
+
[[trigger_command]]
=== Command
diff --git a/doc/fr/weechat_user.fr.adoc b/doc/fr/weechat_user.fr.adoc
index 6085d37d9..5f0198506 100644
--- a/doc/fr/weechat_user.fr.adoc
+++ b/doc/fr/weechat_user.fr.adoc
@@ -4989,44 +4989,48 @@ ${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})
L'expression régulière est utilisée pour modifier des variables dans la table
de hachage de la fonction de rappel.
-Le format est : "/regex/remplacement" ou "/regex/remplacement/var" (où _var_ est
-une variable de la table de hachage).
+Le format est l'un des suivants :
-Si _var_ n'existe pas dans la table de hachage, elle est automatiquement créée
-avec une valeur vide. Cela permet de créer des variables temporaires.
+----
+/chaîne1/chaîne2
+s/chaîne1/chaîne2
+s/chaîne1/chaîne2/var
+y/chaîne1/chaîne2
+y/chaîne1/chaîne2/var
+----
-Si _var_ n'est pas spécifiée, la variable par défaut est utilisée, elle dépend
-du type de hook :
+Champs :
-[width="100%",cols="2,3,7",options="header"]
-|===
-| Hook | Variable par défaut | Mise à jour autorisée ^(1)^
-| signal | tg_signal_data |
-| hsignal | |
-| modifier | tg_string | tg_string
-| line | message | buffer, buffer_name, y, date, date_printed, str_time, tags, notify_level, highlight, prefix, message
-| print | tg_message |
-| command | tg_argv_eol1 |
-| command_run | tg_command |
-| timer | tg_remaining_calls |
-| config | tg_value |
-| focus | |
-| info | tg_info | tg_info
-| info_hashtable | | toutes les variables reçues dans la table de hachage
-|===
+* `s` ou `y` : une lettre avec la commande ; si manquante, la commande par défaut
+ est `s` et le premier caractère est alors utilisé comme délimiteur :
+** `s` : remplacement par expression régulière : la première chaîne est l'expression
+ régulière, la seconde chaîne est le remplacement pour chaque chaîne trouvée
+** `y` : traduction de caractères : la première chaîne est un ensemble de caractères
+ qui sont remplacés par les caractères de la seconde chaîne ; une fois évaluée,
+ chaque chaîne doit contenir exactement le même nombre de caractères UTF-8
+* `/` : le délimiteur d'expression régulière ; le caractère "/" peut être remplacé
+ par n'importe quel caractère (un ou plusieurs caractères identiques)
+* `chaîne1` : la première chaîne (l'utilisation dépend de la commande)
+* `chaîne2` : la seconde chaîne (l'utilisation dépend de la commande)
+* `var` : la table de hachage avec la variable à mettre à jour
-[NOTE]
-^(1)^ Toutes les variables peuvent être mises à jour dans le trigger, mais
-seulement ces variables ont un effet sur la valeur retournée par le trigger
-et utilisée par WeeChat.
+Plusieurs expressions régulières peuvent être séparées par un espace, par exemple :
+
+----
+s/regex1/remplacement1/var1 y/abcdef/ABDDEF/var2
+----
+
+[[trigger_regex_replace]]
+==== Regex replace
-Plusieurs expressions régulières peuvent être séparées par un espace, par
-exemple : "/regex1/remplacement1/var1 /regex2/remplacement2/var2".
+Pour la commande `s`, le format est : `s/regex/remplacement` ou
+`s/regex/remplacement/var` (où _var_ est une variable de la table de hachage).
-Le caractère "/" peut être remplacé par tout caractère (un ou plusieurs
-caractères identiques).
+Comme `s` est la commande par défaut, elle peut être omise, donc `/regex/replace`
+est également valide (mais le premier caractère, qui est le délimiteur, ne doit
+pas être une lettre).
-Les groupes de correspondance peuvent être utilisés dans le "remplacement" :
+Les groupes de correspondance peuvent être utilisés dans le _remplacement_ :
* `+${re:0}+` à `+${re:99}+` : `+${re:0}+` est la correspondance complète, `+${re:1}+`
à `+${re:99}+` sont les groupes capturés
@@ -5038,7 +5042,7 @@ Les groupes de correspondance peuvent être utilisés dans le "remplacement" :
Exemple : utiliser du gras pour les mots entre `+*+` :
----
-/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
+s/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
----
Exemple : le trigger par défaut _server_pass_ utilise cette expression régulière
@@ -5046,13 +5050,75 @@ pour cacher le mot de passe dans les commandes `/server` et `/connect` (les
caractères des mots de passe sont remplacés par `+*+`) :
----
-==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
+s==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
----
[NOTE]
Dans cet exemple, le séparateur utilisé est "==" car il y a "/" dans
l'expression régulière.
+[[trigger_regex_translate_chars]]
+==== Translate chars
+
+Pour la commande `y`, le format est : `y/caractères1/caractères2` ou
+`y/caractères1/caractères2/var` (où _var_ est une variable de la table de hachage).
+
+Exemple : remplacer "a", "b" et "c" par la lettre en majuscules :
+
+----
+y/abc/ABC/
+----
+
+Exemple : faire tourner une flèche dans le sens horaire :
+
+----
+y/←↑→↓/↑→↓←/
+----
+
+Exemple : convertir toutes les lettres en minuscules :
+
+----
+y/${chars:upper}/${chars:lower}/
+----
+
+Exemple : décaler toutes les lettres d'une position, en préservant la casse :
+a→b, b→c … y→z, z→a :
+
+----
+y/${chars:a-z}${chars:A-Z}/${chars:b-z}a${chars:B-Z}A/
+----
+
+[[trigger_regex_variable]]
+==== Variable
+
+Si _var_ n'existe pas dans la table de hachage, elle est automatiquement créée
+avec une valeur vide. Cela permet de créer des variables temporaires.
+
+Si _var_ n'est pas spécifiée, la variable par défaut est utilisée, elle dépend
+du type de hook :
+
+[width="100%",cols="2,3,7",options="header"]
+|===
+| Hook | Variable par défaut | Mise à jour autorisée ^(1)^
+| signal | tg_signal_data |
+| hsignal | |
+| modifier | tg_string | tg_string
+| line | message | buffer, buffer_name, y, date, date_printed, str_time, tags, notify_level, highlight, prefix, message
+| print | tg_message |
+| command | tg_argv_eol1 |
+| command_run | tg_command |
+| timer | tg_remaining_calls |
+| config | tg_value |
+| focus | |
+| info | tg_info | tg_info
+| info_hashtable | | toutes les variables reçues dans la table de hachage
+|===
+
+[NOTE]
+^(1)^ Toutes les variables peuvent être mises à jour dans le trigger, mais
+seulement ces variables ont un effet sur la valeur retournée par le trigger
+et utilisée par WeeChat.
+
[[trigger_command]]
=== Commande
diff --git a/doc/it/weechat_user.it.adoc b/doc/it/weechat_user.it.adoc
index a0b8d5119..a75a68884 100644
--- a/doc/it/weechat_user.it.adoc
+++ b/doc/it/weechat_user.it.adoc
@@ -5177,42 +5177,47 @@ ${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})
The regular expression is used to change variables in callback hashtable.
-The format is: "/regex/replace" or "/regex/replace/var" (where _var_ is a
-variable of the hashtable).
+Format is one of the following:
-If _var_ does not exist in the hashtable, it is created automatically with an
-empty value. This allows to create custom temporary variables.
+----
+/string1/string2
+s/string1/string2
+s/string1/string2/var
+y/string1/string2
+y/string1/string2/var
+----
-If _var_ is not specified, the default variable is used, it depends on hook
-type:
+Fields:
-[width="100%",cols="2,3,7",options="header"]
-|===
-| Hook | Default variable | Update allowed ^(1)^
-| signal | tg_signal_data |
-| hsignal | |
-| modifier | tg_string | tg_string
-| line | message | buffer, buffer_name, y, date, date_printed, str_time, tags, notify_level, highlight, prefix, message
-| print | tg_message |
-| command | tg_argv_eol1 |
-| command_run | tg_command |
-| timer | tg_remaining_calls |
-| config | tg_value |
-| focus | |
-| info | tg_info | tg_info
-| info_hashtable | | all variables received in hashtable
-|===
-
-[NOTE]
-^(1)^ All variables can be updated in the trigger, but only these variables
-have an effect on the value returned by the trigger and used by WeeChat.
+* `s` or `y`: a letter with the command; if missing, default command is `s`
+ and the first char is then used as the delimiter:
+** `s`: regex replacement: first string is a regular expression, second string
+ is the replacement for every matching string
+** `y`: chars translation: first string is a set of characters that are replaced
+ by the characters in the second string; once evaluated, each string must have
+ exactly the same number of UTF-8 chars
+* `/`: the regex delimiter; the char "/" can be replaced by any char
+ (one or more identical chars)
+* `string1`: the first string (use depends on the command)
+* `string2`: the second string (use depends on the command)
+* `var`: the hashtable variable to update
Many regular expressions can be separated by a space, for example:
-"/regex1/replace1/var1 /regex2/replace2/var2".
-The char "/" can be replaced by any char (one or more identical chars).
+----
+s/regex1/replace1/var1 y/abcdef/ABDDEF/var2
+----
+
+[[trigger_regex_replace]]
+==== Regex replace
+
+For the command `s`, the format is: `s/regex/replace` or `s/regex/replace/var`
+(where _var_ is a variable of the hashtable).
-Matching groups can be used in "replace":
+As `s` is the default command, it can be omitted, so `/regex/replace` is also
+valid (but the first char, which is the delimiter, must not be a letter).
+
+Matching groups can be used in _replace_:
* `+${re:0}+` to `+${re:99}+`: `+${re:0}+` is the whole match, `+${re:1}+` to
`+${re:99}+` are groups captured
@@ -5224,7 +5229,7 @@ Matching groups can be used in "replace":
Example: use bold for words between `+*+`:
----
-/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
+s/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
----
Example: default trigger _server_pass_ uses this regular expression to hide
@@ -5232,13 +5237,73 @@ password in commands `/server` and `/connect` (chars in passwords are replaced
by `+*+`):
----
-==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
+s==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
----
[NOTE]
In this example, the delimiter used is "==" because there is a "/" in the
regular expression.
+[[trigger_regex_translate_chars]]
+==== Translate chars
+
+For the command `y`, the format is: `y/chars1/chars2` or `y/chars1/chars2/var`
+(where _var_ is a variable of the hashtable).
+
+Example: replace "a", "b" and "c" by upper case letter:
+
+----
+y/abc/ABC/
+----
+
+Example: rotate arrows clockwise:
+
+----
+y/←↑→↓/↑→↓←/
+----
+
+Example: convert all letters to lower case:
+
+----
+y/${chars:upper}/${chars:lower}/
+----
+
+Example: shift each letter by one position, preserving case: a→b, b→c … y→z, z→a:
+
+----
+y/${chars:a-z}${chars:A-Z}/${chars:b-z}a${chars:B-Z}A/
+----
+
+[[trigger_regex_variable]]
+==== Variable
+
+If _var_ does not exist in the hashtable, it is created automatically with an
+empty value. This allows to create custom temporary variables.
+
+If _var_ is not specified, the default variable is used, it depends on hook
+type:
+
+[width="100%",cols="2,3,7",options="header"]
+|===
+| Hook | Default variable | Update allowed ^(1)^
+| signal | tg_signal_data |
+| hsignal | |
+| modifier | tg_string | tg_string
+| line | message | buffer, buffer_name, y, date, date_printed, str_time, tags, notify_level, highlight, prefix, message
+| print | tg_message |
+| command | tg_argv_eol1 |
+| command_run | tg_command |
+| timer | tg_remaining_calls |
+| config | tg_value |
+| focus | |
+| info | tg_info | tg_info
+| info_hashtable | | all variables received in hashtable
+|===
+
+[NOTE]
+^(1)^ All variables can be updated in the trigger, but only these variables
+have an effect on the value returned by the trigger and used by WeeChat.
+
[[trigger_command]]
=== Command
diff --git a/doc/ja/weechat_user.ja.adoc b/doc/ja/weechat_user.ja.adoc
index 5494fcc2f..8bd7a5a6c 100644
--- a/doc/ja/weechat_user.ja.adoc
+++ b/doc/ja/weechat_user.ja.adoc
@@ -4985,19 +4985,120 @@ trigger.trigger.beep.post_action = none
${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})
----
+// TRANSLATION MISSING
[[trigger_regex]]
-=== 正規表現
+=== Regular expression
+
+The regular expression is used to change variables in callback hashtable.
+
+Format is one of the following:
+
+----
+/string1/string2
+s/string1/string2
+s/string1/string2/var
+y/string1/string2
+y/string1/string2/var
+----
+
+Fields:
+
+* `s` or `y`: a letter with the command; if missing, default command is `s`
+ and the first char is then used as the delimiter:
+** `s`: regex replacement: first string is a regular expression, second string
+ is the replacement for every matching string
+** `y`: chars translation: first string is a set of characters that are replaced
+ by the characters in the second string; once evaluated, each string must have
+ exactly the same number of UTF-8 chars
+* `/`: the regex delimiter; the char "/" can be replaced by any char
+ (one or more identical chars)
+* `string1`: the first string (use depends on the command)
+* `string2`: the second string (use depends on the command)
+* `var`: the hashtable variable to update
+
+Many regular expressions can be separated by a space, for example:
+
+----
+s/regex1/replace1/var1 y/abcdef/ABDDEF/var2
+----
+
+// TRANSLATION MISSING
+[[trigger_regex_replace]]
+==== Regex replace
+
+For the command `s`, the format is: `s/regex/replace` or `s/regex/replace/var`
+(where _var_ is a variable of the hashtable).
+
+As `s` is the default command, it can be omitted, so `/regex/replace` is also
+valid (but the first char, which is the delimiter, must not be a letter).
-正規表現はコールバックハッシュテーブル内の変数を変更するために使われます。
+Matching groups can be used in _replace_:
-書式: "/regex/replace" または "/regex/replace/var" (ここで
-_var_ はハッシュテーブルの変数)。
+* `+${re:0}+` to `+${re:99}+`: `+${re:0}+` is the whole match, `+${re:1}+` to
+ `+${re:99}+` are groups captured
+* `+${re:+}+`: the last match (with highest number)
+* `+${hide:c,${re:N}}+`: match "N" with all chars replaced by "c"
+ (example: `+${hide:*,${re:2}}+` is the group #2 with all chars replaced by
+ `+*+`).
-ハッシュテーブル内に _var_ が存在しない場合、空の値を持つ _var_
-が自動的に作られます。これを使うことで一時的な任意の変数を作れます。
+Example: use bold for words between `+*+`:
-_var_
-が指定されなかった場合、デフォルト変数を使います、これはフックの種類に依存します:
+----
+s/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
+----
+
+Example: default trigger _server_pass_ uses this regular expression to hide
+password in commands `/server` and `/connect` (chars in passwords are replaced
+by `+*+`):
+
+----
+s==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
+----
+
+[NOTE]
+In this example, the delimiter used is "==" because there is a "/" in the
+regular expression.
+
+// TRANSLATION MISSING
+[[trigger_regex_translate_chars]]
+==== Translate chars
+
+For the command `y`, the format is: `y/chars1/chars2` or `y/chars1/chars2/var`
+(where _var_ is a variable of the hashtable).
+
+Example: replace "a", "b" and "c" by upper case letter:
+
+----
+y/abc/ABC/
+----
+
+Example: rotate arrows clockwise:
+
+----
+y/←↑→↓/↑→↓←/
+----
+
+Example: convert all letters to lower case:
+
+----
+y/${chars:upper}/${chars:lower}/
+----
+
+Example: shift each letter by one position, preserving case: a→b, b→c … y→z, z→a:
+
+----
+y/${chars:a-z}${chars:A-Z}/${chars:b-z}a${chars:B-Z}A/
+----
+
+// TRANSLATION MISSING
+[[trigger_regex_variable]]
+==== Variable
+
+If _var_ does not exist in the hashtable, it is created automatically with an
+empty value. This allows to create custom temporary variables.
+
+If _var_ is not specified, the default variable is used, it depends on hook
+type:
[width="100%",cols="2,3,7",options="header"]
|===
@@ -5020,38 +5121,6 @@ _var_
^(1)^ トリガはすべての値を更新できますが、ここで挙げた変数だけがトリガによって返されて
WeeChat によって使われる値に影響を及ぼします
-複数の正規表現を使う場合は空白で区切ってください、例:
-"/regex1/replace1/var1 /regex2/replace2/var2"。
-
-文字 "/" を任意の文字 (1 つ以上の同じ文字) に変えることができます。
-
-マッチグループを "replace" の中で利用できます:
-
-* `+${re:0}+` から `+${re:99}+`: `+${re:0}+` はマッチ部分の全体、`+${re:1}+` から
- `+${re:99}+` はグループ化されたマッチ部分
-* `+${re:+}+`: 最後のマッチ部分 (最大のグループ番号を持つ)
-* `+${hide:c,${re:N}}+`: マッチグループ "N" のすべての文字を "c" で置換した文字列
- (例: `+${hide:*,${re:2}}+` はグループ #2 のすべての文字を `+*+`
- で置換した文字列)。
-
-例: `+*+` で囲まれた文字を太字にする:
-
-----
-/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
-----
-
-例: デフォルトトリガ _server_pass_ はこの正規表現を使って、`/server`
-と `/connect` コマンドのパスワードを隠しています (パスワード部分の文字を
-`*` で置換しています):
-
-----
-==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
-----
-
-[NOTE]
-この例では、区切り文字として "==" を使っています。これは正規表現内で
-"/" を使うためです。
-
[[trigger_command]]
=== コマンド
diff --git a/doc/pl/weechat_user.pl.adoc b/doc/pl/weechat_user.pl.adoc
index 9abb6e6f6..b7c4899e1 100644
--- a/doc/pl/weechat_user.pl.adoc
+++ b/doc/pl/weechat_user.pl.adoc
@@ -4904,19 +4904,120 @@ w przypadku podświetlenia lub otrzymania prywatnej wiadomości:
${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})
----
+// TRANSLATION MISSING
[[trigger_regex]]
-=== Wyrażenia regularne
+=== Regular expression
+
+The regular expression is used to change variables in callback hashtable.
+
+Format is one of the following:
+
+----
+/string1/string2
+s/string1/string2
+s/string1/string2/var
+y/string1/string2
+y/string1/string2/var
+----
+
+Fields:
+
+* `s` or `y`: a letter with the command; if missing, default command is `s`
+ and the first char is then used as the delimiter:
+** `s`: regex replacement: first string is a regular expression, second string
+ is the replacement for every matching string
+** `y`: chars translation: first string is a set of characters that are replaced
+ by the characters in the second string; once evaluated, each string must have
+ exactly the same number of UTF-8 chars
+* `/`: the regex delimiter; the char "/" can be replaced by any char
+ (one or more identical chars)
+* `string1`: the first string (use depends on the command)
+* `string2`: the second string (use depends on the command)
+* `var`: the hashtable variable to update
+
+Many regular expressions can be separated by a space, for example:
+
+----
+s/regex1/replace1/var1 y/abcdef/ABDDEF/var2
+----
+
+// TRANSLATION MISSING
+[[trigger_regex_replace]]
+==== Regex replace
+
+For the command `s`, the format is: `s/regex/replace` or `s/regex/replace/var`
+(where _var_ is a variable of the hashtable).
+
+As `s` is the default command, it can be omitted, so `/regex/replace` is also
+valid (but the first char, which is the delimiter, must not be a letter).
-Wyrażenia regularne są używane do zmiany zmiennych w tablicy hashy callbacka.
+Matching groups can be used in _replace_:
-Format: "/wyrażenie/zamień" lub "/wyrażenie/zamień/zmienna" (gdzie _zmienna_ to
-zmienna tablicy hashy).
+* `+${re:0}+` to `+${re:99}+`: `+${re:0}+` is the whole match, `+${re:1}+` to
+ `+${re:99}+` are groups captured
+* `+${re:+}+`: the last match (with highest number)
+* `+${hide:c,${re:N}}+`: match "N" with all chars replaced by "c"
+ (example: `+${hide:*,${re:2}}+` is the group #2 with all chars replaced by
+ `+*+`).
-Jeśli _zmienna_ nie istnieje w tablicy haszy zostanie automarycznie utworzona bez
-wartości. Pozwala to tworzyć dowolne zmienne tymczasowe.
+Example: use bold for words between `+*+`:
-Jeśli _zmienna_ nie zostanie podana, użyta zostanie domyślna zmienna, zależy ona
-od typu uchwytu:
+----
+s/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
+----
+
+Example: default trigger _server_pass_ uses this regular expression to hide
+password in commands `/server` and `/connect` (chars in passwords are replaced
+by `+*+`):
+
+----
+s==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
+----
+
+[NOTE]
+In this example, the delimiter used is "==" because there is a "/" in the
+regular expression.
+
+// TRANSLATION MISSING
+[[trigger_regex_translate_chars]]
+==== Translate chars
+
+For the command `y`, the format is: `y/chars1/chars2` or `y/chars1/chars2/var`
+(where _var_ is a variable of the hashtable).
+
+Example: replace "a", "b" and "c" by upper case letter:
+
+----
+y/abc/ABC/
+----
+
+Example: rotate arrows clockwise:
+
+----
+y/←↑→↓/↑→↓←/
+----
+
+Example: convert all letters to lower case:
+
+----
+y/${chars:upper}/${chars:lower}/
+----
+
+Example: shift each letter by one position, preserving case: a→b, b→c … y→z, z→a:
+
+----
+y/${chars:a-z}${chars:A-Z}/${chars:b-z}a${chars:B-Z}A/
+----
+
+// TRANSLATION MISSING
+[[trigger_regex_variable]]
+==== Variable
+
+If _var_ does not exist in the hashtable, it is created automatically with an
+empty value. This allows to create custom temporary variables.
+
+If _var_ is not specified, the default variable is used, it depends on hook
+type:
[width="100%",cols="2,3,7",options="header"]
|===
@@ -4939,36 +5040,6 @@ od typu uchwytu:
^(1)^ Wszystkie zmienne mogą zostać zaktualizowane, jednak tylko te zmienne
mają wpływ na zmienne zwrócone i użyte przez WeeChat.
-Wiele wyrażeń może być oddzielonych spacją, na przykład:
-"/regex1/zamień1/zmienna1 /regex2/zamień2/zmienna2".
-
-Znak "/" może zostać zastąpiony dowolnym znakiem (jednym lub kilkoma
-identycznymi znakami).
-
-Dopasowane grupy, które mogą zostać użyte w "zamień":
-
-* `+${re:0}+` to `+${re:99}+`: `+${re:0}+` to pełne dopasowanie, `+${re:1}+` do
- `+${re:99}+` to przechwycone grupy
-* `+${re:+}+`: ostatnie dopasowanie (z najwyższym numerem)
-* `+${hide:c,${re:N}}+`: dopasowanie "N" z wszystkimi znakami zastąpionymi "c"
- (przykład: `+${hide:*,${re:2}}+` to grupa #2 ze znakami zastąpionymi `+*+`).
-
-Przykład: użyj pogrubienia dla słów pomiędzy `+*+`:
-
-----
-/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
-----
-
-Przykład: domyślny trigger _server_pass_ używa tego wyrażenia do ukrycia hasła
-w komendach `/server` i `/connect` (znaki haseł są zastępowane przez `+*+`):
-
-----
-==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
-----
-
-[NOTE]
-W tym przykładzie, użyty jest separator "==" ponieważ w wyrażeniu występuje "/".
-
[[trigger_command]]
=== Komenda
diff --git a/doc/sr/weechat_user.sr.adoc b/doc/sr/weechat_user.sr.adoc
index 0e72af7a5..4f2c8c72e 100644
--- a/doc/sr/weechat_user.sr.adoc
+++ b/doc/sr/weechat_user.sr.adoc
@@ -4559,16 +4559,120 @@ link:weechat_plugin_api.sr.html#_hook_info[hook_info ^↗^,window=_blank]
${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})
----
+// TRANSLATION MISSING
[[trigger_regex]]
-=== Регуларни израз
+=== Regular expression
+
+The regular expression is used to change variables in callback hashtable.
+
+Format is one of the following:
+
+----
+/string1/string2
+s/string1/string2
+s/string1/string2/var
+y/string1/string2
+y/string1/string2/var
+----
+
+Fields:
+
+* `s` or `y`: a letter with the command; if missing, default command is `s`
+ and the first char is then used as the delimiter:
+** `s`: regex replacement: first string is a regular expression, second string
+ is the replacement for every matching string
+** `y`: chars translation: first string is a set of characters that are replaced
+ by the characters in the second string; once evaluated, each string must have
+ exactly the same number of UTF-8 chars
+* `/`: the regex delimiter; the char "/" can be replaced by any char
+ (one or more identical chars)
+* `string1`: the first string (use depends on the command)
+* `string2`: the second string (use depends on the command)
+* `var`: the hashtable variable to update
+
+Many regular expressions can be separated by a space, for example:
+
+----
+s/regex1/replace1/var1 y/abcdef/ABDDEF/var2
+----
+
+// TRANSLATION MISSING
+[[trigger_regex_replace]]
+==== Regex replace
+
+For the command `s`, the format is: `s/regex/replace` or `s/regex/replace/var`
+(where _var_ is a variable of the hashtable).
+
+As `s` is the default command, it can be omitted, so `/regex/replace` is also
+valid (but the first char, which is the delimiter, must not be a letter).
-Регуларни израз се користи за измену променљивих у хеш табели функције повратног позива.
+Matching groups can be used in _replace_:
-Формат је следећи: „/регизраз/замена” или „/регизраз/замена/пром” (где је _пром_ променљива хеш табеле).
+* `+${re:0}+` to `+${re:99}+`: `+${re:0}+` is the whole match, `+${re:1}+` to
+ `+${re:99}+` are groups captured
+* `+${re:+}+`: the last match (with highest number)
+* `+${hide:c,${re:N}}+`: match "N" with all chars replaced by "c"
+ (example: `+${hide:*,${re:2}}+` is the group #2 with all chars replaced by
+ `+*+`).
-Ако _пром_ не постоји у хеш табели, она се аутоматски креира и има празну вредност. На овај начин могу да се креирају произвољне привремене променљиве.
+Example: use bold for words between `+*+`:
-Ако се _пром_ не наведе, користи се подразумевана променљива која зависи од типа употребљене куке:
+----
+s/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
+----
+
+Example: default trigger _server_pass_ uses this regular expression to hide
+password in commands `/server` and `/connect` (chars in passwords are replaced
+by `+*+`):
+
+----
+s==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
+----
+
+[NOTE]
+In this example, the delimiter used is "==" because there is a "/" in the
+regular expression.
+
+// TRANSLATION MISSING
+[[trigger_regex_translate_chars]]
+==== Translate chars
+
+For the command `y`, the format is: `y/chars1/chars2` or `y/chars1/chars2/var`
+(where _var_ is a variable of the hashtable).
+
+Example: replace "a", "b" and "c" by upper case letter:
+
+----
+y/abc/ABC/
+----
+
+Example: rotate arrows clockwise:
+
+----
+y/←↑→↓/↑→↓←/
+----
+
+Example: convert all letters to lower case:
+
+----
+y/${chars:upper}/${chars:lower}/
+----
+
+Example: shift each letter by one position, preserving case: a→b, b→c … y→z, z→a:
+
+----
+y/${chars:a-z}${chars:A-Z}/${chars:b-z}a${chars:B-Z}A/
+----
+
+// TRANSLATION MISSING
+[[trigger_regex_variable]]
+==== Variable
+
+If _var_ does not exist in the hashtable, it is created automatically with an
+empty value. This allows to create custom temporary variables.
+
+If _var_ is not specified, the default variable is used, it depends on hook
+type:
[width="100%", cols="2,3,7", options="header"]
|===
@@ -4590,31 +4694,6 @@ ${tg_displayed} && (${tg_highlight} || ${tg_msg_pv})
[NOTE]
^(1)^ У окидачу је могуће ажурирање свих променљивих, али само ове променљиве утичу на вредност коју враћа окидач и коју користи програм WeeChat.
-Више регуларних израза може да се раздвоји размаком, на пример: /регизраз1/замена1/пром1 /регизраз2/замена2/пром2".
-
-Карактер „/” може да се замени било којим карактером (један или више идентичних карактера).
-
-У „замена” могу да се користе групе подударања:
-
-* `+${re:0}+` до `+${re:99}+`: `+${re:0}+` је комплетно подударање, `+${re:1}+` до `+${re:99}+` су ухваћене групе
-* `+${re:+}+`: последње подударање (са највишим бројем)
-* `+${hide:c,${re:N}}+`: подударање „N” са свим карактерима се замењује са „c” (пример: `+${hide:*,${re:2}}+` је група #2 у којој су сви карактери замењени са `+*+`).
-
-Пример: користи подебљан текст за речи уоквирене са `+*+`:
-
-----
-/\*([^ ]+)\*/*${color:bold}${re:1}${color:-bold}*/
-----
-
-Пример: подразумевани окидач _server_pass_ користи следећи регуларни израз да сакрије лозинке у командама `/server` и `/connect` (карактери у лозинкама се замењују са `+*+`):
-
-----
-==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==${re:1}${hide:*,${re:4}}${re:5}
-----
-
-[NOTE]
-У овом примеру се користи „==” као граничник јер у регуларном изразу постоји „/”.
-
[[trigger_command]]
=== Команда
diff --git a/src/plugins/trigger/trigger-callback.c b/src/plugins/trigger/trigger-callback.c
index 2f1d7cf69..fab098fb1 100644
--- a/src/plugins/trigger/trigger-callback.c
+++ b/src/plugins/trigger/trigger-callback.c
@@ -267,18 +267,95 @@ trigger_callback_check_conditions (struct t_trigger *trigger,
}
/*
- * Replaces text using one or more regex in the trigger.
+ * Replaces text using regex.
+ *
+ * Returns: text replaced.
+ *
+ * Note: result must be freed after use.
+ */
+
+char *
+trigger_callback_regex_replace (struct t_trigger_context *context,
+ const char *text,
+ regex_t *regex,
+ const char *replace)
+{
+ char *value;
+ struct t_hashtable *hashtable_options_regex;
+
+ if (!regex)
+ return NULL;
+
+ hashtable_options_regex = weechat_hashtable_new (
+ 32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL, NULL);
+
+ weechat_hashtable_set (context->pointers, "regex", regex);
+ weechat_hashtable_set (hashtable_options_regex,
+ "regex_replace", replace);
+
+ value = weechat_string_eval_expression (
+ text,
+ context->pointers,
+ context->extra_vars,
+ hashtable_options_regex);
+
+ weechat_hashtable_free (hashtable_options_regex);
+
+ return value;
+}
+
+/*
+ * Translates chars.
+ *
+ * Returns: text with translated chars.
+ *
+ * Note: result must be freed after use.
+ */
+
+char *
+trigger_callback_regex_translate_chars (struct t_trigger_context *context,
+ const char *text,
+ const char *chars1,
+ const char *chars2)
+{
+ char *value, *chars1_eval, *chars2_eval;
+
+ chars1_eval = weechat_string_eval_expression (
+ chars1,
+ context->pointers,
+ context->extra_vars,
+ NULL);
+ chars2_eval = weechat_string_eval_expression (
+ chars2,
+ context->pointers,
+ context->extra_vars,
+ NULL);
+
+ value = weechat_string_translate_chars (text, chars1_eval, chars2_eval);
+
+ if (chars1_eval)
+ free (chars1_eval);
+ if (chars2_eval)
+ free (chars2_eval);
+
+ return value;
+}
+
+/*
+ * Executes regex commands.
*/
void
-trigger_callback_replace_regex (struct t_trigger *trigger,
- struct t_trigger_context *context,
- int display_monitor)
+trigger_callback_regex (struct t_trigger *trigger,
+ struct t_trigger_context *context,
+ int display_monitor)
{
char *value;
const char *ptr_key, *ptr_value;
int i, pointers_allocated;
- struct t_hashtable *hashtable_options_regex;
pointers_allocated = 0;
@@ -298,9 +375,12 @@ trigger_callback_replace_regex (struct t_trigger *trigger,
for (i = 0; i < trigger->regex_count; i++)
{
- /* if regex is not set (invalid), skip it */
- if (!trigger->regex[i].regex)
+ /* if regex is not set (invalid) for command "regex replace", skip it */
+ if ((trigger->regex[i].command == TRIGGER_REGEX_COMMAND_REPLACE)
+ && !trigger->regex[i].regex)
+ {
continue;
+ }
ptr_key = (trigger->regex[i].variable) ?
trigger->regex[i].variable :
@@ -336,25 +416,25 @@ trigger_callback_replace_regex (struct t_trigger *trigger,
ptr_value = weechat_hashtable_get (context->extra_vars, ptr_key);
}
- hashtable_options_regex = weechat_hashtable_new (
- 32,
- WEECHAT_HASHTABLE_STRING,
- WEECHAT_HASHTABLE_STRING,
- NULL, NULL);
-
- weechat_hashtable_set (context->pointers,
- "regex", trigger->regex[i].regex);
- weechat_hashtable_set (hashtable_options_regex,
- "regex_replace",
- trigger->regex[i].replace_escaped);
-
- value = weechat_string_eval_expression (
- ptr_value,
- context->pointers,
- context->extra_vars,
- hashtable_options_regex);
-
- weechat_hashtable_free (hashtable_options_regex);
+ switch (trigger->regex[i].command)
+ {
+ case TRIGGER_REGEX_COMMAND_REPLACE:
+ value = trigger_callback_regex_replace (
+ context,
+ ptr_value,
+ trigger->regex[i].regex,
+ trigger->regex[i].replace_escaped);
+ break;
+ case TRIGGER_REGEX_COMMAND_TRANSLATE_CHARS:
+ value = trigger_callback_regex_translate_chars (
+ context,
+ ptr_value,
+ trigger->regex[i].str_regex,
+ trigger->regex[i].replace);
+ break;
+ case TRIGGER_NUM_REGEX_COMMANDS:
+ break;
+ }
if (value)
{
@@ -493,7 +573,7 @@ trigger_callback_execute (struct t_trigger *trigger,
if (weechat_trigger_plugin->debug >= 1)
{
gettimeofday (&(context->start_check_conditions), NULL);
- context->start_replace_regex = context->start_check_conditions;
+ context->start_regex = context->start_check_conditions;
context->start_run_command = context->start_check_conditions;
}
@@ -505,7 +585,7 @@ trigger_callback_execute (struct t_trigger *trigger,
/* replace text with regex */
if (weechat_trigger_plugin->debug >= 1)
gettimeofday (&(context->start_check_conditions), NULL);
- trigger_callback_replace_regex (trigger, context, display_monitor);
+ trigger_callback_regex (trigger, context, display_monitor);
/* execute command(s) */
if (weechat_trigger_plugin->debug >= 1)
@@ -524,8 +604,8 @@ trigger_callback_execute (struct t_trigger *trigger,
time_init = weechat_util_timeval_diff (&(context->start_exec),
&(context->start_check_conditions));
time_cond = weechat_util_timeval_diff (&(context->start_check_conditions),
- &(context->start_replace_regex));
- time_regex = weechat_util_timeval_diff (&(context->start_replace_regex),
+ &(context->start_regex));
+ time_regex = weechat_util_timeval_diff (&(context->start_regex),
&(context->start_run_command));
time_cmd = weechat_util_timeval_diff (&(context->start_run_command),
&(context->end_exec));
diff --git a/src/plugins/trigger/trigger-callback.h b/src/plugins/trigger/trigger-callback.h
index 07da9b0bb..7435129fc 100644
--- a/src/plugins/trigger/trigger-callback.h
+++ b/src/plugins/trigger/trigger-callback.h
@@ -32,7 +32,7 @@ struct t_trigger_context
struct t_weelist *vars_updated;
struct timeval start_exec;
struct timeval start_check_conditions;
- struct timeval start_replace_regex;
+ struct timeval start_regex;
struct timeval start_run_command;
struct timeval end_exec;
};
diff --git a/src/plugins/trigger/trigger.c b/src/plugins/trigger/trigger.c
index af2ad0c4e..43518c291 100644
--- a/src/plugins/trigger/trigger.c
+++ b/src/plugins/trigger/trigger.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include <regex.h>
#include "../weechat-plugin.h"
@@ -61,6 +62,8 @@ char *trigger_hook_default_rc[TRIGGER_NUM_HOOK_TYPES] =
{ "ok,ok_eat,error", "ok,ok_eat,error", "", "", "ok,error", "ok,error",
"ok,ok_eat,error", "ok", "ok", "", "", "" };
+char trigger_regex_command[TRIGGER_NUM_REGEX_COMMANDS] =
+{ 's', 'y' };
char *trigger_hook_regex_default_var[TRIGGER_NUM_HOOK_TYPES] =
{ "tg_signal_data", "", "tg_string", "message", "tg_message", "tg_argv_eol1",
"tg_command", "tg_remaining_calls", "tg_value", "", "tg_info", "" };
@@ -129,6 +132,27 @@ trigger_search_hook_type (const char *type)
}
/*
+ * Searches for a regex command.
+ *
+ * Returns index of option in enum t_trigger_regex_command, -1 if not found.
+ */
+
+int
+trigger_search_regex_command (char command)
+{
+ int i;
+
+ for (i = 0; i < TRIGGER_NUM_REGEX_COMMANDS; i++)
+ {
+ if (trigger_regex_command[i] == command)
+ return i;
+ }
+
+ /* regex command not found */
+ return -1;
+}
+
+/*
* Searches for trigger return code.
*
* Returns index of return code in enum t_trigger_return_code, -1 if not found.
@@ -630,7 +654,7 @@ trigger_regex_split (const char *str_regex,
const char *ptr_regex, *pos, *pos_replace, *pos_replace_end;
const char *pos_next_regex;
char *delimiter, *str_regex_escaped;
- int rc, index, length_delimiter;
+ int rc, index, length_delimiter, command;
struct t_trigger_regex *new_regex;
rc = 0;
@@ -660,6 +684,21 @@ trigger_regex_split (const char *str_regex,
delimiter = NULL;
}
+ /* extract command */
+ if (isalpha ((unsigned char)ptr_regex[0]))
+ {
+ command = trigger_search_regex_command (ptr_regex[0]);
+ if (command < 0)
+ goto format_error;
+ /* skip the command */
+ ptr_regex = weechat_utf8_next_char (ptr_regex);
+ }
+ else
+ {
+ /* default command is "s" (replace regex) */
+ command = TRIGGER_REGEX_COMMAND_REPLACE;
+ }
+
/* search the delimiter (which can be more than one char) */
pos = weechat_utf8_next_char (ptr_regex);
while (pos[0] && (weechat_utf8_charcmp (ptr_regex, pos) == 0))
@@ -694,6 +733,7 @@ trigger_regex_split (const char *str_regex,
index = *regex_count - 1;
/* initialize new regex */
+ (*regex)[index].command = command;
(*regex)[index].variable = NULL;
(*regex)[index].str_regex = NULL;
(*regex)[index].regex = NULL;
@@ -705,36 +745,44 @@ trigger_regex_split (const char *str_regex,
pos_replace - ptr_regex);
if (!(*regex)[index].str_regex)
goto memory_error;
- if (str_regex_escaped)
- free (str_regex_escaped);
- str_regex_escaped = weechat_string_convert_escaped_chars ((*regex)[index].str_regex);
- if (!str_regex_escaped)
- goto memory_error;
- /* set regex */
- (*regex)[index].regex = malloc (sizeof (*(*regex)[index].regex));
- if (!(*regex)[index].regex)
- goto memory_error;
- if (weechat_string_regcomp ((*regex)[index].regex,
- str_regex_escaped,
- REG_EXTENDED | REG_ICASE) != 0)
+ /* set regex (command "s" only) */
+ if (command == TRIGGER_REGEX_COMMAND_REPLACE)
{
- free ((*regex)[index].regex);
- (*regex)[index].regex = NULL;
- goto compile_error;
+ if (str_regex_escaped)
+ free (str_regex_escaped);
+ str_regex_escaped = weechat_string_convert_escaped_chars ((*regex)[index].str_regex);
+ if (!str_regex_escaped)
+ goto memory_error;
+ (*regex)[index].regex = malloc (sizeof (*(*regex)[index].regex));
+ if (!(*regex)[index].regex)
+ goto memory_error;
+ if (weechat_string_regcomp ((*regex)[index].regex,
+ str_regex_escaped,
+ REG_EXTENDED | REG_ICASE) != 0)
+ {
+ free ((*regex)[index].regex);
+ (*regex)[index].regex = NULL;
+ goto compile_error;
+ }
}
- /* set replace and replace_eval */
+ /* set replace */
(*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 (!(*regex)[index].replace)
goto memory_error;
- (*regex)[index].replace_escaped =
- weechat_string_convert_escaped_chars ((*regex)[index].replace);
- if (!(*regex)[index].replace_escaped)
- goto memory_error;
+
+ /* set replace_escaped (command "s" only) */
+ if (command == TRIGGER_REGEX_COMMAND_REPLACE)
+ {
+ (*regex)[index].replace_escaped =
+ weechat_string_convert_escaped_chars ((*regex)[index].replace);
+ if (!(*regex)[index].replace_escaped)
+ goto memory_error;
+ }
if (!pos_replace_end)
break;
diff --git a/src/plugins/trigger/trigger.h b/src/plugins/trigger/trigger.h
index 2807b3f06..7641a398d 100644
--- a/src/plugins/trigger/trigger.h
+++ b/src/plugins/trigger/trigger.h
@@ -79,8 +79,17 @@ enum t_trigger_post_action
TRIGGER_NUM_POST_ACTIONS,
};
+enum t_trigger_regex_command
+{
+ TRIGGER_REGEX_COMMAND_REPLACE = 0,
+ TRIGGER_REGEX_COMMAND_TRANSLATE_CHARS,
+ /* number of regex commands */
+ TRIGGER_NUM_REGEX_COMMANDS,
+};
+
struct t_trigger_regex
{
+ enum t_trigger_regex_command command; /* regex command */
char *variable; /* the hashtable key used */
char *str_regex; /* regex to search for replacement */
regex_t *regex; /* compiled regex */
@@ -104,7 +113,7 @@ struct t_trigger
int hook_running; /* 1 if one hook callback is running */
char *hook_print_buffers; /* buffers (for hook_print only) */
- /* regular expressions with their replacement text */
+ /* regular expressions */
int regex_count; /* number of regex */
struct t_trigger_regex *regex; /* array of regex */
@@ -124,6 +133,7 @@ extern char *trigger_hook_type_string[];
extern char *trigger_hook_option_values;
extern char *trigger_hook_default_arguments[];
extern char *trigger_hook_default_rc[];
+extern char trigger_regex_command[];
extern char *trigger_hook_regex_default_var[];
extern char *trigger_return_code_string[];
extern int trigger_return_code[];
@@ -137,6 +147,7 @@ extern int trigger_enabled;
extern int trigger_search_option (const char *option_name);
extern int trigger_search_hook_type (const char *type);
+extern int trigger_search_regex_command (char command);
extern int trigger_search_return_code (const char *return_code);
extern int trigger_search_post_action (const char *post_action);
extern struct t_trigger *trigger_search (const char *name);
diff --git a/tests/unit/plugins/trigger/test-trigger.cpp b/tests/unit/plugins/trigger/test-trigger.cpp
index 12617d43c..c919792f4 100644
--- a/tests/unit/plugins/trigger/test-trigger.cpp
+++ b/tests/unit/plugins/trigger/test-trigger.cpp
@@ -93,6 +93,28 @@ TEST(Trigger, SearchHookType)
/*
* Tests functions:
+ * trigger_search_regex_command
+ */
+
+TEST(Trigger, SearchRegexCommand)
+{
+ int i;
+
+ LONGS_EQUAL(-1, trigger_search_regex_command ('a'));
+ LONGS_EQUAL(-1, trigger_search_regex_command ('z'));
+ LONGS_EQUAL(-1, trigger_search_regex_command ('/'));
+ LONGS_EQUAL(-1, trigger_search_regex_command ('*'));
+ LONGS_EQUAL(-1, trigger_search_regex_command (' '));
+
+ for (i = 0; i < TRIGGER_NUM_REGEX_COMMANDS; i++)
+ {
+ LONGS_EQUAL(i,
+ trigger_search_regex_command (trigger_regex_command[i]));
+ }
+}
+
+/*
+ * Tests functions:
* trigger_search_return_code
*/
@@ -179,20 +201,34 @@ TEST(Trigger, RegexSplit)
WEE_CHECK_REGEX_SPLIT(0, 0, NULL);
WEE_CHECK_REGEX_SPLIT(0, 0, "");
- /* regex too short */
+ /* regex too short (default command "s") */
WEE_CHECK_REGEX_SPLIT(-1, 0, "/");
WEE_CHECK_REGEX_SPLIT(-1, 0, "/a");
- /* nothing after the delimiter */
- WEE_CHECK_REGEX_SPLIT(-1, 0, "///");
+ /* regex too short with command "s" (regex replace) */
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "s/");
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "s///");
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "s/a");
+
+ /* regex too short with command "y" (translate chars) */
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "y/");
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "y///");
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "y/a");
/* missing second delimiter */
WEE_CHECK_REGEX_SPLIT(-1, 0, "/abc");
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "s/abc");
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "y/abc");
+
+ /* invalid command */
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "a/a/b");
+ WEE_CHECK_REGEX_SPLIT(-1, 0, "z/a/b");
/* invalid regex */
WEE_CHECK_REGEX_SPLIT(-2, 0, "/*/a");
+ WEE_CHECK_REGEX_SPLIT(-2, 0, "s/*/a");
- /* simple regex */
+ /* simple regex (implicit command "s") */
WEE_CHECK_REGEX_SPLIT(0, 1, "/a/b");
POINTERS_EQUAL(NULL, regex[0].variable);
STRCMP_EQUAL("a", regex[0].str_regex);
@@ -200,7 +236,23 @@ TEST(Trigger, RegexSplit)
STRCMP_EQUAL("b", regex[0].replace);
STRCMP_EQUAL("b", regex[0].replace_escaped);
- /* simple regex with variable */
+ /* simple regex replace (command "s") */
+ WEE_CHECK_REGEX_SPLIT(0, 1, "s/a/b");
+ POINTERS_EQUAL(NULL, regex[0].variable);
+ STRCMP_EQUAL("a", regex[0].str_regex);
+ CHECK(regex[0].regex);
+ STRCMP_EQUAL("b", regex[0].replace);
+ STRCMP_EQUAL("b", regex[0].replace_escaped);
+
+ /* simple translate chars (command "y") */
+ WEE_CHECK_REGEX_SPLIT(0, 1, "y/${chars:a-h}/${chars:A-H}");
+ POINTERS_EQUAL(NULL, regex[0].variable);
+ STRCMP_EQUAL("${chars:a-h}", regex[0].str_regex);
+ POINTERS_EQUAL(NULL, regex[0].regex);
+ STRCMP_EQUAL("${chars:A-H}", regex[0].replace);
+ POINTERS_EQUAL(NULL, regex[0].replace_escaped);
+
+ /* simple regex replace with variable (implicit command "s") */
WEE_CHECK_REGEX_SPLIT(0, 1, "/a/b/var");
STRCMP_EQUAL("var", regex[0].variable);
STRCMP_EQUAL("a", regex[0].str_regex);
@@ -208,7 +260,23 @@ TEST(Trigger, RegexSplit)
STRCMP_EQUAL("b", regex[0].replace);
STRCMP_EQUAL("b", regex[0].replace_escaped);
- /* 2 regex separated by 3 spaces, without variables */
+ /* simple regex replace with variable (command "s") */
+ WEE_CHECK_REGEX_SPLIT(0, 1, "s/a/b/var");
+ STRCMP_EQUAL("var", regex[0].variable);
+ STRCMP_EQUAL("a", regex[0].str_regex);
+ CHECK(regex[0].regex);
+ STRCMP_EQUAL("b", regex[0].replace);
+ STRCMP_EQUAL("b", regex[0].replace_escaped);
+
+ /* simple translate chars with variable (command "y") */
+ WEE_CHECK_REGEX_SPLIT(0, 1, "y/${chars:a-h}/${chars:A-H}/var");
+ STRCMP_EQUAL("var", regex[0].variable);
+ STRCMP_EQUAL("${chars:a-h}", regex[0].str_regex);
+ POINTERS_EQUAL(NULL, regex[0].regex);
+ STRCMP_EQUAL("${chars:A-H}", regex[0].replace);
+ POINTERS_EQUAL(NULL, regex[0].replace_escaped);
+
+ /* 2 regex replace separated by 3 spaces, without variables, implicit command "s" */
WEE_CHECK_REGEX_SPLIT(0, 2, "/abc/def/ /ghi/jkl/");
POINTERS_EQUAL(NULL, regex[0].variable);
STRCMP_EQUAL("abc", regex[0].str_regex);
@@ -221,7 +289,33 @@ TEST(Trigger, RegexSplit)
STRCMP_EQUAL("jkl", regex[1].replace);
STRCMP_EQUAL("jkl", regex[1].replace_escaped);
- /* 3 regex with variables and escaped replace */
+ /* 2 regex replace separated by 3 spaces, without variables, command "s" */
+ WEE_CHECK_REGEX_SPLIT(0, 2, "s/abc/def/ s/ghi/jkl/");
+ POINTERS_EQUAL(NULL, regex[0].variable);
+ STRCMP_EQUAL("abc", regex[0].str_regex);
+ CHECK(regex[0].regex);
+ STRCMP_EQUAL("def", regex[0].replace);
+ STRCMP_EQUAL("def", regex[0].replace_escaped);
+ POINTERS_EQUAL(NULL, regex[1].variable);
+ STRCMP_EQUAL("ghi", regex[1].str_regex);
+ CHECK(regex[1].regex);
+ STRCMP_EQUAL("jkl", regex[1].replace);
+ STRCMP_EQUAL("jkl", regex[1].replace_escaped);
+
+ /* 2 translate chars separated by 3 spaces, without variables, command "y" */
+ WEE_CHECK_REGEX_SPLIT(0, 2, "y/abc/ABC/ y/ghi/GHI/");
+ POINTERS_EQUAL(NULL, regex[0].variable);
+ STRCMP_EQUAL("abc", regex[0].str_regex);
+ POINTERS_EQUAL(NULL, regex[0].regex);
+ STRCMP_EQUAL("ABC", regex[0].replace);
+ POINTERS_EQUAL(NULL, regex[0].replace_escaped);
+ POINTERS_EQUAL(NULL, regex[1].variable);
+ STRCMP_EQUAL("ghi", regex[1].str_regex);
+ POINTERS_EQUAL(NULL, regex[1].regex);
+ STRCMP_EQUAL("GHI", regex[1].replace);
+ POINTERS_EQUAL(NULL, regex[1].replace_escaped);
+
+ /* 3 regex replace with variables and escaped replace, implicit command "s" */
WEE_CHECK_REGEX_SPLIT(0, 3,
"/abc/def/var1 /ghi/jkl/var2 /mno/pqr\\x20stu/var3");
STRCMP_EQUAL("var1", regex[0].variable);
@@ -240,6 +334,58 @@ TEST(Trigger, RegexSplit)
STRCMP_EQUAL("pqr\\x20stu", regex[2].replace);
STRCMP_EQUAL("pqr stu", regex[2].replace_escaped);
+ /* 3 regex replace with variables and escaped replace, command "s" */
+ WEE_CHECK_REGEX_SPLIT(
+ 0, 3,
+ "s/abc/def/var1 s/ghi/jkl/var2 s/mno/pqr\\x20stu/var3");
+ STRCMP_EQUAL("var1", regex[0].variable);
+ STRCMP_EQUAL("abc", regex[0].str_regex);
+ CHECK(regex[0].regex);
+ STRCMP_EQUAL("def", regex[0].replace);
+ STRCMP_EQUAL("def", regex[0].replace_escaped);
+ STRCMP_EQUAL("var2", regex[1].variable);
+ STRCMP_EQUAL("ghi", regex[1].str_regex);
+ CHECK(regex[1].regex);
+ STRCMP_EQUAL("jkl", regex[1].replace);
+ STRCMP_EQUAL("jkl", regex[1].replace_escaped);
+ STRCMP_EQUAL("var3", regex[2].variable);
+ STRCMP_EQUAL("mno", regex[2].str_regex);
+ CHECK(regex[2].regex);
+ STRCMP_EQUAL("pqr\\x20stu", regex[2].replace);
+ STRCMP_EQUAL("pqr stu", regex[2].replace_escaped);
+
+ /* 3 translate chars with variables, command "y" */
+ WEE_CHECK_REGEX_SPLIT(0, 3, "y/abc/ABC/var1 y/ghi/GHI/var2 y/mno/MNO/var3");
+ STRCMP_EQUAL("var1", regex[0].variable);
+ STRCMP_EQUAL("abc", regex[0].str_regex);
+ POINTERS_EQUAL(NULL, regex[0].regex);
+ STRCMP_EQUAL("ABC", regex[0].replace);
+ POINTERS_EQUAL(NULL, regex[0].replace_escaped);
+ STRCMP_EQUAL("var2", regex[1].variable);
+ STRCMP_EQUAL("ghi", regex[1].str_regex);
+ POINTERS_EQUAL(NULL, regex[1].regex);
+ STRCMP_EQUAL("GHI", regex[1].replace);
+ POINTERS_EQUAL(NULL, regex[1].replace_escaped);
+ STRCMP_EQUAL("var3", regex[2].variable);
+ STRCMP_EQUAL("mno", regex[2].str_regex);
+ POINTERS_EQUAL(NULL, regex[2].regex);
+ STRCMP_EQUAL("MNO", regex[2].replace);
+ POINTERS_EQUAL(NULL, regex[2].replace_escaped);
+
+ /* mixed regex replace and translate chars */
+ WEE_CHECK_REGEX_SPLIT(0, 2,
+ "s/abc/defghi/var1 y/${chars:x-z}/${chars:X-Z}/var2");
+ STRCMP_EQUAL("var1", regex[0].variable);
+ STRCMP_EQUAL("abc", regex[0].str_regex);
+ CHECK(regex[0].regex);
+ STRCMP_EQUAL("defghi", regex[0].replace);
+ STRCMP_EQUAL("defghi", regex[0].replace_escaped);
+ STRCMP_EQUAL("var2", regex[1].variable);
+ STRCMP_EQUAL("${chars:x-z}", regex[1].str_regex);
+ POINTERS_EQUAL(NULL, regex[1].regex);
+ STRCMP_EQUAL("${chars:X-Z}", regex[1].replace);
+ POINTERS_EQUAL(NULL, regex[1].replace_escaped);
+
trigger_regex_free (&regex_count, &regex);
}