diff options
-rw-r--r-- | config.def.h | 2 | ||||
-rw-r--r-- | config.h | 2 | ||||
-rw-r--r-- | dmenu-dynamicoptions-5.0.diff | 92 | ||||
-rw-r--r-- | dmenu.c | 68 |
4 files changed, 158 insertions, 6 deletions
diff --git a/config.def.h b/config.def.h index 946df52..ce0a2d3 100644 --- a/config.def.h +++ b/config.def.h @@ -12,6 +12,8 @@ static const char *fonts[] = { }; static char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *dynamic = + NULL; /* -dy option; dynamic command to run on input change */ static char normfgcolor[] = "#bbbbbb"; static char normbgcolor[] = "#222222"; @@ -12,6 +12,8 @@ static const char *fonts[] = { }; static char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *dynamic = + NULL; /* -dy option; dynamic command to run on input change */ static char normfgcolor[] = "#bbbbbb"; static char normbgcolor[] = "#222222"; diff --git a/dmenu-dynamicoptions-5.0.diff b/dmenu-dynamicoptions-5.0.diff new file mode 100644 index 0000000..2614115 --- /dev/null +++ b/dmenu-dynamicoptions-5.0.diff @@ -0,0 +1,92 @@ +diff --git a/dmenu.1 b/dmenu.1 +index 323f93c..1ae3fe3 100644 +--- a/dmenu.1 ++++ b/dmenu.1 +@@ -22,6 +22,8 @@ dmenu \- dynamic menu + .IR color ] + .RB [ \-w + .IR windowid ] ++.RB [ \-dy ++.IR command ] + .P + .BR dmenu_run " ..." + .SH DESCRIPTION +@@ -80,6 +82,9 @@ prints version information to stdout, then exits. + .TP + .BI \-w " windowid" + embed into windowid. ++.TP ++.BI \-dy " command" ++runs command whenever input changes to update menu items. + .SH USAGE + dmenu is completely controlled by the keyboard. Items are selected using the + arrow keys, page up, page down, home, and end. +diff --git a/dmenu.c b/dmenu.c +index 65f25ce..6780122 100644 +--- a/dmenu.c ++++ b/dmenu.c +@@ -519,14 +571,14 @@ paste(void) + } + + static void +-readstdin(void) ++readstdin(FILE* stream) + { + char buf[sizeof text], *p; + size_t i, imax = 0, size = 0; + unsigned int tmpmax = 0; + + /* read each line from stdin and add it to the item list */ +- for (i = 0; fgets(buf, sizeof buf, stdin); i++) { ++ for (i = 0; fgets(buf, sizeof buf, stream); i++) { + if (i + 1 >= size / sizeof *items) + if (!(items = realloc(items, (size += BUFSIZ)))) + die("cannot realloc %u bytes:", size); +@@ -544,7 +596,7 @@ readstdin(void) + if (items) + items[i].text = NULL; + inputw = items ? TEXTW(items[imax].text) : 0; +- lines = MIN(lines, i); ++ lines = MIN(max_lines, i); + } + + static void +@@ -690,7 +742,8 @@ static void + usage(void) + { + fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" +- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); ++ " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n" ++ " [-dy command]\n", stderr); + exit(1); + } + +@@ -733,6 +786,8 @@ main(int argc, char *argv[]) + colors[SchemeSel][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-w")) /* embedding window id */ + embed = argv[++i]; ++ else if (!strcmp(argv[i], "-dy")) /* dynamic command to run */ ++ dynamic = argv[++i] && *argv[i] ? argv[i] : NULL; + else + usage(); + +@@ -757,11 +812,14 @@ main(int argc, char *argv[]) + die("pledge"); + #endif + ++ max_lines = lines; + if (fast && !isatty(0)) { + grabkeyboard(); +- readstdin(); ++ if (!dynamic) ++ readstdin(stdin); + } else { +- readstdin(); ++ if (!dynamic) ++ readstdin(stdin); + grabkeyboard(); + } + setup(); +-- +2.34.1 + @@ -62,6 +62,7 @@ static struct item *items = NULL; static struct item *matches, *matchend; static struct item *prev, *curr, *next, *sel; static int mon = -1, screen; +static unsigned int max_lines = 0; static Atom clip, utf8; static Display *dpy; @@ -302,6 +303,45 @@ static void grabkeyboard(void) { die("cannot grab keyboard"); } +static void readstdin(FILE *stream); + +static void refreshoptions() { + int dynlen = strlen(dynamic); + int cmdlen = dynlen + 4; + char *cmd; + char *c; + char *t = text; + while (*t) + cmdlen += *t++ == '\'' ? 4 : 1; + cmd = malloc(cmdlen); + if (cmd == NULL) + die("cannot malloc %u bytes:", cmdlen); + strcpy(cmd, dynamic); + t = text; + c = cmd + dynlen; + *(c++) = ' '; + *(c++) = '\''; + while (*t) { + // prefix ' with '\' + if (*t == '\'') { + *(c++) = '\''; + *(c++) = '\\'; + *(c++) = '\''; + } + *(c++) = *(t++); + } + *(c++) = '\''; + *(c++) = 0; + FILE *stream = popen(cmd, "r"); + if (!stream) + die("could not popen dynamic command (%s):", cmd); + readstdin(stream); + int r = pclose(stream); + if (r == -1) + die("could not pclose dynamic command"); + free(cmd); +} + int compare_distance(const void *a, const void *b) { struct item *da = *(struct item **)a; struct item *db = *(struct item **)b; @@ -398,6 +438,16 @@ static void match(void) { size_t len, textsize; struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; + if (dynamic) { + refreshoptions(); + matches = matchend = NULL; + for (item = items; item && item->text; item++) + appenditem(item, &matches, &matchend); + curr = sel = matches; + calcoffsets(); + return; + } + strcpy(buf, text); /* separate input text into tokens to be matched individually */ for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) @@ -777,13 +827,13 @@ static void paste(void) { drawmenu(); } -static void readstdin(void) { +static void readstdin(FILE *stream) { char buf[sizeof text], *p; size_t i, imax = 0, size = 0; unsigned int tmpmax = 0; /* read each line from stdin and add it to the item list */ - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { + for (i = 0; fgets(buf, sizeof buf, stream); i++) { if (i + 1 >= size / sizeof *items) if (!(items = realloc(items, (size += BUFSIZ)))) die("cannot realloc %u bytes:", size); @@ -814,7 +864,7 @@ static void readstdin(void) { if (items) items[i].text = NULL; inputw = items ? TEXTW(items[imax].text) : 0; - lines = MIN(lines, i); + lines = MIN(max_lines, i); } void resource_load(XrmDatabase db, char *name, enum resource_type rtype, @@ -1009,7 +1059,8 @@ static void usage(void) { fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" " [-nb color] [-nf color] [-sb color] [-sf color]\n" " [-nhb color] [-nhf color] [-shb color] [-shf color]\n" - " [-d separator] [-D separator] [-w windowid]\n", + " [-d separator] [-D separator] [-dy command] [-w " + "windowid]\n", stderr); exit(1); } @@ -1074,6 +1125,8 @@ int main(int argc, char *argv[]) { separator_reverse = argv[i][1] == '|'; } else if (!strcmp(argv[i], "-w")) /* embedding window id */ embed = argv[++i]; + else if (!strcmp(argv[i], "-dy")) /* dynamic command to run */ + dynamic = argv[++i] && *argv[i] ? argv[i] : NULL; else usage(); @@ -1097,11 +1150,14 @@ int main(int argc, char *argv[]) { die("pledge"); #endif + max_lines = lines; if (fast && !isatty(0)) { grabkeyboard(); - readstdin(); + if (!dynamic) + readstdin(stdin); } else { - readstdin(); + if (!dynamic) + readstdin(stdin); grabkeyboard(); } setup(); |