1 From 01e2dfc79126a7600463b4cf9fa16b4be6886cae Mon Sep 17 00:00:00 2001 2 From: Tiago Teles <tiago.sequeira.teles@gmail.com> 3 Date: Tue, 26 May 2020 19:55:55 +0100 4 Subject: [PATCH] -dy flag for dynamic menu updating 5 6 This patch adds a flag (`-dy`) which makes dmenu run the command given to it 7 whenever input is changed with the current input as the last argument and 8 update the option list according to the output of that command. 9 --- 10 config.def.h | 1 + 11 dmenu.c | 43 ++++++++++++++++++++++++++++++++++++------- 12 2 files changed, 37 insertions(+), 7 deletions(-) 13 14 diff --git a/config.def.h b/config.def.h 15 index 1edb6477..035b8777 100644 16 --- a/config.def.h 17 +++ b/config.def.h 18 @@ -7,6 +7,7 @@ static const char *fonts[] = { 19 "monospace:size=10" 20 }; 21 static const char *prompt = NULL; /* -p option; prompt to the left of input field */ 22 +static const char *dynamic = NULL; /* -dy option; dynamic command to run on input change */ 23 static const char *colors[SchemeLast][2] = { 24 /* fg bg */ 25 [SchemeNorm] = { "#bbbbbb", "#222222" }, 26 diff --git a/dmenu.c b/dmenu.c 27 index 6b8f51b5..356d4cc9 100644 28 --- a/dmenu.c 29 +++ b/dmenu.c 30 @@ -210,9 +210,33 @@ grabkeyboard(void) 31 die("cannot grab keyboard"); 32 } 33 34 +static void readstdin(FILE* stream); 35 + 36 +static void 37 +refreshoptions(){ 38 + int dynlen = strlen(dynamic); 39 + char* cmd= malloc(dynlen + strlen(text)+2); 40 + if(cmd == NULL) 41 + die("malloc:"); 42 + sprintf(cmd,"%s %s",dynamic, text); 43 + FILE *stream = popen(cmd, "r"); 44 + if(!stream) 45 + die("popen(%s):",cmd); 46 + readstdin(stream); 47 + int pc = pclose(stream); 48 + if(pc == -1) 49 + die("pclose:"); 50 + free(cmd); 51 + curr = sel = items; 52 +} 53 + 54 static void 55 match(void) 56 { 57 + if(dynamic && *dynamic){ 58 + refreshoptions(); 59 + } 60 + 61 static char **tokv = NULL; 62 static int tokn = 0; 63 64 @@ -234,7 +258,7 @@ match(void) 65 for (i = 0; i < tokc; i++) 66 if (!fstrstr(item->text, tokv[i])) 67 break; 68 - if (i != tokc) /* not all tokens match */ 69 + if (i != tokc && !(dynamic && *dynamic)) /* not all tokens match */ 70 continue; 71 /* exact matches go first, then prefixes, then substrings */ 72 if (!tokc || !fstrncmp(text, item->text, textsize)) 73 @@ -519,14 +543,14 @@ paste(void) 74 } 75 76 static void 77 -readstdin(void) 78 +readstdin(FILE* stream) 79 { 80 char buf[sizeof text], *p; 81 size_t i, imax = 0, size = 0; 82 unsigned int tmpmax = 0; 83 84 /* read each line from stdin and add it to the item list */ 85 - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { 86 + for (i = 0; fgets(buf, sizeof buf, stream); i++) { 87 if (i + 1 >= size / sizeof *items) 88 if (!(items = realloc(items, (size += BUFSIZ)))) 89 die("cannot realloc %u bytes:", size); 90 @@ -544,7 +568,8 @@ readstdin(void) 91 if (items) 92 items[i].text = NULL; 93 inputw = items ? TEXTW(items[imax].text) : 0; 94 - lines = MIN(lines, i); 95 + if (!dynamic || !*dynamic) 96 + lines = MIN(lines, i); 97 } 98 99 static void 100 @@ -683,7 +708,7 @@ static void 101 usage(void) 102 { 103 fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" 104 - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); 105 + " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n" "[-dy command]\n", stderr); 106 exit(1); 107 } 108 109 @@ -726,6 +751,8 @@ main(int argc, char *argv[]) 110 colors[SchemeSel][ColFg] = argv[++i]; 111 else if (!strcmp(argv[i], "-w")) /* embedding window id */ 112 embed = argv[++i]; 113 + else if (!strcmp(argv[i], "-dy")) /* dynamic command to run */ 114 + dynamic = argv[++i]; 115 else 116 usage(); 117 118 @@ -754,9 +781,11 @@ main(int argc, char *argv[]) 119 120 if (fast && !isatty(0)) { 121 grabkeyboard(); 122 - readstdin(); 123 + if(!(dynamic && *dynamic)) 124 + readstdin(stdin); 125 } else { 126 - readstdin(); 127 + if(!(dynamic && *dynamic)) 128 + readstdin(stdin); 129 grabkeyboard(); 130 } 131 setup(); 132 -- 133 2.26.2 134