navhistorysearch-nodoc.patch (5019B)
1 diff --git a/dmenu.c b/dmenu.c 2 index 65f25ce..4242eb4 100644 3 --- a/dmenu.c 4 +++ b/dmenu.c 5 @@ -40,7 +40,7 @@ static int bh, mw, mh; 6 static int inputw = 0, promptw; 7 static int lrpad; /* sum of left and right padding */ 8 static size_t cursor; 9 -static struct item *items = NULL; 10 +static struct item *items = NULL, *backup_items; 11 static struct item *matches, *matchend; 12 static struct item *prev, *curr, *next, *sel; 13 static int mon = -1, screen; 14 @@ -53,6 +53,10 @@ static XIC xic; 15 static Drw *drw; 16 static Clr *scheme[SchemeLast]; 17 18 +static char *histfile; 19 +static char **history; 20 +static size_t histsz, histpos; 21 + 22 #include "config.h" 23 24 static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; 25 @@ -304,11 +308,134 @@ movewordedge(int dir) 26 } 27 } 28 29 +static void 30 +loadhistory(void) 31 +{ 32 + FILE *fp = NULL; 33 + static size_t cap = 0; 34 + size_t llen; 35 + char *line; 36 + 37 + if (!histfile) { 38 + return; 39 + } 40 + 41 + fp = fopen(histfile, "r"); 42 + if (!fp) { 43 + return; 44 + } 45 + 46 + for (;;) { 47 + line = NULL; 48 + llen = 0; 49 + if (-1 == getline(&line, &llen, fp)) { 50 + if (ferror(fp)) { 51 + die("failed to read history"); 52 + } 53 + free(line); 54 + break; 55 + } 56 + 57 + if (cap == histsz) { 58 + cap += 64 * sizeof(char*); 59 + history = realloc(history, cap); 60 + if (!history) { 61 + die("failed to realloc memory"); 62 + } 63 + } 64 + strtok(line, "\n"); 65 + history[histsz] = line; 66 + histsz++; 67 + } 68 + histpos = histsz; 69 + 70 + if (fclose(fp)) { 71 + die("failed to close file %s", histfile); 72 + } 73 +} 74 + 75 +static void 76 +navhistory(int dir) 77 +{ 78 + static char def[BUFSIZ]; 79 + char *p = NULL; 80 + size_t len = 0; 81 + 82 + if (!history || histpos + 1 == 0) 83 + return; 84 + 85 + if (histsz == histpos) { 86 + strncpy(def, text, sizeof(def)); 87 + } 88 + 89 + switch(dir) { 90 + case 1: 91 + if (histpos < histsz - 1) { 92 + p = history[++histpos]; 93 + } else if (histpos == histsz - 1) { 94 + p = def; 95 + histpos++; 96 + } 97 + break; 98 + case -1: 99 + if (histpos > 0) { 100 + p = history[--histpos]; 101 + } 102 + break; 103 + } 104 + if (p == NULL) { 105 + return; 106 + } 107 + 108 + len = MIN(strlen(p), BUFSIZ - 1); 109 + strncpy(text, p, len); 110 + text[len] = '\0'; 111 + cursor = len; 112 + match(); 113 +} 114 + 115 +static void 116 +savehistory(char *input) 117 +{ 118 + unsigned int i; 119 + FILE *fp; 120 + 121 + if (!histfile || 122 + 0 == maxhist || 123 + 0 == strlen(input)) { 124 + goto out; 125 + } 126 + 127 + fp = fopen(histfile, "w"); 128 + if (!fp) { 129 + die("failed to open %s", histfile); 130 + } 131 + for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) { 132 + if (0 >= fprintf(fp, "%s\n", history[i])) { 133 + die("failed to write to %s", histfile); 134 + } 135 + } 136 + if (!histnodup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) { /* TODO */ 137 + if (0 >= fputs(input, fp)) { 138 + die("failed to write to %s", histfile); 139 + } 140 + } 141 + if (fclose(fp)) { 142 + die("failed to close file %s", histfile); 143 + } 144 + 145 +out: 146 + for (i = 0; i < histsz; i++) { 147 + free(history[i]); 148 + } 149 + free(history); 150 +} 151 + 152 static void 153 keypress(XKeyEvent *ev) 154 { 155 char buf[32]; 156 - int len; 157 + int len, i; 158 KeySym ksym = NoSymbol; 159 Status status; 160 161 @@ -359,6 +486,27 @@ keypress(XKeyEvent *ev) 162 XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, 163 utf8, utf8, win, CurrentTime); 164 return; 165 + case XK_r: 166 + if (histfile) { 167 + if (!backup_items) { 168 + backup_items = items; 169 + items = calloc(histsz + 1, sizeof(struct item)); 170 + if (!items) { 171 + die("cannot allocate memory"); 172 + } 173 + 174 + for (i = 0; i < histsz; i++) { 175 + items[i].text = history[i]; 176 + } 177 + } else { 178 + free(items); 179 + items = backup_items; 180 + backup_items = NULL; 181 + } 182 + } 183 + match(); 184 + ksym = NoSymbol; 185 + break; 186 case XK_Left: 187 movewordedge(-1); 188 ksym = NoSymbol; 189 @@ -388,6 +535,14 @@ keypress(XKeyEvent *ev) 190 case XK_j: ksym = XK_Next; break; 191 case XK_k: ksym = XK_Prior; break; 192 case XK_l: ksym = XK_Down; break; 193 + case XK_p: 194 + navhistory(-1); 195 + buf[0]=0; 196 + break; 197 + case XK_n: 198 + navhistory(1); 199 + buf[0]=0; 200 + break; 201 default: 202 return; 203 } 204 @@ -466,6 +621,8 @@ insert: 205 case XK_KP_Enter: 206 puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); 207 if (!(ev->state & ControlMask)) { 208 + savehistory((sel && !(ev->state & ShiftMask)) 209 + ? sel->text : text); 210 cleanup(); 211 exit(0); 212 } 213 @@ -715,6 +873,8 @@ main(int argc, char *argv[]) 214 } else if (i + 1 == argc) 215 usage(); 216 /* these options take one argument */ 217 + else if (!strcmp(argv[i], "-H")) 218 + histfile = argv[++i]; 219 else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ 220 lines = atoi(argv[++i]); 221 else if (!strcmp(argv[i], "-m")) 222 @@ -757,6 +897,8 @@ main(int argc, char *argv[]) 223 die("no fonts could be loaded."); 224 lrpad = drw->fonts->h; 225 226 + loadhistory(); 227 + 228 if (fast) { 229 grabkeyboard(); 230 readstdin(); 231 diff --git a/dmenu_run b/dmenu_run 232 index 834ede5..59ec622 100755 233 --- a/dmenu_run 234 +++ b/dmenu_run 235 @@ -1,2 +1,2 @@ 236 #!/bin/sh 237 -dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & 238 +dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} &