From 608e5b5306c1ca188960fd1d2a247776d9c2d08e Mon Sep 17 00:00:00 2001 From: justsaumit Date: Wed, 2 Mar 2022 12:51:31 +0530 Subject: navhistory patch --- config.h | 2 + dmenu | Bin 43736 -> 44160 bytes dmenu.1 | 5 ++ dmenu.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- dmenu.o | Bin 41056 -> 44704 bytes dmenu_run | 2 +- 6 files changed, 162 insertions(+), 4 deletions(-) diff --git a/config.h b/config.h index 4962f01..eedb917 100644 --- a/config.h +++ b/config.h @@ -17,6 +17,8 @@ static const char *colors[SchemeLast][2] = { }; /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ static unsigned int lines = 0; +static unsigned int maxhist = 64; +static int histnodup = 1; /* if 0, record repeated histories */ /* * Characters not considered part of a word while deleting words diff --git a/dmenu b/dmenu index 8dbe25b..da6be5e 100755 Binary files a/dmenu and b/dmenu differ diff --git a/dmenu.1 b/dmenu.1 index aac82c0..a54abdf 100644 --- a/dmenu.1 +++ b/dmenu.1 @@ -22,6 +22,8 @@ dmenu \- dynamic menu .IR color ] .RB [ \-w .IR windowid ] +.RB [ \-H +.IR histfile ] .P .BR dmenu_run " ..." .SH DESCRIPTION @@ -86,6 +88,9 @@ prints version information to stdout, then exits. .TP .BI \-w " windowid" embed into windowid. +.TP +.BI \-H " histfile" +save input in histfile and use it for history navigation. .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 f2542a4..61f6af6 100644 --- a/dmenu.c +++ b/dmenu.c @@ -60,6 +60,10 @@ static Clr *scheme[SchemeLast]; static char *colortemp[4]; static char *tempfonts; +static char *histfile; +static char **history; +static size_t histsz, histpos; + #include "config.h" static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; @@ -373,6 +377,129 @@ movewordedge(int dir) } } +static void +loadhistory(void) +{ + FILE *fp = NULL; + static size_t cap = 0; + size_t llen; + char *line; + + if (!histfile) { + return; + } + + fp = fopen(histfile, "r"); + if (!fp) { + return; + } + + for (;;) { + line = NULL; + llen = 0; + if (-1 == getline(&line, &llen, fp)) { + if (ferror(fp)) { + die("failed to read history"); + } + free(line); + break; + } + + if (cap == histsz) { + cap += 64 * sizeof(char*); + history = realloc(history, cap); + if (!history) { + die("failed to realloc memory"); + } + } + strtok(line, "\n"); + history[histsz] = line; + histsz++; + } + histpos = histsz; + + if (fclose(fp)) { + die("failed to close file %s", histfile); + } +} + +static void +navhistory(int dir) +{ + static char def[BUFSIZ]; + char *p = NULL; + size_t len = 0; + + if (!history || histpos + 1 == 0) + return; + + if (histsz == histpos) { + strncpy(def, text, sizeof(def)); + } + + switch(dir) { + case 1: + if (histpos < histsz - 1) { + p = history[++histpos]; + } else if (histpos == histsz - 1) { + p = def; + histpos++; + } + break; + case -1: + if (histpos > 0) { + p = history[--histpos]; + } + break; + } + if (p == NULL) { + return; + } + + len = MIN(strlen(p), BUFSIZ - 1); + strncpy(text, p, len); + text[len] = '\0'; + cursor = len; + match(); +} + +static void +savehistory(char *input) +{ + unsigned int i; + FILE *fp; + + if (!histfile || + 0 == maxhist || + 0 == strlen(input)) { + goto out; + } + + fp = fopen(histfile, "w"); + if (!fp) { + die("failed to open %s", histfile); + } + for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) { + if (0 >= fprintf(fp, "%s\n", history[i])) { + die("failed to write to %s", histfile); + } + } + if (histsz == 0 || !histnodup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) { /* TODO */ + if (0 >= fputs(input, fp)) { + die("failed to write to %s", histfile); + } + } + if (fclose(fp)) { + die("failed to close file %s", histfile); + } + +out: + for (i = 0; i < histsz; i++) { + free(history[i]); + } + free(history); +} + static void keypress(XKeyEvent *ev) { @@ -456,9 +583,26 @@ keypress(XKeyEvent *ev) case XK_g: ksym = XK_Home; break; case XK_G: ksym = XK_End; break; case XK_h: ksym = XK_Up; break; - case XK_j: ksym = XK_Next; break; - case XK_k: ksym = XK_Prior; break; + //case XK_j: ksym = XK_Next; break; + //case XK_k: ksym = XK_Prior; break; case XK_l: ksym = XK_Down; break; + + case XK_j: + navhistory(-1); + buf[0]=0; + break; + case XK_k: + navhistory(1); + buf[0]=0; + break; + case XK_p: + navhistory(-1); + buf[0]=0; + break; + case XK_n: + navhistory(1); + buf[0]=0; + break; default: return; } @@ -544,6 +688,8 @@ insert: 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); } @@ -899,7 +1045,8 @@ usage(void) { fputs("usage: dmenu [-bfinvP] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n" - " [-hb color] [-hf color] [-hp items]\n", stderr); + " [-hb color] [-hf color] [-hp items]\n" + " [-H histfile]", stderr); exit(1); } @@ -965,6 +1112,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")) @@ -1028,6 +1177,8 @@ main(int argc, char *argv[]) die("pledge"); #endif + loadhistory(); + if (fast && !isatty(0)) { grabkeyboard(); readstdin(); diff --git a/dmenu.o b/dmenu.o index e75ed6b..3533401 100644 Binary files a/dmenu.o and b/dmenu.o differ diff --git a/dmenu_run b/dmenu_run index 834ede5..59ec622 100755 --- a/dmenu_run +++ b/dmenu_run @@ -1,2 +1,2 @@ #!/bin/sh -dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & +dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} & -- cgit v1.2.3