dmenu-nonblockingstdincontrol-4.9.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dmenu-nonblockingstdincontrol-4.9.diff (7742B)
       ---
            1 From 1a2f76ad1a0ebf65ae7739cd102b69c02fdcd0ba Mon Sep 17 00:00:00 2001
            2 From: Miles Alan <m@milesalan.com>
            3 Date: Wed, 30 Sep 2020 08:16:47 -0500
            4 Subject: [PATCH] nonblockingstdincontrol: Add Non-blocking stdin and control
            5  character reloading
            6 
            7 Read from stdin continously in parallel to X events. And also adds support
            8 for using control characters for reloading options (e.g. emptying list
            9 and setting curr/sel).
           10 
           11 The following control characters are supported when sent at the beginning of
           12 a line:
           13 \f - Clear the current items prior to following line
           14 \a - Set the following line to be equal to sel
           15 \b - Set the following line to be equal to curr
           16 ---
           17  dmenu.1 |   6 +--
           18  dmenu.c | 144 ++++++++++++++++++++++++++++++++++++++------------------
           19  2 files changed, 98 insertions(+), 52 deletions(-)
           20 
           21 diff --git a/dmenu.1 b/dmenu.1
           22 index 323f93c..a07532d 100644
           23 --- a/dmenu.1
           24 +++ b/dmenu.1
           25 @@ -3,7 +3,7 @@
           26  dmenu \- dynamic menu
           27  .SH SYNOPSIS
           28  .B dmenu
           29 -.RB [ \-bfiv ]
           30 +.RB [ \-biv ]
           31  .RB [ \-l
           32  .IR lines ]
           33  .RB [ \-m
           34 @@ -40,10 +40,6 @@ which lists programs in the user's $PATH and runs the result in their $SHELL.
           35  .B \-b
           36  dmenu appears at the bottom of the screen.
           37  .TP
           38 -.B \-f
           39 -dmenu grabs the keyboard before reading stdin if not reading from a tty. This
           40 -is faster, but will lock up X until stdin reaches end\-of\-file.
           41 -.TP
           42  .B \-i
           43  dmenu matches menu items case insensitively.
           44  .TP
           45 diff --git a/dmenu.c b/dmenu.c
           46 index 6b8f51b..cc87b04 100644
           47 --- a/dmenu.c
           48 +++ b/dmenu.c
           49 @@ -1,5 +1,6 @@
           50  /* See LICENSE file for copyright and license details. */
           51  #include <ctype.h>
           52 +#include <fcntl.h>
           53  #include <locale.h>
           54  #include <stdio.h>
           55  #include <stdlib.h>
           56 @@ -8,6 +9,8 @@
           57  #include <time.h>
           58  #include <unistd.h>
           59  
           60 +
           61 +#include <sys/select.h>
           62  #include <X11/Xlib.h>
           63  #include <X11/Xatom.h>
           64  #include <X11/Xutil.h>
           65 @@ -31,6 +34,7 @@ enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */
           66  struct item {
           67          char *text;
           68          struct item *left, *right;
           69 +        struct item *next;
           70          int out;
           71  };
           72  
           73 @@ -41,6 +45,7 @@ static int inputw = 0, promptw;
           74  static int lrpad; /* sum of left and right padding */
           75  static size_t cursor;
           76  static struct item *items = NULL;
           77 +static struct item *itemstail= NULL;
           78  static struct item *matches, *matchend;
           79  static struct item *prev, *curr, *next, *sel;
           80  static int mon = -1, screen;
           81 @@ -173,6 +178,7 @@ drawmenu(void)
           82                  }
           83          }
           84          drw_map(drw, win, 0, 0, mw, mh);
           85 +        XFlush(dpy);
           86  }
           87  
           88  static void
           89 @@ -220,6 +226,7 @@ match(void)
           90          int i, tokc = 0;
           91          size_t len, textsize;
           92          struct item *item, *lprefix, *lsubstr, *prefixend, *substrend;
           93 +        int preserve = 0;
           94  
           95          strcpy(buf, text);
           96          /* separate input text into tokens to be matched individually */
           97 @@ -230,19 +237,23 @@ match(void)
           98  
           99          matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
          100          textsize = strlen(text) + 1;
          101 -        for (item = items; item && item->text; item++) {
          102 +        for (item = items; item; item = item->next) {
          103                  for (i = 0; i < tokc; i++)
          104                          if (!fstrstr(item->text, tokv[i]))
          105                                  break;
          106                  if (i != tokc) /* not all tokens match */
          107                          continue;
          108                  /* exact matches go first, then prefixes, then substrings */
          109 -                if (!tokc || !fstrncmp(text, item->text, textsize))
          110 +                if (!tokc || !fstrncmp(text, item->text, textsize)) {
          111                          appenditem(item, &matches, &matchend);
          112 -                else if (!fstrncmp(tokv[0], item->text, len))
          113 +                        if (sel == item) preserve = 1;
          114 +                } else if (!fstrncmp(tokv[0], item->text, len)) {
          115                          appenditem(item, &lprefix, &prefixend);
          116 -                else
          117 +                        if (sel == item) preserve = 1;
          118 +                } else {
          119                          appenditem(item, &lsubstr, &substrend);
          120 +                        if (sel == item) preserve = 1;
          121 +                }
          122          }
          123          if (lprefix) {
          124                  if (matches) {
          125 @@ -260,7 +271,9 @@ match(void)
          126                          matches = lsubstr;
          127                  matchend = substrend;
          128          }
          129 -        curr = sel = matches;
          130 +        if (!preserve)
          131 +                curr = sel = matches;
          132 +
          133          calcoffsets();
          134  }
          135  
          136 @@ -519,40 +532,11 @@ paste(void)
          137  }
          138  
          139  static void
          140 -readstdin(void)
          141 -{
          142 -        char buf[sizeof text], *p;
          143 -        size_t i, imax = 0, size = 0;
          144 -        unsigned int tmpmax = 0;
          145 -
          146 -        /* read each line from stdin and add it to the item list */
          147 -        for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
          148 -                if (i + 1 >= size / sizeof *items)
          149 -                        if (!(items = realloc(items, (size += BUFSIZ))))
          150 -                                die("cannot realloc %u bytes:", size);
          151 -                if ((p = strchr(buf, '\n')))
          152 -                        *p = '\0';
          153 -                if (!(items[i].text = strdup(buf)))
          154 -                        die("cannot strdup %u bytes:", strlen(buf) + 1);
          155 -                items[i].out = 0;
          156 -                drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL);
          157 -                if (tmpmax > inputw) {
          158 -                        inputw = tmpmax;
          159 -                        imax = i;
          160 -                }
          161 -        }
          162 -        if (items)
          163 -                items[i].text = NULL;
          164 -        inputw = items ? TEXTW(items[imax].text) : 0;
          165 -        lines = MIN(lines, i);
          166 -}
          167 -
          168 -static void
          169 -run(void)
          170 +readevent(void)
          171  {
          172          XEvent ev;
          173  
          174 -        while (!XNextEvent(dpy, &ev)) {
          175 +        while (XPending(dpy) && !XNextEvent(dpy, &ev)) {
          176                  if (XFilterEvent(&ev, None))
          177                          continue;
          178                  switch(ev.type) {
          179 @@ -580,6 +564,80 @@ run(void)
          180          }
          181  }
          182  
          183 +static void
          184 +readstdin(void)
          185 +{
          186 +        size_t max = 0;
          187 +        char buf[sizeof text], *p, *maxstr;
          188 +        struct item *item;
          189 +        int ctrloffset = 0;
          190 +
          191 +
          192 +        /* read each line from stdin and add it to the item list */
          193 +        while (fgets(buf, sizeof buf, stdin)) {
          194 +                if (!(item = malloc(sizeof *item)))
          195 +                        die("cannot malloc %u bytes:", sizeof *item);
          196 +                if ((p = strchr(buf, '\n')))
          197 +                        *p = '\0';
          198 +
          199 +                ctrloffset = 0;
          200 +                while (ctrloffset + 1 < sizeof buf && (
          201 +                        buf[ctrloffset] == '\a' ||
          202 +                        buf[ctrloffset] == '\b' ||
          203 +                        buf[ctrloffset] == '\f'
          204 +                )) {
          205 +                        if (buf[ctrloffset] == '\a')
          206 +                                sel = item;
          207 +                        if (buf[ctrloffset] == '\b')
          208 +                                curr = item;
          209 +                        if (buf[ctrloffset] == '\f')
          210 +                                itemstail = sel = curr = items = NULL;
          211 +                        ctrloffset++;
          212 +                }
          213 +
          214 +                if (!(item->text = strdup(buf+ctrloffset)))
          215 +                        die("cannot strdup %u bytes:", strlen(buf+ctrloffset)+1);
          216 +                if (strlen(item->text) > max) {
          217 +                        max = strlen(maxstr = item->text);
          218 +                        inputw = maxstr ? TEXTW(maxstr) : 0;
          219 +                }
          220 +                item->out = 0;
          221 +                item->next = NULL;
          222 +
          223 +                if (items == NULL)
          224 +                        items = item;
          225 +                if (itemstail)
          226 +                        itemstail->next = item;
          227 +                itemstail = item;
          228 +        }
          229 +        match();
          230 +        drawmenu();
          231 +}
          232 +
          233 +static void
          234 +run(void)
          235 +{
          236 +        fd_set fds;
          237 +        int flags, xfd = XConnectionNumber(dpy);
          238 +
          239 +        if ((flags = fcntl(0, F_GETFL)) == -1)
          240 +                die("cannot get stdin control flags:");
          241 +        if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1)
          242 +                die("cannot set stdin control flags:");
          243 +        for (;;) {
          244 +                FD_ZERO(&fds);
          245 +                FD_SET(xfd, &fds);
          246 +                if (!feof(stdin))
          247 +                        FD_SET(0, &fds);
          248 +                if (select(xfd + 1, &fds, NULL, NULL, NULL) == -1)
          249 +                        die("cannot multiplex input:");
          250 +                if (FD_ISSET(xfd, &fds))
          251 +                        readevent();
          252 +                if (FD_ISSET(0, &fds))
          253 +                        readstdin();
          254 +        }
          255 +}
          256 +
          257  static void
          258  setup(void)
          259  {
          260 @@ -682,7 +740,7 @@ setup(void)
          261  static void
          262  usage(void)
          263  {
          264 -        fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
          265 +        fputs("usage: dmenu [-biv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
          266                "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
          267          exit(1);
          268  }
          269 @@ -691,7 +749,7 @@ int
          270  main(int argc, char *argv[])
          271  {
          272          XWindowAttributes wa;
          273 -        int i, fast = 0;
          274 +        int i;
          275  
          276          for (i = 1; i < argc; i++)
          277                  /* these options take no arguments */
          278 @@ -700,8 +758,6 @@ main(int argc, char *argv[])
          279                          exit(0);
          280                  } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */
          281                          topbar = 0;
          282 -                else if (!strcmp(argv[i], "-f"))   /* grabs keyboard before reading stdin */
          283 -                        fast = 1;
          284                  else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
          285                          fstrncmp = strncasecmp;
          286                          fstrstr = cistrstr;
          287 @@ -752,13 +808,7 @@ main(int argc, char *argv[])
          288                  die("pledge");
          289  #endif
          290  
          291 -        if (fast && !isatty(0)) {
          292 -                grabkeyboard();
          293 -                readstdin();
          294 -        } else {
          295 -                readstdin();
          296 -                grabkeyboard();
          297 -        }
          298 +        grabkeyboard();
          299          setup();
          300          run();
          301  
          302 -- 
          303 2.25.4
          304