diff --git a/Examples/test_script_mode.sh b/Examples/test_script_mode.sh
index 68b931be..bae2816f 100755
--- a/Examples/test_script_mode.sh
+++ b/Examples/test_script_mode.sh
@@ -1,32 +1,29 @@
#!/usr/bin/env bash
-if [ "$*" = "quit" ]
-then
- exit 0
+if [ "$*" = "quit" ]; then
+ exit 0
fi
-if [ "$@" ]
-then
- # Override the previously set prompt.
- echo -en "\x00prompt\x1fChange prompt\n"
- for a in {1..10}
- do
- echo "$a"
- done
- echo "quit"
+if [ "$@" ]; then
+ # Override the previously set prompt.
+ echo -en "\x00prompt\x1fChange prompt\n"
+ for a in {1..10}; do
+ echo "$a"
+ done
+ echo "quit"
else
- echo -en "\x00prompt\x1ftesting\n"
- echo -en "\0urgent\x1f0,2\n"
- echo -en "\0active\x1f1\n"
- echo -en "\0markup-rows\x1ftrue\n"
- echo -en "\0message\x1fSpecial boldmessage\n"
+ echo -en "\x00prompt\x1ftesting\n"
+ echo -en "\0urgent\x1f0,2\n"
+ echo -en "\0active\x1f1\n"
+ echo -en "\0markup-rows\x1ftrue\n"
+ echo -en "\0message\x1fSpecial boldmessage\n"
- echo -en "aap\0icon\x1ffolder\n"
- echo -en "blob\0icon\x1ffolder\x1fdisplay\x1fblub\n"
- echo "noot"
- echo "mies"
- echo -en "-------------\0nonselectable\x1ftrue\n"
- echo "testing"
- echo "Bold"
- echo "quit"
+ echo -en "aap\0icon\x1ffolder\n"
+ echo -en "blob\0icon\x1ffolder\x1fdisplay\x1fblub\n"
+ echo "noot"
+ echo "mies"
+ echo -en "-------------\0nonselectable\x1ftrue\x1fpermanent\x1ftrue\n"
+ echo "testing"
+ echo "Bold"
+ echo "quit"
fi
diff --git a/doc/rofi-script.5 b/doc/rofi-script.5
index a09e2dec..6b0c2126 100644
--- a/doc/rofi-script.5
+++ b/doc/rofi-script.5
@@ -185,6 +185,8 @@ The following options are supported:
.IP \(bu 2
\fBnonselectable\fP: If true the row cannot activated.
.IP \(bu 2
+\fBpermantent\fP: If true the row always shows, independent of filter.
+.IP \(bu 2
\fBinfo\fP: Info that, on selection, gets placed in the \fB\fCROFI_INFO\fR
environment variable. This entry does not get searched for filtering.
.IP \(bu 2
diff --git a/doc/rofi-script.5.markdown b/doc/rofi-script.5.markdown
index 03df5bc9..65bb318d 100644
--- a/doc/rofi-script.5.markdown
+++ b/doc/rofi-script.5.markdown
@@ -143,6 +143,8 @@ The following options are supported:
- **nonselectable**: If true the row cannot activated.
+- **permantent**: If true the row always shows, independent of filter.
+
- **info**: Info that, on selection, gets placed in the `ROFI_INFO`
environment variable. This entry does not get searched for filtering.
diff --git a/include/modes/dmenuscriptshared.h b/include/modes/dmenuscriptshared.h
index bf83d741..56a22c8c 100644
--- a/include/modes/dmenuscriptshared.h
+++ b/include/modes/dmenuscriptshared.h
@@ -26,6 +26,9 @@ typedef struct {
/** non-selectable */
gboolean nonselectable;
+ /** permanent */
+ gboolean permanent;
+
/** urgent */
gboolean urgent;
/** active */
diff --git a/source/modes/dmenu.c b/source/modes/dmenu.c
index 27615302..3437a6e8 100644
--- a/source/modes/dmenu.c
+++ b/source/modes/dmenu.c
@@ -139,6 +139,7 @@ static void read_add_block(DmenuModePrivateData *pd, Block **block, char *data,
(*block)->values[(*block)->length].meta = NULL;
(*block)->values[(*block)->length].info = NULL;
(*block)->values[(*block)->length].nonselectable = FALSE;
+ (*block)->values[(*block)->length].permanent = FALSE;
char *end = data;
while (end < data + len && *end != '\0') {
end++;
@@ -668,6 +669,11 @@ static int dmenu_token_match(const Mode *sw, rofi_int_matcher **tokens,
/** Strip out the markup when matching. */
char *esc = NULL;
+ if (rmpd->cmd_list[index].permanent == TRUE) {
+ // Always match
+ return 1;
+ }
+
if (rmpd->do_markup) {
pango_parse_markup(rmpd->cmd_list[index].entry, -1, 0, NULL, &esc, NULL,
NULL);
diff --git a/source/modes/script.c b/source/modes/script.c
index dfd5bf32..f9811704 100644
--- a/source/modes/script.c
+++ b/source/modes/script.c
@@ -101,6 +101,9 @@ void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw,
} else if (strcasecmp(key, "nonselectable") == 0) {
entry->nonselectable = g_ascii_strcasecmp(value, "true") == 0;
g_free(value);
+ } else if (strcasecmp(key, "permanent") == 0) {
+ entry->permanent = g_ascii_strcasecmp(value, "true") == 0;
+ g_free(value);
} else if (strcasecmp(key, "urgent") == 0) {
entry->urgent = g_ascii_strcasecmp(value, "true") == 0;
g_free(value);
@@ -252,6 +255,7 @@ static DmenuScriptEntry *execute_executor(Mode *sw, char *arg,
retv[(*length)].icon_fetch_uid = 0;
retv[(*length)].icon_fetch_size = 0;
retv[(*length)].nonselectable = FALSE;
+ retv[(*length)].permanent = FALSE;
if (buf_length > 0 && (read_length > (ssize_t)buf_length)) {
dmenuscript_parse_entry_extras(sw, &(retv[(*length)]),
buffer + buf_length,
@@ -454,6 +458,12 @@ static int script_token_match(const Mode *sw, rofi_int_matcher **tokens,
ScriptModePrivateData *rmpd = sw->private_data;
/** Strip out the markup when matching. */
char *esc = NULL;
+
+ if (rmpd->cmd_list[index].permanent == TRUE) {
+ // Always match
+ return 1;
+ }
+
if (rmpd->do_markup) {
pango_parse_markup(rmpd->cmd_list[index].entry, -1, 0, NULL, &esc, NULL,
NULL);