aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.def.h2
-rw-r--r--config.h2
-rw-r--r--dmenu-dynamicoptions-5.0.diff92
-rw-r--r--dmenu.c68
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";
diff --git a/config.h b/config.h
index 946df52..ce0a2d3 100644
--- a/config.h
+++ b/config.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";
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
+
diff --git a/dmenu.c b/dmenu.c
index e940e57..3dfbeb8 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -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();