dmenu-navhistory-5.0.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dmenu-navhistory-5.0.diff (5744B)
       ---
            1 From a4a08baf35edb6b50ed14f76e99d0c6fe790759d Mon Sep 17 00:00:00 2001
            2 From: Max Schillinger <maxschillinger@web.de>
            3 Date: Fri, 9 Jul 2021 17:17:36 +0200
            4 Subject: [PATCH] Bug fix: Writing first entry to history file was skipped
            5 
            6 ---
            7  config.def.h |   2 +
            8  dmenu.1      |   5 ++
            9  dmenu.c      | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++-
           10  dmenu_run    |   2 +-
           11  4 files changed, 151 insertions(+), 2 deletions(-)
           12 
           13 diff --git a/config.def.h b/config.def.h
           14 index 1edb647..e3e1b53 100644
           15 --- a/config.def.h
           16 +++ b/config.def.h
           17 @@ -15,6 +15,8 @@ static const char *colors[SchemeLast][2] = {
           18  };
           19  /* -l option; if nonzero, dmenu uses vertical list with given number of lines */
           20  static unsigned int lines      = 0;
           21 +static unsigned int maxhist    = 64;
           22 +static int histnodup           = 1;        /* if 0, record repeated histories */
           23  
           24  /*
           25   * Characters not considered part of a word while deleting words
           26 diff --git a/dmenu.1 b/dmenu.1
           27 index 323f93c..ff496dd 100644
           28 --- a/dmenu.1
           29 +++ b/dmenu.1
           30 @@ -22,6 +22,8 @@ dmenu \- dynamic menu
           31  .IR color ]
           32  .RB [ \-w
           33  .IR windowid ]
           34 +.RB [ \-H
           35 +.IR histfile ]
           36  .P
           37  .BR dmenu_run " ..."
           38  .SH DESCRIPTION
           39 @@ -80,6 +82,9 @@ prints version information to stdout, then exits.
           40  .TP
           41  .BI \-w " windowid"
           42  embed into windowid.
           43 +.TP
           44 +.BI \-H " histfile"
           45 +save input in histfile and use it for history navigation.
           46  .SH USAGE
           47  dmenu is completely controlled by the keyboard.  Items are selected using the
           48  arrow keys, page up, page down, home, and end.
           49 diff --git a/dmenu.c b/dmenu.c
           50 index 65f25ce..5023257 100644
           51 --- a/dmenu.c
           52 +++ b/dmenu.c
           53 @@ -53,6 +53,10 @@ static XIC xic;
           54  static Drw *drw;
           55  static Clr *scheme[SchemeLast];
           56  
           57 +static char *histfile;
           58 +static char **history;
           59 +static size_t histsz, histpos;
           60 +
           61  #include "config.h"
           62  
           63  static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
           64 @@ -304,6 +308,129 @@ movewordedge(int dir)
           65          }
           66  }
           67  
           68 +static void
           69 +loadhistory(void)
           70 +{
           71 +        FILE *fp = NULL;
           72 +        static size_t cap = 0;
           73 +        size_t llen;
           74 +        char *line;
           75 +
           76 +        if (!histfile) {
           77 +                return;
           78 +        }
           79 +
           80 +        fp = fopen(histfile, "r");
           81 +        if (!fp) {
           82 +                return;
           83 +        }
           84 +
           85 +        for (;;) {
           86 +                line = NULL;
           87 +                llen = 0;
           88 +                if (-1 == getline(&line, &llen, fp)) {
           89 +                        if (ferror(fp)) {
           90 +                                die("failed to read history");
           91 +                        }
           92 +                        free(line);
           93 +                        break;
           94 +                }
           95 +
           96 +                if (cap == histsz) {
           97 +                        cap += 64 * sizeof(char*);
           98 +                        history = realloc(history, cap);
           99 +                        if (!history) {
          100 +                                die("failed to realloc memory");
          101 +                        }
          102 +                }
          103 +                strtok(line, "\n");
          104 +                history[histsz] = line;
          105 +                histsz++;
          106 +        }
          107 +        histpos = histsz;
          108 +
          109 +        if (fclose(fp)) {
          110 +                die("failed to close file %s", histfile);
          111 +        }
          112 +}
          113 +
          114 +static void
          115 +navhistory(int dir)
          116 +{
          117 +        static char def[BUFSIZ];
          118 +        char *p = NULL;
          119 +        size_t len = 0;
          120 +
          121 +        if (!history || histpos + 1 == 0)
          122 +                return;
          123 +
          124 +        if (histsz == histpos) {
          125 +                strncpy(def, text, sizeof(def));
          126 +        }
          127 +
          128 +        switch(dir) {
          129 +        case 1:
          130 +                if (histpos < histsz - 1) {
          131 +                        p = history[++histpos];
          132 +                } else if (histpos == histsz - 1) {
          133 +                        p = def;
          134 +                        histpos++;
          135 +                }
          136 +                break;
          137 +        case -1:
          138 +                if (histpos > 0) {
          139 +                        p = history[--histpos];
          140 +                }
          141 +                break;
          142 +        }
          143 +        if (p == NULL) {
          144 +                return;
          145 +        }
          146 +
          147 +        len = MIN(strlen(p), BUFSIZ - 1);
          148 +        strncpy(text, p, len);
          149 +        text[len] = '\0';
          150 +        cursor = len;
          151 +        match();
          152 +}
          153 +
          154 +static void
          155 +savehistory(char *input)
          156 +{
          157 +        unsigned int i;
          158 +        FILE *fp;
          159 +
          160 +        if (!histfile ||
          161 +            0 == maxhist ||
          162 +            0 == strlen(input)) {
          163 +                goto out;
          164 +        }
          165 +
          166 +        fp = fopen(histfile, "w");
          167 +        if (!fp) {
          168 +                die("failed to open %s", histfile);
          169 +        }
          170 +        for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
          171 +                if (0 >= fprintf(fp, "%s\n", history[i])) {
          172 +                        die("failed to write to %s", histfile);
          173 +                }
          174 +        }
          175 +        if (histsz == 0 || !histnodup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) { /* TODO */
          176 +                if (0 >= fputs(input, fp)) {
          177 +                        die("failed to write to %s", histfile);
          178 +                }
          179 +        }
          180 +        if (fclose(fp)) {
          181 +                die("failed to close file %s", histfile);
          182 +        }
          183 +
          184 +out:
          185 +        for (i = 0; i < histsz; i++) {
          186 +                free(history[i]);
          187 +        }
          188 +        free(history);
          189 +}
          190 +
          191  static void
          192  keypress(XKeyEvent *ev)
          193  {
          194 @@ -388,6 +515,14 @@ keypress(XKeyEvent *ev)
          195                  case XK_j: ksym = XK_Next;  break;
          196                  case XK_k: ksym = XK_Prior; break;
          197                  case XK_l: ksym = XK_Down;  break;
          198 +                case XK_p:
          199 +                        navhistory(-1);
          200 +                        buf[0]=0;
          201 +                        break;
          202 +                case XK_n:
          203 +                        navhistory(1);
          204 +                        buf[0]=0;
          205 +                        break;
          206                  default:
          207                          return;
          208                  }
          209 @@ -466,6 +601,8 @@ insert:
          210          case XK_KP_Enter:
          211                  puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
          212                  if (!(ev->state & ControlMask)) {
          213 +                        savehistory((sel && !(ev->state & ShiftMask))
          214 +                                    ? sel->text : text);
          215                          cleanup();
          216                          exit(0);
          217                  }
          218 @@ -690,7 +827,8 @@ static void
          219  usage(void)
          220  {
          221          fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
          222 -              "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
          223 +              "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n"
          224 +              "             [-H histfile]", stderr);
          225          exit(1);
          226  }
          227  
          228 @@ -715,6 +853,8 @@ main(int argc, char *argv[])
          229                  } else if (i + 1 == argc)
          230                          usage();
          231                  /* these options take one argument */
          232 +                else if (!strcmp(argv[i], "-H"))
          233 +                        histfile = argv[++i];
          234                  else if (!strcmp(argv[i], "-l"))   /* number of lines in vertical list */
          235                          lines = atoi(argv[++i]);
          236                  else if (!strcmp(argv[i], "-m"))
          237 @@ -757,6 +897,8 @@ main(int argc, char *argv[])
          238                  die("pledge");
          239  #endif
          240  
          241 +        loadhistory();
          242 +
          243          if (fast && !isatty(0)) {
          244                  grabkeyboard();
          245                  readstdin();
          246 diff --git a/dmenu_run b/dmenu_run
          247 index 834ede5..59ec622 100755
          248 --- a/dmenu_run
          249 +++ b/dmenu_run
          250 @@ -1,2 +1,2 @@
          251  #!/bin/sh
          252 -dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &
          253 +dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} &
          254 -- 
          255 2.25.1
          256