merge token -> default 50207344
Connor Lane Smith · 2011-09-20 00:11 2 file(s) · +41 −33
dmenu.1 +6 −9
25 25
.BR dmenu_run " ..."
26 26
.SH DESCRIPTION
27 27
.B dmenu
28 -
is a dynamic menu for X, originally designed for
29 -
.IR dwm (1).
30 -
It manages huge numbers of user\-defined menu items efficiently.
31 -
.P
32 -
dmenu reads a list of newline\-separated items from stdin and creates a menu.
33 -
When the user selects an item or enters any text and presses Return, their
34 -
choice is printed to stdout and dmenu terminates.
28 +
is a dynamic menu for X, which reads a list of newline\-separated items from
29 +
stdin.  When the user selects an item and presses Return, their choice is printed
30 +
to stdout and dmenu terminates.  Entering text will narrow the items to those
31 +
matching the tokens in the input.
35 32
.P
36 33
.B dmenu_run
37 34
is a dmenu script used by dwm which lists programs in the user's $PATH and
42 39
dmenu appears at the bottom of the screen.
43 40
.TP
44 41
.B \-f
45 -
dmenu grabs the keyboard before reading stdin.  This is faster, but may lock up
46 -
X if stdin is from a terminal.
42 +
dmenu grabs the keyboard before reading stdin.  This is faster, but will lock up
43 +
X until stdin reaches end\-of\-file.
47 44
.TP
48 45
.B \-i
49 46
dmenu matches menu items case insensitively.
dmenu.c +35 −24
30 30
static void grabkeyboard(void);
31 31
static void insert(const char *str, ssize_t n);
32 32
static void keypress(XKeyEvent *ev);
33 -
static void match(Bool sub);
33 +
static void match(void);
34 34
static size_t nextrune(int inc);
35 35
static void paste(void);
36 36
static void readstdin(void);
120 120
121 121
void
122 122
appenditem(Item *item, Item **list, Item **last) {
123 -
	if(!*last)
124 -
		*list = item;
125 -
	else
123 +
	if(*last)
126 124
		(*last)->right = item;
125 +
	else
126 +
		*list = item;
127 127
128 128
	item->left = *last;
129 129
	item->right = NULL;
223 223
	if(n > 0)
224 224
		memcpy(&text[cursor], str, n);
225 225
	cursor += n;
226 -
	match(n > 0 && text[cursor] == '\0');
226 +
	match();
227 227
}
228 228
229 229
void
252 252
253 253
		case XK_k: /* delete right */
254 254
			text[cursor] = '\0';
255 -
			match(False);
255 +
			match();
256 256
			break;
257 257
		case XK_u: /* delete left */
258 258
			insert(NULL, 0 - cursor);
355 355
			return;
356 356
		strncpy(text, sel->text, sizeof text);
357 357
		cursor = strlen(text);
358 -
		match(True);
358 +
		match();
359 359
		break;
360 360
	}
361 361
	drawmenu();
362 362
}
363 363
364 364
void
365 -
match(Bool sub) {
366 -
	size_t len = strlen(text);
367 -
	Item *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend;
368 -
	Item *item, *lnext;
365 +
match(void) {
366 +
	static char **tokv = NULL;
367 +
	static int tokn = 0;
368 +
369 +
	char buf[sizeof text], *s;
370 +
	int i, tokc = 0;
371 +
	size_t len;
372 +
	Item *item, *lprefix, *lsubstr, *prefixend, *substrend;
373 +
374 +
	strcpy(buf, text);
375 +
	for(s = strtok(buf, " "); s; tokv[tokc-1] = s, s = strtok(NULL, " "))
376 +
		if(++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
377 +
			eprintf("cannot realloc %u bytes\n", tokn * sizeof *tokv);
378 +
	len = tokc ? strlen(tokv[0]) : 0;
369 379
370 -
	lexact = lprefix = lsubstr = exactend = prefixend = substrend = NULL;
371 -
	for(item = sub ? matches : items; item && item->text; item = lnext) {
372 -
		lnext = sub ? item->right : item + 1;
373 -
		if(!fstrncmp(text, item->text, len + 1))
374 -
			appenditem(item, &lexact, &exactend);
375 -
		else if(!fstrncmp(text, item->text, len))
380 +
	matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
381 +
	for(item = items; item && item->text; item++) {
382 +
		for(i = 0; i < tokc; i++)
383 +
			if(!fstrstr(item->text, tokv[i]))
384 +
				break;
385 +
		if(i != tokc)
386 +
			continue;
387 +
		if(!tokc || !fstrncmp(tokv[0], item->text, len+1))
388 +
			appenditem(item, &matches, &matchend);
389 +
		else if(!fstrncmp(tokv[0], item->text, len))
376 390
			appenditem(item, &lprefix, &prefixend);
377 -
		else if(fstrstr(item->text, text))
391 +
		else
378 392
			appenditem(item, &lsubstr, &substrend);
379 393
	}
380 -
	matches = lexact;
381 -
	matchend = exactend;
382 -
383 394
	if(lprefix) {
384 -
		if(matchend) {
395 +
		if(matches) {
385 396
			matchend->right = lprefix;
386 397
			lprefix->left = matchend;
387 398
		}
390 401
		matchend = prefixend;
391 402
	}
392 403
	if(lsubstr) {
393 -
		if(matchend) {
404 +
		if(matches) {
394 405
			matchend->right = lsubstr;
395 406
			lsubstr->left = matchend;
396 407
		}
519 530
	}
520 531
	promptw = prompt ? textw(dc, prompt) : 0;
521 532
	inputw = MIN(inputw, mw/3);
522 -
	match(False);
533 +
	match();
523 534
524 535
	/* menu window */
525 536
	swa.override_redirect = True;