summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Davenport <qball@gmpclient.org>2023-02-11 12:42:35 +0100
committerDave Davenport <qball@gmpclient.org>2023-02-11 12:42:35 +0100
commit2003b7bd5288846bc03bdd76751542661c53c244 (patch)
tree5f53be3781184dd95bd85a0e0cd9c2e1a81b6fce
parentcaa92637f1a436d2f629f92b301f1b374e72f6c1 (diff)
[Dmenu] Implement a select rows for dmenu multi-select.1806-request-pre-check-some-or-all-boxes-on-demu-multi-select
Issue: #1802
-rw-r--r--doc/rofi-dmenu.57
-rw-r--r--doc/rofi-dmenu.5.markdown5
-rw-r--r--doc/rofi-theme.55
-rw-r--r--source/modes/dmenu.c82
4 files changed, 92 insertions, 7 deletions
diff --git a/doc/rofi-dmenu.5 b/doc/rofi-dmenu.5
index c11dc96c..a462389b 100644
--- a/doc/rofi-dmenu.5
+++ b/doc/rofi-dmenu.5
@@ -148,6 +148,13 @@ Or any combination: '5,-3:,7:11,2,0,-9'
Urgent row, mark \fIX\fP as urgent. See \fB\fC-a\fR option for details.
.PP
+\fB\fC-select-rows\fR \fIX\fP
+
+.PP
+If multi-select is enabled, pre-select rows, See \fB\fC-a\fR option for format details.
+If same row is specified multiple times, it state is toggled on subsequential sets.
+
+.PP
\fB\fC-only-match\fR
.PP
diff --git a/doc/rofi-dmenu.5.markdown b/doc/rofi-dmenu.5.markdown
index ff2f0203..2c79b675 100644
--- a/doc/rofi-dmenu.5.markdown
+++ b/doc/rofi-dmenu.5.markdown
@@ -93,6 +93,11 @@ Active row, mark *X* as active. Where *X* is a comma-separated list of python(1)
Urgent row, mark *X* as urgent. See `-a` option for details.
+`-select-rows` *X*
+
+If multi-select is enabled, pre-select rows, See `-a` option for format details.
+If same row is specified multiple times, it state is toggled on subsequential sets.
+
`-only-match`
Only return a selected item, do not allow custom entry.
diff --git a/doc/rofi-theme.5 b/doc/rofi-theme.5
index a5887a46..187c2102 100644
--- a/doc/rofi-theme.5
+++ b/doc/rofi-theme.5
@@ -1615,7 +1615,7 @@ property.
These cannot be changed using the \fB\fCchildren\fR property.
.PP
-Each entries displayed by listview are captured by a \fB\fCbox\fR called \fB\fCelement\fR\&.
+Each Entry displayed by listview is captured by a \fB\fCbox\fR called \fB\fCelement\fR\&.
An \fB\fCelement\fR widget can contain the following special child widgets:
.RS
@@ -1630,7 +1630,8 @@ An \fB\fCelement\fR widget can contain the following special child widgets:
.PP
By default the \fB\fCelement-icon\fR and \fB\fCelement-text\fR child widgets are added to the
-\fB\fCelement\fR\&. This can be modified using the \fB\fCchildren\fR property.
+\fB\fCelement\fR\&. This can be modified using the \fB\fCchildren\fR property or the
+\fB\fC[no]-show-icons\fR option.
.PP
A child added with another name is seen as a \fB\fCbox\fR, this can be used as dynamic
diff --git a/source/modes/dmenu.c b/source/modes/dmenu.c
index 0b604e78..91bdfdc9 100644
--- a/source/modes/dmenu.c
+++ b/source/modes/dmenu.c
@@ -123,6 +123,66 @@ typedef struct {
DmenuModePrivateData *pd;
} Block;
+
+static void dmenu_parse_multi_select_range ( DmenuModePrivateData *pd, const char *entries)
+{
+ if ( entries == NULL ) {
+ return;
+ }
+ // Pre-alloc array.
+ if (pd->selected_list == NULL) {
+ pd->selected_list =
+ g_malloc0(sizeof(uint32_t) * (pd->cmd_list_length / 32 + 1));
+ }
+ char *entries_cp = g_strdup ( entries );
+ char *endp;
+ const char *const sep = ",";
+ for (char *token = strtok_r(entries_cp, sep, &endp); token != NULL;
+ token = strtok_r(NULL, sep, &endp)) {
+ const char *sep[] = {"-", ":"};
+ int pythonic = (strchr(token, ':') || token[0] == '-') ? 1 : 0;
+ int index = 0;
+
+ int start = -1;
+ int stop = -1;
+ for (char *inner_token = strsep(&token, sep[pythonic]); inner_token != NULL;
+ inner_token = strsep(&token, sep[pythonic])) {
+ if (index == 0) {
+ start = stop = (int)strtol(inner_token, NULL, 10);
+ index++;
+ continue;
+ }
+
+ if (inner_token[0] == '\0') {
+ stop = -1;
+ continue;
+ }
+
+ stop = (int)strtol(inner_token, NULL, 10);
+ if (pythonic) {
+ --stop;
+ }
+ }
+ // Fix negative numbers.
+ if ( start < 0 ) {
+ start = pd->cmd_list_length + start;
+ }
+ if ( stop < 0 ) {
+ stop = pd->cmd_list_length + stop;
+ }
+ // Fix starting
+ for ( int index = start; index <= stop; index++ ){
+ if ( index < 0 ) {
+ index = pd->cmd_list_length - index;
+ }
+ if ( index < (int)pd->cmd_list_length ) {
+ bittoggle(pd->selected_list, index);
+ }
+ }
+ }
+ g_free ( entries_cp );
+}
+
static void read_add_block(DmenuModePrivateData *pd, Block **block, char *data,
gsize len) {
@@ -514,14 +574,20 @@ static int dmenu_mode_init(Mode *sw) {
DmenuModePrivateData *pd = (DmenuModePrivateData *)mode_get_private_data(sw);
pd->async = TRUE;
+ pd->multi_select = FALSE;
// For now these only work in sync mode.
if (find_arg("-sync") >= 0 || find_arg("-dump") >= 0 ||
find_arg("-select") >= 0 || find_arg("-no-custom") >= 0 ||
find_arg("-only-match") >= 0 || config.auto_select ||
- find_arg("-selected-row") >= 0) {
+ find_arg("-selected-row") >= 0 ) {
pd->async = FALSE;
}
+ // In multi-select mode we should disable async mode.
+ if ( find_arg("-multi-select") >= 0 ) {
+ pd->async = FALSE;
+ pd->multi_select = TRUE;
+ }
pd->separator = '\n';
pd->selected_line = UINT32_MAX;
@@ -634,6 +700,14 @@ static int dmenu_mode_init(Mode *sw) {
read_input_sync(pd, -1);
}
+
+ if ( pd->multi_select ) {
+ char *entries = NULL;
+ if ( find_arg_str ( "-select-rows", &entries ) >= 0 ) {
+ dmenu_parse_multi_select_range(pd, entries);
+ }
+ }
+
gchar *columns = NULL;
if (find_arg_str("-display-columns", &columns)) {
pd->columns = g_strsplit(columns, ",", 0);
@@ -907,14 +981,10 @@ int dmenu_mode_dialog(void) {
DmenuScriptEntry *cmd_list = pd->cmd_list;
pd->only_selected = FALSE;
- pd->multi_select = FALSE;
pd->ballot_selected = "☑ ";
pd->ballot_unselected = "☐ ";
find_arg_str("-ballot-selected-str", &(pd->ballot_selected));
find_arg_str("-ballot-unselected-str", &(pd->ballot_unselected));
- if (find_arg("-multi-select") >= 0) {
- pd->multi_select = TRUE;
- }
if (find_arg("-markup-rows") >= 0) {
pd->do_markup = TRUE;
}
@@ -1006,6 +1076,8 @@ void print_dmenu_options(void) {
is_term);
print_help_msg("-a", "[list]", "List of row indexes to mark active", NULL,
is_term);
+ print_help_msg("-select-rows", "[list]", "List of row indexes to select when multi-select is enabled", NULL,
+ is_term);
print_help_msg("-l", "[integer] ", "Number of rows to display", NULL,
is_term);
print_help_msg("-window-title", "[string] ", "Set the dmenu window title",