| dmenu-dynamicoptions-5.0.diff - sites - public wiki contents of suckless.org | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| Refs | |
| --- | |
| dmenu-dynamicoptions-5.0.diff (5263B) | |
| --- | |
| 1 From f70735c476c25da46f9e44b835ac967e0dfa4d85 Mon Sep 17 00:00:00 2001 | |
| 2 From: Ziad EL KHOURY HANNA <[email protected]> | |
| 3 Date: Mon, 29 Nov 2021 17:36:35 +0100 | |
| 4 Subject: [PATCH] add `-dy` flag for dynamic menu updating | |
| 5 | |
| 6 `-dy` flag makes dmenu run the command given to it whenever input is | |
| 7 changed with the current input as the last argument and update the | |
| 8 option list according to the output of that command. | |
| 9 | |
| 10 Based on dynamic options patch by ttmx <[email protected]>. | |
| 11 Adds proper quoting of the given command. | |
| 12 Adds option to man file documentation. | |
| 13 --- | |
| 14 config.def.h | 1 + | |
| 15 dmenu.1 | 5 ++++ | |
| 16 dmenu.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++----- | |
| 17 3 files changed, 70 insertions(+), 6 deletions(-) | |
| 18 | |
| 19 diff --git a/config.def.h b/config.def.h | |
| 20 index 1edb647..035b877 100644 | |
| 21 --- a/config.def.h | |
| 22 +++ b/config.def.h | |
| 23 @@ -7,6 +7,7 @@ static const char *fonts[] = { | |
| 24 "monospace:size=10" | |
| 25 }; | |
| 26 static const char *prompt = NULL; /* -p option; prompt to th… | |
| 27 +static const char *dynamic = NULL; /* -dy option; dynamic comm… | |
| 28 static const char *colors[SchemeLast][2] = { | |
| 29 /* fg bg */ | |
| 30 [SchemeNorm] = { "#bbbbbb", "#222222" }, | |
| 31 diff --git a/dmenu.1 b/dmenu.1 | |
| 32 index 323f93c..1ae3fe3 100644 | |
| 33 --- a/dmenu.1 | |
| 34 +++ b/dmenu.1 | |
| 35 @@ -22,6 +22,8 @@ dmenu \- dynamic menu | |
| 36 .IR color ] | |
| 37 .RB [ \-w | |
| 38 .IR windowid ] | |
| 39 +.RB [ \-dy | |
| 40 +.IR command ] | |
| 41 .P | |
| 42 .BR dmenu_run " ..." | |
| 43 .SH DESCRIPTION | |
| 44 @@ -80,6 +82,9 @@ prints version information to stdout, then exits. | |
| 45 .TP | |
| 46 .BI \-w " windowid" | |
| 47 embed into windowid. | |
| 48 +.TP | |
| 49 +.BI \-dy " command" | |
| 50 +runs command whenever input changes to update menu items. | |
| 51 .SH USAGE | |
| 52 dmenu is completely controlled by the keyboard. Items are selected usi… | |
| 53 arrow keys, page up, page down, home, and end. | |
| 54 diff --git a/dmenu.c b/dmenu.c | |
| 55 index 65f25ce..6780122 100644 | |
| 56 --- a/dmenu.c | |
| 57 +++ b/dmenu.c | |
| 58 @@ -44,6 +44,7 @@ static struct item *items = NULL; | |
| 59 static struct item *matches, *matchend; | |
| 60 static struct item *prev, *curr, *next, *sel; | |
| 61 static int mon = -1, screen; | |
| 62 +static unsigned int max_lines = 0; | |
| 63 | |
| 64 static Atom clip, utf8; | |
| 65 static Display *dpy; | |
| 66 @@ -210,6 +211,47 @@ grabkeyboard(void) | |
| 67 die("cannot grab keyboard"); | |
| 68 } | |
| 69 | |
| 70 +static void readstdin(FILE* stream); | |
| 71 + | |
| 72 +static void | |
| 73 +refreshoptions() | |
| 74 +{ | |
| 75 + int dynlen = strlen(dynamic); | |
| 76 + int cmdlen = dynlen + 4; | |
| 77 + char *cmd; | |
| 78 + char *c; | |
| 79 + char *t = text; | |
| 80 + while (*t) | |
| 81 + cmdlen += *t++ == '\'' ? 4 : 1; | |
| 82 + cmd = malloc(cmdlen); | |
| 83 + if (cmd == NULL) | |
| 84 + die("cannot malloc %u bytes:", cmdlen); | |
| 85 + strcpy(cmd, dynamic); | |
| 86 + t = text; | |
| 87 + c = cmd + dynlen; | |
| 88 + *(c++) = ' '; | |
| 89 + *(c++) = '\''; | |
| 90 + while (*t) { | |
| 91 + // prefix ' with '\' | |
| 92 + if (*t == '\'') { | |
| 93 + *(c++) = '\''; | |
| 94 + *(c++) = '\\'; | |
| 95 + *(c++) = '\''; | |
| 96 + } | |
| 97 + *(c++) = *(t++); | |
| 98 + } | |
| 99 + *(c++) = '\''; | |
| 100 + *(c++) = 0; | |
| 101 + FILE *stream = popen(cmd, "r"); | |
| 102 + if (!stream) | |
| 103 + die("could not popen dynamic command (%s):", cmd); | |
| 104 + readstdin(stream); | |
| 105 + int r = pclose(stream); | |
| 106 + if (r == -1) | |
| 107 + die("could not pclose dynamic command"); | |
| 108 + free(cmd); | |
| 109 +} | |
| 110 + | |
| 111 static void | |
| 112 match(void) | |
| 113 { | |
| 114 @@ -221,6 +263,16 @@ match(void) | |
| 115 size_t len, textsize; | |
| 116 struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; | |
| 117 | |
| 118 + if (dynamic) { | |
| 119 + refreshoptions(); | |
| 120 + matches = matchend = NULL; | |
| 121 + for (item = items; item && item->text; item++) | |
| 122 + appenditem(item, &matches, &matchend); | |
| 123 + curr = sel = matches; | |
| 124 + calcoffsets(); | |
| 125 + return; | |
| 126 + } | |
| 127 + | |
| 128 strcpy(buf, text); | |
| 129 /* separate input text into tokens to be matched individually */ | |
| 130 for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NU… | |
| 131 @@ -519,14 +571,14 @@ paste(void) | |
| 132 } | |
| 133 | |
| 134 static void | |
| 135 -readstdin(void) | |
| 136 +readstdin(FILE* stream) | |
| 137 { | |
| 138 char buf[sizeof text], *p; | |
| 139 size_t i, imax = 0, size = 0; | |
| 140 unsigned int tmpmax = 0; | |
| 141 | |
| 142 /* read each line from stdin and add it to the item list */ | |
| 143 - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { | |
| 144 + for (i = 0; fgets(buf, sizeof buf, stream); i++) { | |
| 145 if (i + 1 >= size / sizeof *items) | |
| 146 if (!(items = realloc(items, (size += BUFSIZ)))) | |
| 147 die("cannot realloc %u bytes:", size); | |
| 148 @@ -544,7 +596,7 @@ readstdin(void) | |
| 149 if (items) | |
| 150 items[i].text = NULL; | |
| 151 inputw = items ? TEXTW(items[imax].text) : 0; | |
| 152 - lines = MIN(lines, i); | |
| 153 + lines = MIN(max_lines, i); | |
| 154 } | |
| 155 | |
| 156 static void | |
| 157 @@ -690,7 +742,8 @@ static void | |
| 158 usage(void) | |
| 159 { | |
| 160 fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [… | |
| 161 - " [-nb color] [-nf color] [-sb color] [-sf co… | |
| 162 + " [-nb color] [-nf color] [-sb color] [-sf co… | |
| 163 + " [-dy command]\n", stderr); | |
| 164 exit(1); | |
| 165 } | |
| 166 | |
| 167 @@ -733,6 +786,8 @@ main(int argc, char *argv[]) | |
| 168 colors[SchemeSel][ColFg] = argv[++i]; | |
| 169 else if (!strcmp(argv[i], "-w")) /* embedding window … | |
| 170 embed = argv[++i]; | |
| 171 + else if (!strcmp(argv[i], "-dy")) /* dynamic command t… | |
| 172 + dynamic = argv[++i] && *argv[i] ? argv[i] : NUL… | |
| 173 else | |
| 174 usage(); | |
| 175 | |
| 176 @@ -757,11 +812,14 @@ main(int argc, char *argv[]) | |
| 177 die("pledge"); | |
| 178 #endif | |
| 179 | |
| 180 + max_lines = lines; | |
| 181 if (fast && !isatty(0)) { | |
| 182 grabkeyboard(); | |
| 183 - readstdin(); | |
| 184 + if (!dynamic) | |
| 185 + readstdin(stdin); | |
| 186 } else { | |
| 187 - readstdin(); | |
| 188 + if (!dynamic) | |
| 189 + readstdin(stdin); | |
| 190 grabkeyboard(); | |
| 191 } | |
| 192 setup(); | |
| 193 -- | |
| 194 2.34.1 | |
| 195 |