commit 27e32cdbaa3141f85d845df2288897dec8e7584f
parent ca33dd0080acf6eb8987e88ffd47b10028d3a550
Author: phi <crispyfrog@163.com>
Date: Mon, 4 Apr 2016 18:58:46 +0800
Add a new patch navhistory for dmenu
Diffstat:
2 files changed, 192 insertions(+), 0 deletions(-)
diff --git a/tools.suckless.org/dmenu/patches/dmenu-4.6-navhistory.diff b/tools.suckless.org/dmenu/patches/dmenu-4.6-navhistory.diff
@@ -0,0 +1,173 @@
+diff -urp dmenu-4.6/config.def.h dmenu-4.6-patched/config.def.h
+--- dmenu-4.6/config.def.h 2015-11-09 06:42:21.000000000 +0800
++++ dmenu-4.6-patched/config.def.h 2016-04-03 10:59:02.413544865 +0800
+@@ -15,3 +15,5 @@ static const char *outbgcolor = "#00fff
+ static const char *outfgcolor = "#000000";
+ /* -l option; if nonzero, dmenu uses vertical list with given number of lines */
+ static unsigned int lines = 0;
++static unsigned int maxhist = 15;
++static int histnodup = 1; /* if 0, record repeated histories */
+diff -urp dmenu-4.6/dmenu.c dmenu-4.6-patched/dmenu.c
+--- dmenu-4.6/dmenu.c 2015-11-09 06:42:21.000000000 +0800
++++ dmenu-4.6-patched/dmenu.c 2016-04-03 10:54:51.798552270 +0800
+@@ -52,6 +52,10 @@ static XIC xic;
+ static ClrScheme scheme[SchemeLast];
+ static Drw *drw;
+
++static char *histfile;
++static char *histbuf, *histptr;
++static size_t histsz;
++
+ #include "config.h"
+
+ static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
+@@ -278,6 +282,105 @@ nextrune(int inc)
+ }
+
+ static void
++loadhistory(void)
++{
++ FILE *fp = NULL;
++ size_t sz;
++
++ if (!histfile)
++ return;
++ if (!(fp = fopen(histfile, "r")))
++ return;
++ fseek(fp, 0, SEEK_END);
++ sz = ftell(fp);
++ fseek(fp, 0, SEEK_SET);
++ if (sz) {
++ histsz = sz + 1 + BUFSIZ;
++ if (!(histbuf = malloc(histsz))) {
++ fprintf(stderr, "warning: cannot malloc %lu "\
++ "bytes", histsz);
++ } else {
++ histptr = histbuf + fread(histbuf, 1, sz, fp);
++ if (histptr <= histbuf) { /* fread error */
++ free(histbuf);
++ histbuf = NULL;
++ return;
++ }
++ if (histptr[-1] != '\n')
++ *histptr++ = '\n';
++ histptr[BUFSIZ - 1] = '\0';
++ *histptr = '\0';
++ histsz = histptr - histbuf + BUFSIZ;
++ }
++ }
++ fclose(fp);
++}
++
++static void
++navhistory(int dir)
++{
++ char *p;
++ size_t len = 0, textlen;
++
++ if (!histbuf)
++ return;
++ if (dir > 0) {
++ if (histptr == histbuf + histsz - BUFSIZ)
++ return;
++ while (*histptr && *histptr++ != '\n');
++ for (p = histptr; *p && *p++ != '\n'; len++);
++ } else {
++ if (histptr == histbuf)
++ return;
++ if (histptr == histbuf + histsz - BUFSIZ) {
++ textlen = strlen(text);
++ textlen = MIN(textlen, BUFSIZ - 1);
++ strncpy(histptr, text, textlen);
++ histptr[textlen] = '\0';
++ }
++ for (histptr--; histptr != histbuf && histptr[-1] != '\n';
++ histptr--, len++);
++ }
++ len = MIN(len, BUFSIZ - 1);
++ strncpy(text, histptr, len);
++ text[len] = '\0';
++ cursor = len;
++ match();
++}
++static void
++savehistory(char *str)
++{
++ unsigned int n, len = 0;
++ size_t slen;
++ char *p;
++ FILE *fp;
++
++ if (!histfile || !maxhist)
++ return;
++ if (!(slen = strlen(str)))
++ return;
++ if (histbuf && maxhist > 1) {
++ p = histbuf + histsz - BUFSIZ - 1; /* skip the last newline */
++ if (histnodup) {
++ for (; p != histbuf && p[-1] != '\n'; p--, len++);
++ n++;
++ if (slen == len && !strncmp(p, str, len)) {
++ return;
++ }
++ }
++ for (; p != histbuf; p--, len++)
++ if (p[-1] == '\n' && ++n + 1 > maxhist)
++ break;
++ fp = fopen(histfile, "w");
++ fwrite(p, 1, len + 1, fp); /* plus the last newline */
++ } else {
++ fp = fopen(histfile, "w");
++ }
++ fwrite(str, 1, strlen(str), fp);
++ fclose(fp);
++}
++
++static void
+ keypress(XKeyEvent *ev)
+ {
+ char buf[32];
+@@ -341,6 +444,8 @@ keypress(XKeyEvent *ev)
+ case XK_j: ksym = XK_Next; break;
+ case XK_k: ksym = XK_Prior; break;
+ case XK_l: ksym = XK_Down; break;
++ case XK_p: navhistory(-1); buf[0]=0; break;
++ case XK_n: navhistory(1); buf[0]=0; break;
+ default:
+ return;
+ }
+@@ -416,6 +521,8 @@ keypress(XKeyEvent *ev)
+ case XK_KP_Enter:
+ puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
+ if (!(ev->state & ControlMask)) {
++ savehistory((sel && !(ev->state & ShiftMask))
++ ? sel->text : text);
+ cleanup();
+ exit(0);
+ }
+@@ -608,7 +715,7 @@ setup(void)
+ static void
+ usage(void)
+ {
+- fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
++ fputs("usage: dmenu [-b] [-f] [-H histfile] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
+ " [-nb color] [-nf color] [-sb color] [-sf color] [-v]\n", stderr);
+ exit(1);
+ }
+@@ -633,6 +740,8 @@ main(int argc, char *argv[])
+ } else if (i + 1 == argc)
+ usage();
+ /* these options take one argument */
++ else if (!strcmp(argv[i], "-H"))
++ histfile = argv[++i];
+ else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */
+ lines = atoi(argv[++i]);
+ else if (!strcmp(argv[i], "-m"))
+@@ -665,6 +774,7 @@ main(int argc, char *argv[])
+ if (!drw->fontcount)
+ die("no fonts could be loaded.\n");
+ drw_setscheme(drw, &scheme[SchemeNorm]);
++ loadhistory();
+
+ if (fast) {
+ grabkeyboard();
diff --git a/tools.suckless.org/dmenu/patches/navhistory.md b/tools.suckless.org/dmenu/patches/navhistory.md
@@ -0,0 +1,19 @@
+# navhistory
+
+## Description
+
+This patch provides dmenu the ability for history navigation similar to that
+of bash. Press alt+p for the previous history and alt+n for the next.
+
+## Configuration
+
+Set the maximum number of histories with a new variable 'maxhist' in config.h.
+By default, it only records a new history if it is not the same as the last one.
+To change this behaviour, set 'histnodup' to 0 in config.h.
+
+## Download
+
+* [dmenu-4.6-navhistory.diff](dmenu-4.6-navhistory.diff) (4677b) (20160404)
+
+## Author
+* phi <crispyforg@163.com>