shithub: dmenu

Download patch

ref: 7d29d072f84e97ed311932b3a3cfdbeca317f4f9
parent: bc69d3c62762f155e54e487f2145cd7fe3224ce7
author: glenda <[email protected]>
date: Sun Sep 5 19:41:28 EDT 2021

renamed from sel/line to just dmenu

--- /dev/null
+++ b/dmenu.c
@@ -1,0 +1,367 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+
+#define Ctl(c) ((c) - 64)
+#define PROMPT "  > "
+
+enum
+{
+	BACK,
+	HBACK,
+	TEXT,
+	HTEXT,
+	NCOLORS
+};
+
+Image *color[NCOLORS];
+char **lines, **matches, *buffer;
+usize nlines, nmatches, scroll;
+Rune kbinput[512];
+int selected;
+
+static void
+readbuffer(void)
+{
+	Biobuf *bp;
+	char *line, *s;
+
+	if((bp = Bfdopen(0, OREAD)) == nil)
+		sysfatal("setting buffering on fd0: %r");
+	if((buffer = Brdstr(bp, '\0', 1)) == nil)
+		sysfatal("reading input lines: %r");
+
+	for(line = s = buffer; s = strchr(s, '\n'); line = ++s){
+		*s = '\0';
+		if((lines = realloc(lines, ++nlines * sizeof *lines)) == nil)
+			sysfatal("malloc: %r");
+		lines[nlines-1] = line;
+	}
+
+	if((matches = malloc(nlines * sizeof *lines)) == nil)
+		sysfatal("malloc: %r");
+	memmove(matches, lines, nlines * sizeof *lines);
+	nmatches = nlines;
+}
+
+static Point
+linetopoint(int ln)
+{
+	ln -= scroll;
+	return Pt(screen->r.min.x, screen->r.min.y + (ln + 2) * font->height);
+}
+
+static int
+pointtoline(Point pt)
+{
+	return (pt.y - screen->r.min.y) / font->height - 2 + scroll;
+}
+
+static void
+drawbackground(Point pt, Image *color)
+{
+	draw(screen,
+	  Rect(screen->r.min.x, pt.y, screen->r.max.x, pt.y + font->height),
+	  color, nil, ZP);
+}
+
+static Point
+tabstring(Image *dst, Point dp, Image *src, Point sp, Font *f, char *s)
+{
+	Rune r[2] = {L'0', L'\0'};
+	int n, w0, x;
+	Point op;
+
+	op = dp;
+	w0 = stringwidth(f, "0");
+	for(; *s && (n = chartorune(r, s)) > 0; s += n){
+		if(r[0] == '\t'){
+			x = 8 * w0 - (dp.x - op.x) % (8 * w0);
+			sp.x += x;
+			dp.x += x;
+		}else{
+			dp = runestring(dst, dp, src, sp, f, r);
+		}
+	}
+	return dp;
+}
+
+static void
+drawprompt(void)
+{
+	Point pt;
+	char buf[512];
+
+	snprint(buf, sizeof buf, PROMPT"%S▏", kbinput);
+	pt = Pt(screen->r.max.x, screen->r.min.y + font->height * 2);
+	draw(screen, Rpt(screen->r.min, pt), color[BACK], nil, ZP);
+	pt = Pt(screen->r.min.x, screen->r.min.y + font->height);
+	tabstring(screen, pt, color[TEXT], ZP, font, buf);
+}
+
+static int
+drawline(int ln)
+{
+	Point pt = linetopoint(ln);
+	Image *bgcolor, *txcolor;
+
+	if(ln < scroll)
+		return 1;
+	if(ln == selected){
+		bgcolor = color[HBACK];
+		txcolor = color[HTEXT];
+	}else{
+		bgcolor = color[BACK];
+		txcolor = color[TEXT];
+	}
+	pt.x += stringwidth(font, PROMPT);
+	drawbackground(pt, bgcolor);
+	if(ln < nmatches)
+		tabstring(screen, pt, txcolor, ZP, font, matches[ln]);
+	return pt.y < screen->r.max.y;
+}
+
+void
+eresized(int new)
+{
+	int i;
+
+	if(new && getwindow(display, Refnone) < 0)
+		sysfatal("resize failed: %r");
+
+	drawprompt();
+	for(i = scroll; drawline(i); i++);
+}
+
+int
+match(char *s, char **words, int nwords)
+{
+	char **w;
+
+	if(nwords == 0)
+		return 1;
+	for(w = words; w < words + nwords; w++)
+		if(cistrstr(s, *w) == nil)
+			return 0;
+	return 1;
+}
+
+void
+filter(char **lines, int nlines)
+{
+	char *buf, *words[64], **l, **m;
+	int nwords;
+
+	if((buf = smprint("%S", kbinput)) == nil)
+		sysfatal("malloc");
+	nwords = tokenize(buf, words, sizeof words / sizeof *words);
+
+	nmatches = 0;
+	m = matches;
+	for(l = lines; l < lines + nlines; l++)
+		if(match(*l, words, nwords)){
+			*m++ = *l;
+			nmatches++;
+		}
+
+	selected = 0;
+	scroll = 0;
+	free(buf);
+	eresized(0); /* possibly different lines: redraw everything */
+}
+
+static void
+kbadd(Rune r)
+{
+	int len = runestrlen(kbinput);
+
+	if(len == sizeof kbinput / sizeof *kbinput)
+		return;
+	kbinput[len++] = r;
+	kbinput[len] = L'\0';
+
+	filter(matches, nmatches);
+}
+
+static void
+kbbackspace(void)
+{
+	usize len = runestrlen(kbinput);
+
+	if(len == 0)
+		return;
+	kbinput[len - 1] = L'\0';
+
+	filter(lines, nlines);
+}
+
+static void
+kbdelword(void)
+{
+	usize len = runestrlen(kbinput);
+
+	if(len == 0)
+		return;
+	while(len > 0 && isspacerune(kbinput[len-1]))
+		len--;
+	while(len > 0 && !isspacerune(kbinput[len-1]))
+		len--;
+	kbinput[len] = L'\0';
+
+	filter(lines, nlines);
+}
+
+static void
+kbclear(void)
+{
+	kbinput[0] = L'\0';
+
+	filter(lines, nlines);
+}
+
+static void
+kbmove(int n)
+{
+	int old = selected;
+
+	if(selected + n < 0)
+		selected = 0;
+	else if(selected + n >= nmatches)
+		selected = nmatches - 1;
+	else
+		selected += n;
+
+	drawline(old);
+	drawline(selected);
+}
+
+static void
+kbscroll(int percent)
+{
+	int ln = Dy(screen->r) / font->height * percent / 100;
+
+	if(ln < 0 && abs(ln) > scroll)
+		scroll = 0;
+	else if(ln > 0 && scroll + ln >= nmatches)
+		scroll = nmatches - 1 + (nmatches > 0);
+	else
+		scroll += ln;
+
+	eresized(0);
+}
+
+static void
+mselect(Point pt)
+{
+	int old, sel = pointtoline(pt);
+
+	if(sel < 0)
+		sel = 0;
+	if(nmatches > 0 && sel >= nmatches)
+		sel = nmatches - 1;
+	if(sel != selected){
+		old = selected;
+		selected = sel;
+		drawline(old);
+		drawline(sel);
+	}
+}
+
+static void
+usage(void)
+{
+	print("usage: %s [-b] <choices\n", argv0);
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	Event e;
+	int bflag = 0;
+
+	ARGBEGIN{
+	case 'b':
+		bflag = 1;
+		break;
+	default:
+		usage();
+	}ARGEND;
+
+	readbuffer();
+
+	if(initdraw(nil, nil, "linesel") < 0)
+		sysfatal("initdraw: %r");
+
+	if(bflag){
+		color[TEXT] = display->white;
+		color[BACK] = display->black;
+	}else{
+		color[TEXT] = display->black;
+		color[BACK] = display->white;
+	}
+	color[HTEXT] = display->black;
+	color[HBACK] = allocimage(display,
+	  Rect(0,0,1,1), screen->chan, 1, DPaleyellow);
+
+	eresized(0);
+
+	einit(Emouse|Ekeyboard);
+	for(;;){
+		switch(event(&e)){
+		case -1:
+			sysfatal("watching events: %r");
+
+		case Ekeyboard:
+			switch(e.kbdc){
+			case Kdel:
+				exits("interrupted with Del");
+			case '\n':
+				goto End;
+			case Kbs:
+				kbbackspace();
+				break;
+			case Ctl('W'):
+				kbdelword();
+				break;
+			case Ctl('U'):
+				kbclear();
+				break;
+			case Kup:
+				kbmove(-1);
+				break;
+			case Kdown:
+				kbmove(+1);
+				break;
+			case Kpgdown:
+				kbscroll(+40);
+				break;
+			case Kpgup:
+				kbscroll(-40);
+				break;
+			default:
+				kbadd(e.kbdc);
+				break;
+			}
+			break;
+
+		case Emouse:
+			if(e.mouse.buttons&1)
+				mselect(e.mouse.xy);
+			if(e.mouse.buttons&4)
+				goto End;
+			if(e.mouse.buttons&8)
+				kbscroll(-40);
+			if(e.mouse.buttons&16)
+				kbscroll(+40);
+			break;
+		}
+	}
+End:
+	if(nmatches > 0)
+		print("%s\n", matches[selected]);
+	exits(nil);
+}
--- a/line.c
+++ /dev/null
@@ -1,365 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <draw.h>
-#include <event.h>
-#include <keyboard.h>
-
-#define Ctl(c) ((c) - 64)
-#define PROMPT "  > "
-
-enum
-{
-	BACK,
-	HBACK,
-	TEXT,
-	HTEXT,
-	NCOLORS
-};
-
-Image *color[NCOLORS];
-char **lines, **matches, *buffer;
-usize nlines, nmatches, scroll;
-Rune kbinput[512];
-int selected;
-
-static void
-readbuffer(void)
-{
-	Biobuf *bp;
-	char *line, *s;
-
-	if((bp = Bfdopen(0, OREAD)) == nil)
-		sysfatal("setting buffering on fd0: %r");
-	if((buffer = Brdstr(bp, '\0', 1)) == nil)
-		sysfatal("reading input lines: %r");
-
-	for(line = s = buffer; s = strchr(s, '\n'); line = ++s){
-		*s = '\0';
-		if((lines = realloc(lines, ++nlines * sizeof *lines)) == nil)
-			sysfatal("malloc: %r");
-		lines[nlines-1] = line;
-	}
-
-	if((matches = malloc(nlines * sizeof *lines)) == nil)
-		sysfatal("malloc: %r");
-	memmove(matches, lines, nlines * sizeof *lines);
-	nmatches = nlines;
-}
-
-static Point
-linetopoint(int ln)
-{
-	ln -= scroll;
-	return Pt(screen->r.min.x, screen->r.min.y + (ln + 2) * font->height);
-}
-
-static int
-pointtoline(Point pt)
-{
-	return (pt.y - screen->r.min.y) / font->height - 2 + scroll;
-}
-
-static void
-drawbackground(Point pt, Image *color)
-{
-	draw(screen,
-	  Rect(screen->r.min.x, pt.y, screen->r.max.x, pt.y + font->height),
-	  color, nil, ZP);
-}
-
-static Point
-tabstring(Image *dst, Point dp, Image *src, Point sp, Font *f, char *s)
-{
-	Rune r[2] = {L'0', L'\0'};
-	int n, w0, x;
-	Point op;
-
-	op = dp;
-	w0 = stringwidth(f, "0");
-	for(; *s && (n = chartorune(r, s)) > 0; s += n){
-		if(r[0] == '\t'){
-			x = 8 * w0 - (dp.x - op.x) % (8 * w0);
-			sp.x += x;
-			dp.x += x;
-		}else{
-			dp = runestring(dst, dp, src, sp, f, r);
-		}
-	}
-	return dp;
-}
-
-static void
-drawprompt(void)
-{
-	Point pt;
-	char buf[512];
-
-	snprint(buf, sizeof buf, PROMPT"%S▏", kbinput);
-	pt = Pt(screen->r.max.x, screen->r.min.y + font->height * 2);
-	draw(screen, Rpt(screen->r.min, pt), color[BACK], nil, ZP);
-	pt = Pt(screen->r.min.x, screen->r.min.y + font->height);
-	tabstring(screen, pt, color[TEXT], ZP, font, buf);
-}
-
-static int
-drawline(int ln)
-{
-	Point pt = linetopoint(ln);
-	Image *bgcolor, *txcolor;
-
-	if(ln < scroll)
-		return 1;
-	if(ln == selected){
-		bgcolor = color[HBACK];
-		txcolor = color[HTEXT];
-	}else{
-		bgcolor = color[BACK];
-		txcolor = color[TEXT];
-	}
-	pt.x += stringwidth(font, PROMPT);
-	drawbackground(pt, bgcolor);
-	if(ln < nmatches)
-		tabstring(screen, pt, txcolor, ZP, font, matches[ln]);
-	return pt.y < screen->r.max.y;
-}
-
-void
-eresized(int new)
-{
-	int i;
-
-	if(new && getwindow(display, Refnone) < 0)
-		sysfatal("resize failed: %r");
-
-	drawprompt();
-	for(i = scroll; drawline(i); i++);
-}
-
-int
-match(char *s, char **words, int nwords)
-{
-	char **w;
-
-	if(nwords == 0)
-		return 1;
-	for(w = words; w < words + nwords; w++)
-		if(cistrstr(s, *w) == nil)
-			return 0;
-	return 1;
-}
-
-void
-filter(char **lines, int nlines)
-{
-	char *buf, *words[64], **l, **m;
-	int nwords;
-
-	if((buf = smprint("%S", kbinput)) == nil)
-		sysfatal("malloc");
-	nwords = tokenize(buf, words, sizeof words / sizeof *words);
-
-	nmatches = 0;
-	m = matches;
-	for(l = lines; l < lines + nlines; l++)
-		if(match(*l, words, nwords)){
-			*m++ = *l;
-			nmatches++;
-		}
-
-	selected = 0;
-	scroll = 0;
-	free(buf);
-	eresized(0); /* possibly different lines: redraw everything */
-}
-
-static void
-kbadd(Rune r)
-{
-	int len = runestrlen(kbinput);
-
-	if(len == sizeof kbinput / sizeof *kbinput)
-		return;
-	kbinput[len++] = r;
-	kbinput[len] = L'\0';
-
-	filter(matches, nmatches);
-}
-
-static void
-kbbackspace(void)
-{
-	usize len = runestrlen(kbinput);
-
-	if(len == 0)
-		return;
-	kbinput[len - 1] = L'\0';
-
-	filter(lines, nlines);
-}
-
-static void
-kbdelword(void)
-{
-	usize len = runestrlen(kbinput);
-
-	if(len == 0)
-		return;
-	while(len > 0 && isspacerune(kbinput[len-1]))
-		len--;
-	while(len > 0 && !isspacerune(kbinput[len-1]))
-		len--;
-	kbinput[len] = L'\0';
-
-	filter(lines, nlines);
-}
-
-static void
-kbclear(void)
-{
-	kbinput[0] = L'\0';
-
-	filter(lines, nlines);
-}
-
-static void
-kbmove(int n)
-{
-	int old = selected;
-
-	if(selected + n < 0)
-		selected = 0;
-	else if(selected + n >= nmatches)
-		selected = nmatches - 1;
-	else
-		selected += n;
-	drawline(old);
-	drawline(selected);
-}
-
-static void
-kbscroll(int percent)
-{
-	int ln = Dy(screen->r) / font->height * percent / 100;
-
-	if(ln < 0 && abs(ln) > scroll)
-		scroll = 0;
-	else if(ln > 0 && scroll + ln >= nmatches)
-		scroll = nmatches - 1 + (nmatches > 0);
-	else
-		scroll += ln;
-	eresized(0);
-}
-
-static void
-mselect(Point pt)
-{
-	int old, sel = pointtoline(pt);
-
-	if(sel < 0)
-		sel = 0;
-	if(nmatches > 0 && sel >= nmatches)
-		sel = nmatches - 1;
-	if(sel != selected){
-		old = selected;
-		selected = sel;
-		drawline(old);
-		drawline(sel);
-	}
-}
-
-static void
-usage(void)
-{
-	print("usage: %s [-b] <choices\n", argv0);
-	exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
-	Event e;
-	int bflag = 0;
-
-	ARGBEGIN{
-	case 'b':
-		bflag = 1;
-		break;
-	default:
-		usage();
-	}ARGEND;
-
-	readbuffer();
-
-	if(initdraw(nil, nil, "linesel") < 0)
-		sysfatal("initdraw: %r");
-
-	if(bflag){
-		color[TEXT] = display->white;
-		color[BACK] = display->black;
-	}else{
-		color[TEXT] = display->black;
-		color[BACK] = display->white;
-	}
-	color[HTEXT] = display->black;
-	color[HBACK] = allocimage(display,
-	  Rect(0,0,1,1), screen->chan, 1, DPaleyellow);
-
-	eresized(0);
-
-	einit(Emouse|Ekeyboard);
-	for(;;){
-		switch(event(&e)){
-		case -1:
-			sysfatal("watching events: %r");
-
-		case Ekeyboard:
-			switch(e.kbdc){
-			case Kdel:
-				exits("interrupted with Del");
-			case '\n':
-				goto End;
-			case Kbs:
-				kbbackspace();
-				break;
-			case Ctl('W'):
-				kbdelword();
-				break;
-			case Ctl('U'):
-				kbclear();
-				break;
-			case Kup:
-				kbmove(-1);
-				break;
-			case Kdown:
-				kbmove(+1);
-				break;
-			case Kpgdown:
-				kbscroll(+40);
-				break;
-			case Kpgup:
-				kbscroll(-40);
-				break;
-			default:
-				kbadd(e.kbdc);
-				break;
-			}
-			break;
-
-		case Emouse:
-			if(e.mouse.buttons&1)
-				mselect(e.mouse.xy);
-			if(e.mouse.buttons&4)
-				goto End;
-			if(e.mouse.buttons&8)
-				kbscroll(-40);
-			if(e.mouse.buttons&16)
-				kbscroll(+40);
-			break;
-		}
-	}
-End:
-	if(nmatches > 0)
-		print("%s\n", matches[selected]);
-	exits(nil);
-}
--- a/mkfile
+++ b/mkfile
@@ -1,16 +1,9 @@
 </$objtype/mkfile
 
-TARG=\
-	line\
-
+TARG= dmenu
 HFILES=
-
+OFILES= dmenu.$O
 LIB= /$objtype/lib/libdraw.a
-BIN= /$objtype/bin/sel
+BIN= /$objtype/bin
 
-</sys/src/cmd/mkmany
-
-install: $BIN
-
-$BIN:
-	mkdir -p $target
+</sys/src/cmd/mkone