Introduction
Introduction Statistics Contact Development Disclaimer Help
[dmenu][patches][navhistory] Updated patch - sites - public wiki contents of su…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
commit ad2184d57ae98c48d365081e6326c31a855cf896
parent cf6279c687765a4571cdf166e7bb9f91fc5af44e
Author: elbachir-one <[email protected]>
Date: Sat, 29 Mar 2025 17:50:04 +0000
[dmenu][patches][navhistory] Updated patch
* Fixed duplicate names in history
Diffstat:
A tools.suckless.org/dmenu/patches/n… | 290 +++++++++++++++++++++++++++…
M tools.suckless.org/dmenu/patches/n… | 3 ++-
2 files changed, 292 insertions(+), 1 deletion(-)
---
diff --git a/tools.suckless.org/dmenu/patches/navhistory/dmenu-navhistory+searc…
@@ -0,0 +1,290 @@
+From 52fc8a05d6a20b861ff7e9f9f215ff6acefda683 Mon Sep 17 00:00:00 2001
+From: elbachir-one <[email protected]>
+Date: Fri, 28 Mar 2025 21:55:52 +0000
+Subject: [PATCH] Fixed duplicate names in history
+
+---
+ config.def.h | 1 +
+ dmenu.1 | 5 ++
+ dmenu.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ dmenu_run | 2 +-
+ 4 files changed, 165 insertions(+), 4 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1edb647..6adc0f3 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -15,6 +15,7 @@ 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;
+
+ /*
+ * Characters not considered part of a word while deleting words
+diff --git a/dmenu.1 b/dmenu.1
+index 323f93c..ff496dd 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
+@@ -80,6 +82,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 fd49549..aba7af6 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -39,7 +39,7 @@ static int bh, mw, mh;
+ static int inputw = 0, promptw;
+ static int lrpad; /* sum of left and right padding */
+ static size_t cursor;
+-static struct item *items = NULL;
++static struct item *items = NULL, *backup_items;
+ static struct item *matches, *matchend;
+ static struct item *prev, *curr, *next, *sel;
+ static int mon = -1, screen;
+@@ -52,6 +52,10 @@ static XIC xic;
+ static Drw *drw;
+ static Clr *scheme[SchemeLast];
+
++static char *histfile;
++static char **history;
++static size_t histsz, histpos;
++
+ #include "config.h"
+
+ static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
+@@ -320,11 +324,127 @@ 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 || maxhist == 0 || strlen(input) == 0)
++ return;
++
++ for (i = 0; i < histsz; i++) {
++ if (strcmp(input, history[i]) == 0)
++ return;
++ }
++
++ fp = fopen(histfile, "w");
++ if (!fp) {
++ die("failed to open %s", histfile);
++ }
++
++ for (i = (histsz < maxhist) ? 0 : (histsz - maxhist); i < histsz; i++…
++ if (fprintf(fp, "%s\n", history[i]) <= 0)
++ die("failed to write to %s", histfile);
++ }
++
++ if (fprintf(fp, "%s\n", input) <= 0)
++ die("failed to write to %s", histfile);
++
++ if (fclose(fp))
++ die("failed to close file %s", histfile);
++}
++
+ static void
+ keypress(XKeyEvent *ev)
+ {
+ char buf[64];
+- int len;
++ int len, i;
+ KeySym ksym = NoSymbol;
+ Status status;
+
+@@ -375,6 +495,26 @@ keypress(XKeyEvent *ev)
+ XConvertSelection(dpy, (ev->state & ShiftMask) ? clip…
+ utf8, utf8, win, CurrentTime);
+ return;
++ case XK_r:
++ if (histfile) {
++ if (!backup_items) {
++ backup_items = items;
++ items = calloc(histsz + 1, sizeof(str…
++ if (!items) {
++ die("cannot allocate memory");
++ }
++
++ for (i = 0; i < histsz; i++) {
++ items[i].text = history[i];
++ }
++ } else {
++ free(items);
++ items = backup_items;
++ backup_items = NULL;
++ }
++ }
++ match();
++ goto draw;
+ case XK_Left:
+ case XK_KP_Left:
+ movewordedge(-1);
+@@ -406,6 +546,14 @@ 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;
+ }
+@@ -491,6 +639,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);
+ }
+@@ -715,7 +865,8 @@ static void
+ usage(void)
+ {
+ die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monit…
+- " [-nb color] [-nf color] [-sb color] [-sf color] [-w…
++ " [-nb color] [-nf color] [-sb color] [-sf color]…
++ " [-H histfile]\n");
+ }
+
+ int
+@@ -739,6 +890,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 vert…
+ lines = atoi(argv[++i]);
+ else if (!strcmp(argv[i], "-m"))
+@@ -781,6 +934,8 @@ main(int argc, char *argv[])
+ die("pledge");
+ #endif
+
++ loadhistory();
++
+ if (fast && !isatty(0)) {
+ grabkeyboard();
+ readstdin();
+diff --git a/dmenu_run b/dmenu_run
+index 834ede5..03607d2 100755
+--- a/dmenu_run
++++ b/dmenu_run
+@@ -1,2 +1,2 @@
+ #!/bin/sh
+-dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &
++(cat "${XDG_CACHE_HOME:-$HOME/.cache}/dmenu_run.hist"; dmenu_path) | dmenu -H…
+--
+2.48.1
+
diff --git a/tools.suckless.org/dmenu/patches/navhistory/index.md b/tools.suckl…
@@ -23,9 +23,10 @@ ctrl-r, like in bash or ksh, and the suggestions will be rep…
the history. Press ctrl-r again to revert.
* [dmenu-navhistory+search-20200709.diff](dmenu-navhistory+search-20200709.dif…
-
+* [dmenu-navhistory+search-20250328-52fc8a0.diff](dmenu-navhistory+search-2025…
Author
------
* phi <[email protected]>
* Philip K. - philipk (at) posteo (dot) net
+* [El Bachir](https://github.com/elbachir-one) (2025-03-28)
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.