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 |