dmenu-nonblockingstdincontrol-4.9.diff - sites - public wiki contents of suckle… | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dmenu-nonblockingstdincontrol-4.9.diff (7742B) | |
--- | |
1 From 1a2f76ad1a0ebf65ae7739cd102b69c02fdcd0ba Mon Sep 17 00:00:00 2001 | |
2 From: Miles Alan <[email protected]> | |
3 Date: Wed, 30 Sep 2020 08:16:47 -0500 | |
4 Subject: [PATCH] nonblockingstdincontrol: Add Non-blocking stdin and con… | |
5 character reloading | |
6 | |
7 Read from stdin continously in parallel to X events. And also adds suppo… | |
8 for using control characters for reloading options (e.g. emptying list | |
9 and setting curr/sel). | |
10 | |
11 The following control characters are supported when sent at the beginnin… | |
12 a line: | |
13 \f - Clear the current items prior to following line | |
14 \a - Set the following line to be equal to sel | |
15 \b - Set the following line to be equal to curr | |
16 --- | |
17 dmenu.1 | 6 +-- | |
18 dmenu.c | 144 ++++++++++++++++++++++++++++++++++++++------------------ | |
19 2 files changed, 98 insertions(+), 52 deletions(-) | |
20 | |
21 diff --git a/dmenu.1 b/dmenu.1 | |
22 index 323f93c..a07532d 100644 | |
23 --- a/dmenu.1 | |
24 +++ b/dmenu.1 | |
25 @@ -3,7 +3,7 @@ | |
26 dmenu \- dynamic menu | |
27 .SH SYNOPSIS | |
28 .B dmenu | |
29 -.RB [ \-bfiv ] | |
30 +.RB [ \-biv ] | |
31 .RB [ \-l | |
32 .IR lines ] | |
33 .RB [ \-m | |
34 @@ -40,10 +40,6 @@ which lists programs in the user's $PATH and runs the… | |
35 .B \-b | |
36 dmenu appears at the bottom of the screen. | |
37 .TP | |
38 -.B \-f | |
39 -dmenu grabs the keyboard before reading stdin if not reading from a tty… | |
40 -is faster, but will lock up X until stdin reaches end\-of\-file. | |
41 -.TP | |
42 .B \-i | |
43 dmenu matches menu items case insensitively. | |
44 .TP | |
45 diff --git a/dmenu.c b/dmenu.c | |
46 index 6b8f51b..cc87b04 100644 | |
47 --- a/dmenu.c | |
48 +++ b/dmenu.c | |
49 @@ -1,5 +1,6 @@ | |
50 /* See LICENSE file for copyright and license details. */ | |
51 #include <ctype.h> | |
52 +#include <fcntl.h> | |
53 #include <locale.h> | |
54 #include <stdio.h> | |
55 #include <stdlib.h> | |
56 @@ -8,6 +9,8 @@ | |
57 #include <time.h> | |
58 #include <unistd.h> | |
59 | |
60 + | |
61 +#include <sys/select.h> | |
62 #include <X11/Xlib.h> | |
63 #include <X11/Xatom.h> | |
64 #include <X11/Xutil.h> | |
65 @@ -31,6 +34,7 @@ enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast };… | |
66 struct item { | |
67 char *text; | |
68 struct item *left, *right; | |
69 + struct item *next; | |
70 int out; | |
71 }; | |
72 | |
73 @@ -41,6 +45,7 @@ static int inputw = 0, promptw; | |
74 static int lrpad; /* sum of left and right padding */ | |
75 static size_t cursor; | |
76 static struct item *items = NULL; | |
77 +static struct item *itemstail= NULL; | |
78 static struct item *matches, *matchend; | |
79 static struct item *prev, *curr, *next, *sel; | |
80 static int mon = -1, screen; | |
81 @@ -173,6 +178,7 @@ drawmenu(void) | |
82 } | |
83 } | |
84 drw_map(drw, win, 0, 0, mw, mh); | |
85 + XFlush(dpy); | |
86 } | |
87 | |
88 static void | |
89 @@ -220,6 +226,7 @@ match(void) | |
90 int i, tokc = 0; | |
91 size_t len, textsize; | |
92 struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; | |
93 + int preserve = 0; | |
94 | |
95 strcpy(buf, text); | |
96 /* separate input text into tokens to be matched individually */ | |
97 @@ -230,19 +237,23 @@ match(void) | |
98 | |
99 matches = lprefix = lsubstr = matchend = prefixend = substrend … | |
100 textsize = strlen(text) + 1; | |
101 - for (item = items; item && item->text; item++) { | |
102 + for (item = items; item; item = item->next) { | |
103 for (i = 0; i < tokc; i++) | |
104 if (!fstrstr(item->text, tokv[i])) | |
105 break; | |
106 if (i != tokc) /* not all tokens match */ | |
107 continue; | |
108 /* exact matches go first, then prefixes, then substrin… | |
109 - if (!tokc || !fstrncmp(text, item->text, textsize)) | |
110 + if (!tokc || !fstrncmp(text, item->text, textsize)) { | |
111 appenditem(item, &matches, &matchend); | |
112 - else if (!fstrncmp(tokv[0], item->text, len)) | |
113 + if (sel == item) preserve = 1; | |
114 + } else if (!fstrncmp(tokv[0], item->text, len)) { | |
115 appenditem(item, &lprefix, &prefixend); | |
116 - else | |
117 + if (sel == item) preserve = 1; | |
118 + } else { | |
119 appenditem(item, &lsubstr, &substrend); | |
120 + if (sel == item) preserve = 1; | |
121 + } | |
122 } | |
123 if (lprefix) { | |
124 if (matches) { | |
125 @@ -260,7 +271,9 @@ match(void) | |
126 matches = lsubstr; | |
127 matchend = substrend; | |
128 } | |
129 - curr = sel = matches; | |
130 + if (!preserve) | |
131 + curr = sel = matches; | |
132 + | |
133 calcoffsets(); | |
134 } | |
135 | |
136 @@ -519,40 +532,11 @@ paste(void) | |
137 } | |
138 | |
139 static void | |
140 -readstdin(void) | |
141 -{ | |
142 - char buf[sizeof text], *p; | |
143 - size_t i, imax = 0, size = 0; | |
144 - unsigned int tmpmax = 0; | |
145 - | |
146 - /* read each line from stdin and add it to the item list */ | |
147 - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { | |
148 - if (i + 1 >= size / sizeof *items) | |
149 - if (!(items = realloc(items, (size += BUFSIZ)))) | |
150 - die("cannot realloc %u bytes:", size); | |
151 - if ((p = strchr(buf, '\n'))) | |
152 - *p = '\0'; | |
153 - if (!(items[i].text = strdup(buf))) | |
154 - die("cannot strdup %u bytes:", strlen(buf) + 1); | |
155 - items[i].out = 0; | |
156 - drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax,… | |
157 - if (tmpmax > inputw) { | |
158 - inputw = tmpmax; | |
159 - imax = i; | |
160 - } | |
161 - } | |
162 - if (items) | |
163 - items[i].text = NULL; | |
164 - inputw = items ? TEXTW(items[imax].text) : 0; | |
165 - lines = MIN(lines, i); | |
166 -} | |
167 - | |
168 -static void | |
169 -run(void) | |
170 +readevent(void) | |
171 { | |
172 XEvent ev; | |
173 | |
174 - while (!XNextEvent(dpy, &ev)) { | |
175 + while (XPending(dpy) && !XNextEvent(dpy, &ev)) { | |
176 if (XFilterEvent(&ev, None)) | |
177 continue; | |
178 switch(ev.type) { | |
179 @@ -580,6 +564,80 @@ run(void) | |
180 } | |
181 } | |
182 | |
183 +static void | |
184 +readstdin(void) | |
185 +{ | |
186 + size_t max = 0; | |
187 + char buf[sizeof text], *p, *maxstr; | |
188 + struct item *item; | |
189 + int ctrloffset = 0; | |
190 + | |
191 + | |
192 + /* read each line from stdin and add it to the item list */ | |
193 + while (fgets(buf, sizeof buf, stdin)) { | |
194 + if (!(item = malloc(sizeof *item))) | |
195 + die("cannot malloc %u bytes:", sizeof *item); | |
196 + if ((p = strchr(buf, '\n'))) | |
197 + *p = '\0'; | |
198 + | |
199 + ctrloffset = 0; | |
200 + while (ctrloffset + 1 < sizeof buf && ( | |
201 + buf[ctrloffset] == '\a' || | |
202 + buf[ctrloffset] == '\b' || | |
203 + buf[ctrloffset] == '\f' | |
204 + )) { | |
205 + if (buf[ctrloffset] == '\a') | |
206 + sel = item; | |
207 + if (buf[ctrloffset] == '\b') | |
208 + curr = item; | |
209 + if (buf[ctrloffset] == '\f') | |
210 + itemstail = sel = curr = items = NULL; | |
211 + ctrloffset++; | |
212 + } | |
213 + | |
214 + if (!(item->text = strdup(buf+ctrloffset))) | |
215 + die("cannot strdup %u bytes:", strlen(buf+ctrlo… | |
216 + if (strlen(item->text) > max) { | |
217 + max = strlen(maxstr = item->text); | |
218 + inputw = maxstr ? TEXTW(maxstr) : 0; | |
219 + } | |
220 + item->out = 0; | |
221 + item->next = NULL; | |
222 + | |
223 + if (items == NULL) | |
224 + items = item; | |
225 + if (itemstail) | |
226 + itemstail->next = item; | |
227 + itemstail = item; | |
228 + } | |
229 + match(); | |
230 + drawmenu(); | |
231 +} | |
232 + | |
233 +static void | |
234 +run(void) | |
235 +{ | |
236 + fd_set fds; | |
237 + int flags, xfd = XConnectionNumber(dpy); | |
238 + | |
239 + if ((flags = fcntl(0, F_GETFL)) == -1) | |
240 + die("cannot get stdin control flags:"); | |
241 + if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1) | |
242 + die("cannot set stdin control flags:"); | |
243 + for (;;) { | |
244 + FD_ZERO(&fds); | |
245 + FD_SET(xfd, &fds); | |
246 + if (!feof(stdin)) | |
247 + FD_SET(0, &fds); | |
248 + if (select(xfd + 1, &fds, NULL, NULL, NULL) == -1) | |
249 + die("cannot multiplex input:"); | |
250 + if (FD_ISSET(xfd, &fds)) | |
251 + readevent(); | |
252 + if (FD_ISSET(0, &fds)) | |
253 + readstdin(); | |
254 + } | |
255 +} | |
256 + | |
257 static void | |
258 setup(void) | |
259 { | |
260 @@ -682,7 +740,7 @@ setup(void) | |
261 static void | |
262 usage(void) | |
263 { | |
264 - fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [… | |
265 + fputs("usage: dmenu [-biv] [-l lines] [-p prompt] [-fn font] [-… | |
266 " [-nb color] [-nf color] [-sb color] [-sf co… | |
267 exit(1); | |
268 } | |
269 @@ -691,7 +749,7 @@ int | |
270 main(int argc, char *argv[]) | |
271 { | |
272 XWindowAttributes wa; | |
273 - int i, fast = 0; | |
274 + int i; | |
275 | |
276 for (i = 1; i < argc; i++) | |
277 /* these options take no arguments */ | |
278 @@ -700,8 +758,6 @@ main(int argc, char *argv[]) | |
279 exit(0); | |
280 } else if (!strcmp(argv[i], "-b")) /* appears at the bo… | |
281 topbar = 0; | |
282 - else if (!strcmp(argv[i], "-f")) /* grabs keyboard be… | |
283 - fast = 1; | |
284 else if (!strcmp(argv[i], "-i")) { /* case-insensitive … | |
285 fstrncmp = strncasecmp; | |
286 fstrstr = cistrstr; | |
287 @@ -752,13 +808,7 @@ main(int argc, char *argv[]) | |
288 die("pledge"); | |
289 #endif | |
290 | |
291 - if (fast && !isatty(0)) { | |
292 - grabkeyboard(); | |
293 - readstdin(); | |
294 - } else { | |
295 - readstdin(); | |
296 - grabkeyboard(); | |
297 - } | |
298 + grabkeyboard(); | |
299 setup(); | |
300 run(); | |
301 | |
302 -- | |
303 2.25.4 | |
304 |