commit 375254cef9738528a4dbf276a43744f2aedf0d18
Author: Ziad EL KHOURY HANNA <[email protected]>
Date:   Mon Nov 29 17:43:25 2021 +0100

    [dmenu][patches][dynamicoptions] Add new improved version of the patch

diff --git 
a/tools.suckless.org/dmenu/patches/dynamicoptions/dmenu-dynamicoptions-5.0.diff 
b/tools.suckless.org/dmenu/patches/dynamicoptions/dmenu-dynamicoptions-5.0.diff
new file mode 100644
index 00000000..e26f3bd8
--- /dev/null
+++ 
b/tools.suckless.org/dmenu/patches/dynamicoptions/dmenu-dynamicoptions-5.0.diff
@@ -0,0 +1,195 @@
+From f70735c476c25da46f9e44b835ac967e0dfa4d85 Mon Sep 17 00:00:00 2001
+From: Ziad EL KHOURY HANNA <[email protected]>
+Date: Mon, 29 Nov 2021 17:36:35 +0100
+Subject: [PATCH] add `-dy` flag for dynamic menu updating
+
+`-dy` flag makes dmenu run the command given to it whenever input is
+changed with the current input as the last argument and update the
+option list according to the output of that command.
+
+Based on dynamic options patch by ttmx <[email protected]>.
+Adds proper quoting of the given command.
+Adds option to man file documentation.
+---
+ config.def.h |  1 +
+ dmenu.1      |  5 ++++
+ dmenu.c      | 70 +++++++++++++++++++++++++++++++++++++++++++++++-----
+ 3 files changed, 70 insertions(+), 6 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1edb647..035b877 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -7,6 +7,7 @@ static const char *fonts[] = {
+       "monospace:size=10"
+ };
+ static const 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 const char *colors[SchemeLast][2] = {
+       /*     fg         bg       */
+       [SchemeNorm] = { "#bbbbbb", "#222222" },
+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
+@@ -44,6 +44,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;
+@@ -210,6 +211,47 @@ 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);
++}
++
+ static void
+ match(void)
+ {
+@@ -221,6 +263,16 @@ 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, " "))
+@@ -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]
"
+-            "             [-nb color] [-nf color] [-sb color] [-sf color] [-w 
windowid]
", stderr);
++            "             [-nb color] [-nf color] [-sb color] [-sf color] [-w 
windowid]
"
++            "             [-dy command]
", 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/tools.suckless.org/dmenu/patches/dynamicoptions/index.md 
b/tools.suckless.org/dmenu/patches/dynamicoptions/index.md
index 3410fe97..c4d65855 100644
--- a/tools.suckless.org/dmenu/patches/dynamicoptions/index.md
+++ b/tools.suckless.org/dmenu/patches/dynamicoptions/index.md
@@ -16,8 +16,10 @@ in dmenu and lets you select it)
 
 Download
 --------
-* 
[dmenu-dynamicoptions-20200526-01e2dfc7.diff](dmenu-dynamicoptions-20200526-01e2dfc7.diff)
+* [dmenu-dynamicoptions-5.0.diff](dmenu-dynamicoptions-5.0.diff) (with proper 
command quoting)
+* 
[dmenu-dynamicoptions-20200526-01e2dfc7.diff](dmenu-dynamicoptions-20200526-01e2dfc7.diff)
 (2020-05-26)
 
 Author
 ------
-* ttmx - [email protected]
+* ttmx - [email protected] (2020-05-26)
+* Ziad EL KHOURY HANNA - [email protected] (5.0)


Reply via email to