mirror of
https://github.com/mintycube/dmenu.git
synced 2024-10-22 12:05:48 +00:00
[dmenu][patch][navhistory] Bug fix: Write first entry to history file
- Bug fix: Don't skip writing first entry to history file. This happened for `histnodup` = 1 (default) plus `histsz` = 0 (value when starting with an empty history). Ref. https://git.suckless.org/sites/commit/f759877d393eaed126dfc8e56932c49e7581a181.html
This commit is contained in:
parent
21641d4f3f
commit
3cb4dbdf7a
10
dmenu.c
10
dmenu.c
@ -1027,8 +1027,14 @@ keypress(XKeyEvent *ev)
|
|||||||
case XK_k: ksym = XK_Prior; break;
|
case XK_k: ksym = XK_Prior; break;
|
||||||
case XK_l: ksym = XK_Down; break;
|
case XK_l: ksym = XK_Down; break;
|
||||||
#if NAVHISTORY_PATCH
|
#if NAVHISTORY_PATCH
|
||||||
case XK_p: navhistory(-1); buf[0]=0; break;
|
case XK_p:
|
||||||
case XK_n: navhistory(1); buf[0]=0; break;
|
navhistory(-1);
|
||||||
|
buf[0]=0;
|
||||||
|
break;
|
||||||
|
case XK_n:
|
||||||
|
navhistory(1);
|
||||||
|
buf[0]=0;
|
||||||
|
break;
|
||||||
#endif // NAVHISTORY_PATCH
|
#endif // NAVHISTORY_PATCH
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
export _JAVA_AWT_WM_NONREPARENTING=1
|
export _JAVA_AWT_WM_NONREPARENTING=1
|
||||||
exec $(dmenu_path | dmenu "$@")
|
exec $(dmenu_path | dmenu "$@")
|
||||||
|
|
||||||
|
# Uncomment for the NAVHISTORY patch (and remove the exec above)
|
||||||
|
#dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} &
|
@ -1,103 +1,126 @@
|
|||||||
static char *histfile;
|
static char *histfile;
|
||||||
static char *histbuf, *histptr;
|
static char **history;
|
||||||
static size_t histsz;
|
static size_t histsz, histpos;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
loadhistory(void)
|
loadhistory(void)
|
||||||
{
|
{
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
size_t sz;
|
static size_t cap = 0;
|
||||||
|
size_t llen;
|
||||||
|
char *line;
|
||||||
|
|
||||||
if (!histfile)
|
if (!histfile) {
|
||||||
return;
|
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);
|
|
||||||
|
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
|
static void
|
||||||
navhistory(int dir)
|
navhistory(int dir)
|
||||||
{
|
{
|
||||||
char *p;
|
static char def[BUFSIZ];
|
||||||
size_t len = 0, textlen;
|
char *p = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
if (!histbuf)
|
if (!history || histpos + 1 == 0)
|
||||||
return;
|
return;
|
||||||
if (dir > 0) {
|
|
||||||
if (histptr == histbuf + histsz - BUFSIZ)
|
if (histsz == histpos) {
|
||||||
return;
|
strncpy(def, text, sizeof(def));
|
||||||
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);
|
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';
|
text[len] = '\0';
|
||||||
cursor = len;
|
cursor = len;
|
||||||
match();
|
match();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
savehistory(char *str)
|
savehistory(char *input)
|
||||||
{
|
{
|
||||||
unsigned int n = 0, len = 0;
|
unsigned int i;
|
||||||
size_t slen;
|
|
||||||
char *p;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (!histfile || !maxhist)
|
if (!histfile ||
|
||||||
return;
|
0 == maxhist ||
|
||||||
if (!(slen = strlen(str)))
|
0 == strlen(input)) {
|
||||||
return;
|
goto out;
|
||||||
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);
|
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);
|
||||||
}
|
}
|
@ -158,6 +158,10 @@
|
|||||||
#define MULTI_SELECTION_PATCH 0
|
#define MULTI_SELECTION_PATCH 0
|
||||||
|
|
||||||
/* This patch provides dmenu the ability for history navigation similar to that of bash.
|
/* This patch provides dmenu the ability for history navigation similar to that of bash.
|
||||||
|
*
|
||||||
|
* If you take this patch then it is recommended that you also uncomment the line in the
|
||||||
|
* dmenu_run script which replaces the exec command.
|
||||||
|
*
|
||||||
* https://tools.suckless.org/dmenu/patches/navhistory/
|
* https://tools.suckless.org/dmenu/patches/navhistory/
|
||||||
*/
|
*/
|
||||||
#define NAVHISTORY_PATCH 0
|
#define NAVHISTORY_PATCH 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user