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