diff options
Diffstat (limited to '')
| -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();  | 
