shithub: bar

Download patch

ref: 49cca4636e049d4b70c4cdca646d3e79228cf805
parent: 287d533fb09f017e5c933f0f761ac09428806e6a
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Jan 26 13:22:57 EST 2021

bar: write to stdout the item that was clicked

--- a/README.md
+++ b/README.md
@@ -10,4 +10,10 @@
 `bar` reads additional data from standard input and displays it along
 with other information.
 
+When clicked, `bar` writes to standard output a single line of text,
+consisting of two fields, separated by a tab: buttons pressed (number)
+and the text of the item that was pressed.  This may be used for
+additional actions defined by an optional user's script on the right
+side of a pipe.
+
 ![screenshot](scr.png)
--- a/bar.c
+++ b/bar.c
@@ -13,10 +13,11 @@
 	Off = 3,
 };
 
-static int wctl, owidth, width, twidth, bottom, bat, minheight;
-static Image *cback, *ctext;
+static int wctl, owidth, width, twidth, bottom, bat, minheight, seplen, sepw;
 static char sep[16], bats[16], *aux;
-static char *pos = "rb";
+static char *pos = "rb", *items[64];
+static int itemw[64], nitems;
+static Image *cback, *ctext;
 static Tzone *local;
 static Font *f;
 
@@ -106,9 +107,28 @@
 }
 
 static void
+split(char *s)
+{
+	char *i;
+
+	for(nitems = 0, i = s; nitems < nelem(items); s += seplen, i = s){
+		if((s = strstr(s, sep)) != nil)
+			*s = 0;
+		if(*i == 0)
+			continue;
+		items[nitems] = i;
+		itemw[nitems++] = stringwidth(f, i) + sepw;
+		if(s == nil)
+			break;
+	}
+	
+}
+
+static void
 redraw(void)
 {
-	char s[128];
+	static char s[128];
+	char tmp[128];
 	Rectangle r;
 	Tmfmt tf;
 	Point p;
@@ -130,14 +150,15 @@
 			p.x = r.max.x - (stringwidth(f, s) + Off);
 	}
 	string(screen, p, ctext, ZP, f, s);
+	split(s);
 
 	flushimage(display, 1);
 	unlockdisplay(display);
 
-	snprint(s, sizeof(s), "%τ", tf);
-	twidth = MAX(twidth, stringwidth(f, s));
-	snprint(s, sizeof(s), "%|%s%|%s", bats, bats[0] ? "100%" : "", aux, aux);
-	width = twidth + stringwidth(f, s);
+	snprint(tmp, sizeof(tmp), "%τ", tf);
+	twidth = MAX(twidth, stringwidth(f, tmp));
+	snprint(tmp, sizeof(tmp), "%|%s%|%s", bats, bats[0] ? "100%" : "", aux, aux);
+	width = twidth + stringwidth(f, tmp);
 	if(owidth != width)
 		place();
 }
@@ -209,11 +230,26 @@
 	threadexitsall("usage");
 }
 
+static void
+clicked(int x, int buttons)
+{
+	int i, ix;
+
+	for(i = ix = 0; i < nitems; i++){
+		ix += itemw[i];
+		if(x <= ix){
+			fprint(1, "%d\t%s\n", buttons, items[i]);
+			break;
+		}
+	}
+}
+
 void
 threadmain(int argc, char **argv)
 {
 	Keyboardctl *kctl;
 	Mousectl *mctl;
+	int oldbuttons;
 	char *s, *v[3];
 	u32int brgb;
 	Biobuf *b;
@@ -248,6 +284,7 @@
 	default:
 		usage();
 	}ARGEND
+	seplen = strlen(sep);
 
 	fmtinstall('|', sepfmt);
 	tmfmtinstall();
@@ -273,6 +310,7 @@
 		sysfatal("initdraw: %r");
 	f = display->defaultfont;
 	minheight = 2*(Borderwidth+1) + f->height;
+	sepw = stringwidth(f, sep);
 	unlockdisplay(display);
 	if((mctl = initmouse(nil, screen)) == nil)
 		sysfatal("initmouse: %r");
@@ -295,11 +333,11 @@
 	proccreate(updateproc, nil, 4096);
 	proccreate(auxproc, a[Eaux].c, 16384);
 
+	m.buttons = 0;
 	for(;;){
-		switch(alt(a)){
-		case Emouse:
-			break;
+		oldbuttons = m.buttons;
 
+		switch(alt(a)){
 		case Ekeyboard:
 			if(key == Kdel){
 				close(wctl);
@@ -308,18 +346,26 @@
 			}
 			break;
 
+		case Emouse:
+			if(m.buttons == 0 || m.buttons == oldbuttons)
+				break;
+			clicked(m.xy.x-screen->r.min.x, m.buttons);
+			/* wet floor */
+
+		if(0){
 		case Eresize:
 			if(getwindow(display, Refnone) < 0)
 				threadexitsall(nil);
-			redraw();
-			place();
-			break;
+			/* wet floor */
+		}
 
+		if(0){
 		case Eaux:
 			if(wctl >= 0)
 				fprint(wctl, bottom ? "bottom" : "top");
 			free(aux);
 			aux = s;
+		}
 			redraw();
 			place();
 			break;