sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dmenu-dynamicoptions-5.0.diff (5263B)


      1 From f70735c476c25da46f9e44b835ac967e0dfa4d85 Mon Sep 17 00:00:00 2001
      2 From: Ziad EL KHOURY HANNA <me@ziadkh.ovh>
      3 Date: Mon, 29 Nov 2021 17:36:35 +0100
      4 Subject: [PATCH] add `-dy` flag for dynamic menu updating
      5 
      6 `-dy` flag makes dmenu run the command given to it whenever input is
      7 changed with the current input as the last argument and update the
      8 option list according to the output of that command.
      9 
     10 Based on dynamic options patch by ttmx <tiago.sequeira.teles@gmail.com>.
     11 Adds proper quoting of the given command.
     12 Adds option to man file documentation.
     13 ---
     14  config.def.h |  1 +
     15  dmenu.1      |  5 ++++
     16  dmenu.c      | 70 +++++++++++++++++++++++++++++++++++++++++++++++-----
     17  3 files changed, 70 insertions(+), 6 deletions(-)
     18 
     19 diff --git a/config.def.h b/config.def.h
     20 index 1edb647..035b877 100644
     21 --- a/config.def.h
     22 +++ b/config.def.h
     23 @@ -7,6 +7,7 @@ static const char *fonts[] = {
     24  	"monospace:size=10"
     25  };
     26  static const char *prompt      = NULL;      /* -p  option; prompt to the left of input field */
     27 +static const char *dynamic     = NULL;      /* -dy option; dynamic command to run on input change */
     28  static const char *colors[SchemeLast][2] = {
     29  	/*     fg         bg       */
     30  	[SchemeNorm] = { "#bbbbbb", "#222222" },
     31 diff --git a/dmenu.1 b/dmenu.1
     32 index 323f93c..1ae3fe3 100644
     33 --- a/dmenu.1
     34 +++ b/dmenu.1
     35 @@ -22,6 +22,8 @@ dmenu \- dynamic menu
     36  .IR color ]
     37  .RB [ \-w
     38  .IR windowid ]
     39 +.RB [ \-dy
     40 +.IR command ]
     41  .P
     42  .BR dmenu_run " ..."
     43  .SH DESCRIPTION
     44 @@ -80,6 +82,9 @@ prints version information to stdout, then exits.
     45  .TP
     46  .BI \-w " windowid"
     47  embed into windowid.
     48 +.TP
     49 +.BI \-dy " command"
     50 +runs command whenever input changes to update menu items.
     51  .SH USAGE
     52  dmenu is completely controlled by the keyboard.  Items are selected using the
     53  arrow keys, page up, page down, home, and end.
     54 diff --git a/dmenu.c b/dmenu.c
     55 index 65f25ce..6780122 100644
     56 --- a/dmenu.c
     57 +++ b/dmenu.c
     58 @@ -44,6 +44,7 @@ static struct item *items = NULL;
     59  static struct item *matches, *matchend;
     60  static struct item *prev, *curr, *next, *sel;
     61  static int mon = -1, screen;
     62 +static unsigned int max_lines = 0;
     63  
     64  static Atom clip, utf8;
     65  static Display *dpy;
     66 @@ -210,6 +211,47 @@ grabkeyboard(void)
     67  	die("cannot grab keyboard");
     68  }
     69  
     70 +static void readstdin(FILE* stream);
     71 +
     72 +static void
     73 +refreshoptions()
     74 +{
     75 +	int dynlen = strlen(dynamic);
     76 +	int cmdlen = dynlen + 4;
     77 +	char *cmd;
     78 +	char *c;
     79 +	char *t = text;
     80 +	while (*t)
     81 +		cmdlen += *t++ == '\'' ? 4 : 1;
     82 +	cmd = malloc(cmdlen);
     83 +	if (cmd == NULL)
     84 +		die("cannot malloc %u bytes:", cmdlen);
     85 +	strcpy(cmd, dynamic);
     86 +	t = text;
     87 +	c = cmd + dynlen;
     88 +	*(c++) = ' ';
     89 +	*(c++) = '\'';
     90 +	while (*t) {
     91 +		// prefix ' with '\'
     92 +		if (*t == '\'') {
     93 +			*(c++) = '\'';
     94 +			*(c++) = '\\';
     95 +			*(c++) = '\'';
     96 +		}
     97 +		*(c++) = *(t++);
     98 +	}
     99 +	*(c++) = '\'';
    100 +	*(c++) = 0;
    101 +	FILE *stream = popen(cmd, "r");
    102 +	if (!stream)
    103 +		die("could not popen dynamic command (%s):", cmd);
    104 +	readstdin(stream);
    105 +	int r = pclose(stream);
    106 +	if (r == -1)
    107 +		die("could not pclose dynamic command");
    108 +	free(cmd);
    109 +}
    110 +
    111  static void
    112  match(void)
    113  {
    114 @@ -221,6 +263,16 @@ match(void)
    115  	size_t len, textsize;
    116  	struct item *item, *lprefix, *lsubstr, *prefixend, *substrend;
    117  
    118 +	if (dynamic) {
    119 +		refreshoptions();
    120 +		matches = matchend = NULL;
    121 +		for (item = items; item && item->text; item++)
    122 +			appenditem(item, &matches, &matchend);
    123 +		curr = sel = matches;
    124 +		calcoffsets();
    125 +		return;
    126 +	}
    127 +
    128  	strcpy(buf, text);
    129  	/* separate input text into tokens to be matched individually */
    130  	for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
    131 @@ -519,14 +571,14 @@ paste(void)
    132  }
    133  
    134  static void
    135 -readstdin(void)
    136 +readstdin(FILE* stream)
    137  {
    138  	char buf[sizeof text], *p;
    139  	size_t i, imax = 0, size = 0;
    140  	unsigned int tmpmax = 0;
    141  
    142  	/* read each line from stdin and add it to the item list */
    143 -	for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
    144 +	for (i = 0; fgets(buf, sizeof buf, stream); i++) {
    145  		if (i + 1 >= size / sizeof *items)
    146  			if (!(items = realloc(items, (size += BUFSIZ))))
    147  				die("cannot realloc %u bytes:", size);
    148 @@ -544,7 +596,7 @@ readstdin(void)
    149  	if (items)
    150  		items[i].text = NULL;
    151  	inputw = items ? TEXTW(items[imax].text) : 0;
    152 -	lines = MIN(lines, i);
    153 +	lines = MIN(max_lines, i);
    154  }
    155  
    156  static void
    157 @@ -690,7 +742,8 @@ static void
    158  usage(void)
    159  {
    160  	fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
    161 -	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
    162 +	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n"
    163 +	      "             [-dy command]\n", stderr);
    164  	exit(1);
    165  }
    166  
    167 @@ -733,6 +786,8 @@ main(int argc, char *argv[])
    168  			colors[SchemeSel][ColFg] = argv[++i];
    169  		else if (!strcmp(argv[i], "-w"))   /* embedding window id */
    170  			embed = argv[++i];
    171 +		else if (!strcmp(argv[i], "-dy"))  /* dynamic command to run */
    172 +			dynamic = argv[++i] && *argv[i] ? argv[i] : NULL;
    173  		else
    174  			usage();
    175  
    176 @@ -757,11 +812,14 @@ main(int argc, char *argv[])
    177  		die("pledge");
    178  #endif
    179  
    180 +	max_lines = lines;
    181  	if (fast && !isatty(0)) {
    182  		grabkeyboard();
    183 -		readstdin();
    184 +		if (!dynamic)
    185 +			readstdin(stdin);
    186  	} else {
    187 -		readstdin();
    188 +		if (!dynamic)
    189 +			readstdin(stdin);
    190  		grabkeyboard();
    191  	}
    192  	setup();
    193 -- 
    194 2.34.1
    195