diff --git a/include/helper.h b/include/helper.h
index 76657173..77718cfe 100644
--- a/include/helper.h
+++ b/include/helper.h
@@ -336,5 +336,21 @@ void parse_ranges ( char *input, rofi_range_pair **list, unsigned int *length );
* @param filter
*/
void rofi_output_formatted_line ( const char *format, const char *string, int selected_line, const char *filter );
+
+
+/**
+ * @param string The string with elements to be replaced
+ * @param ... Set of {key}, value that will be replaced, terminated by a NULL
+ *
+ * Items {key} are replaced by the value if '{key}' is passed as key/value pair, otherwise removed from string.
+ * If the {key} is in between [] all the text between [] are removed if {key}
+ * is not found. Otherwise key is replaced and [ & ] removed.
+ *
+ * This allows for optional replacement, f.e. '{ssh-client} [-t {title}] -e
+ * "{cmd}"' the '-t {title}' is only there if {title} is set.
+ *
+ * @returns a new string with the keys replaced.
+ */
+char *helper_string_replace_if_exists ( char * string, ... );
G_END_DECLS
#endif // ROFI_HELPER_H
diff --git a/source/helper.c b/source/helper.c
index 0ca94e47..6722cf50 100644
--- a/source/helper.c
+++ b/source/helper.c
@@ -1233,3 +1233,95 @@ void rofi_output_formatted_line ( const char *format, const char *string, int se
fputc ( '\n', stdout );
fflush ( stdout );
}
+
+
+static gboolean helper_eval_cb2 ( const GMatchInfo *info, GString *res, gpointer data )
+{
+ GHashTable *h = (GHashTable*)h;
+ gchar *match;
+ // Get the match
+ int num_match = g_match_info_get_match_count(info);
+ // Just {text} This is inside () 5.
+ if ( num_match == 5 ) {
+ match = g_match_info_fetch ( info, 4);
+ if ( match != NULL ) {
+ // Lookup the match, so we can replace it.
+ gchar *r = g_hash_table_lookup ( (GHashTable *) data, match );
+ if ( r != NULL ) {
+ // Append the replacement to the string.
+ g_string_append ( res, r );
+ }
+ // Free match.
+ g_free ( match );
+ }
+ }
+ // {} with [] guard around it.
+ else if ( num_match == 4 ) {
+ match = g_match_info_fetch ( info, 2);
+ if ( match != NULL ) {
+ // Lookup the match, so we can replace it.
+ gchar *r = g_hash_table_lookup ( (GHashTable *) data, match );
+ if ( r != NULL ) {
+ // Add (optional) prefix
+ gchar *prefix = g_match_info_fetch (info, 1);
+ g_string_append ( res, prefix );
+ g_free (prefix );
+ // Append the replacement to the string.
+ g_string_append ( res, r );
+ // Add (optional) postfix
+ gchar *post = g_match_info_fetch (info, 3);
+ g_string_append ( res, post );
+ g_free (post );
+ }
+ // Free match.
+ g_free ( match );
+ }
+ }
+ // Else we have an invalid match.
+ // Continue replacement.
+ return FALSE;
+}
+
+char *helper_string_replace_if_exists ( char * string, ... )
+{
+ GError *error = NULL;
+ GHashTable *h;
+ h = g_hash_table_new ( g_str_hash, g_str_equal );
+ // By default, we insert terminal and ssh-client
+ g_hash_table_insert ( h, "{terminal}", config.terminal_emulator );
+ g_hash_table_insert ( h, "{ssh-client}", config.ssh_client );
+ // Add list from variable arguments.
+ va_list ap;
+ va_start ( ap, string );
+ while ( 1 ) {
+ char * key = va_arg ( ap, char * );
+ if ( key == (char *) 0 ) {
+ break;
+ }
+ char *value = va_arg ( ap, char * );
+ if ( value == (char *) 0 ) {
+ break;
+ }
+ g_hash_table_insert ( h, key, value );
+ }
+ va_end ( ap );
+
+ // Replace hits within {-\w+}.
+ GRegex *reg = g_regex_new ( "\\[(.*)({[-\\w]+})(.*)\\]|({[\\w-]+})", 0, 0, NULL );
+ char *res = g_regex_replace_eval ( reg, string, -1, 0, 0, helper_eval_cb2, h, NULL );
+ // Free regex.
+ g_regex_unref ( reg );
+ // Destroy key-value storage.
+ g_hash_table_destroy ( h );
+ // Throw error if shell parsing fails.
+ if ( error ) {
+ char *msg = g_strdup_printf ( "Failed to parse: '%s'\nError: '%s'", string, error->message );
+ rofi_view_error_dialog ( msg, FALSE );
+ g_free ( msg );
+ // print error.
+ g_error_free ( error );
+ g_free ( res );
+ return NULL;
+ }
+ return res;
+}
diff --git a/test/helper-test.c b/test/helper-test.c
index ddafde63..052af651 100644
--- a/test/helper-test.c
+++ b/test/helper-test.c
@@ -156,4 +156,30 @@ int main ( int argc, char ** argv )
TASSERTL ( rofi_scorer_fuzzy_evaluate ("aap noot mies", 12,"Anm", 3 ), 1073741824);
}
+
+
+ char *a;
+ a = helper_string_replace_if_exists ( "{terminal} [-t {title} blub ]-e {cmd}", "{cmd}", "aap", "{title}", "some title", NULL);
+ printf("%s\n",a);
+ TASSERT ( g_utf8_collate ( a, "rofi-sensible-terminal -t some title blub -e aap") == 0);
+ g_free(a);
+ a = helper_string_replace_if_exists ( "{terminal} [-t {title} blub ]-e {cmd}", "{cmd}", "aap", NULL);
+ printf("%s\n",a);
+ TASSERT ( g_utf8_collate ( a, "rofi-sensible-terminal -e aap") == 0);
+ g_free(a);
+ a = helper_string_replace_if_exists ( "{name} [({category})]", "{name}", "Librecad", "{category}", "Desktop app", NULL );
+ printf("%s\n",a);
+ TASSERT ( g_utf8_collate ( a, "Librecad (Desktop app)") == 0);
+ g_free(a);
+ a = helper_string_replace_if_exists ( "{name}[ ({category})]", "{name}", "Librecad", NULL );
+ TASSERT ( g_utf8_collate ( a, "Librecad") == 0);
+ g_free(a);
+ a = helper_string_replace_if_exists ( "{terminal} [{title} blub ]-e {cmd}", "{cmd}", "aap", "{title}", "some title", NULL);
+ printf("%s\n",a);
+ TASSERT ( g_utf8_collate ( a, "rofi-sensible-terminal some title blub -e aap") == 0);
+ g_free(a);
+ a = helper_string_replace_if_exists ( "{terminal} [{title} blub ]-e {cmd}", "{cmd}", "aap", "{title}", NULL, NULL);
+ printf("%s\n",a);
+ TASSERT ( g_utf8_collate ( a, "rofi-sensible-terminal -e aap") == 0);
+ g_free(a);
}