Return to repo list

suckless-gf-dmenu

Gentoo-friendly patches for Suckless's dmenu.
Return to HMagellan.com

navhistory.patch (4835B)


      1 diff --git a/dmenu.1 b/dmenu.1
      2 index 323f93c..ff496dd 100644
      3 --- a/dmenu.1
      4 +++ b/dmenu.1
      5 @@ -22,6 +22,8 @@ dmenu \- dynamic menu
      6  .IR color ]
      7  .RB [ \-w
      8  .IR windowid ]
      9 +.RB [ \-H
     10 +.IR histfile ]
     11  .P
     12  .BR dmenu_run " ..."
     13  .SH DESCRIPTION
     14 @@ -80,6 +82,9 @@ prints version information to stdout, then exits.
     15  .TP
     16  .BI \-w " windowid"
     17  embed into windowid.
     18 +.TP
     19 +.BI \-H " histfile"
     20 +save input in histfile and use it for history navigation.
     21  .SH USAGE
     22  dmenu is completely controlled by the keyboard.  Items are selected using the
     23  arrow keys, page up, page down, home, and end.
     24 diff --git a/dmenu.c b/dmenu.c
     25 index 65f25ce..9d15f78 100644
     26 --- a/dmenu.c
     27 +++ b/dmenu.c
     28 @@ -53,6 +53,10 @@ static XIC xic;
     29  static Drw *drw;
     30  static Clr *scheme[SchemeLast];
     31 
     32 +static char *histfile;
     33 +static char **history;
     34 +static size_t histsz, histpos;
     35 +
     36  #include "config.h"
     37 
     38  static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
     39 @@ -304,6 +308,129 @@ movewordedge(int dir)
     40  	}
     41  }
     42 
     43 +static void
     44 +loadhistory(void)
     45 +{
     46 +	FILE *fp = NULL;
     47 +	static size_t cap = 0;
     48 +	size_t llen;
     49 +	char *line;
     50 +
     51 +	if (!histfile) {
     52 +		return;
     53 +	}
     54 +
     55 +	fp = fopen(histfile, "r");
     56 +	if (!fp) {
     57 +		return;
     58 +	}
     59 +
     60 +	for (;;) {
     61 +		line = NULL;
     62 +		llen = 0;
     63 +		if (-1 == getline(&line, &llen, fp)) {
     64 +			if (ferror(fp)) {
     65 +				die("failed to read history");
     66 +			}
     67 +			free(line);
     68 +			break;
     69 +		}
     70 +
     71 +		if (cap == histsz) {
     72 +			cap += 64 * sizeof(char*);
     73 +			history = realloc(history, cap);
     74 +			if (!history) {
     75 +				die("failed to realloc memory");
     76 +			}
     77 +		}
     78 +		strtok(line, "\n");
     79 +		history[histsz] = line;
     80 +		histsz++;
     81 +	}
     82 +	histpos = histsz;
     83 +
     84 +	if (fclose(fp)) {
     85 +		die("failed to close file %s", histfile);
     86 +	}
     87 +}
     88 +
     89 +static void
     90 +navhistory(int dir)
     91 +{
     92 +	static char def[BUFSIZ];
     93 +	char *p = NULL;
     94 +	size_t len = 0;
     95 +
     96 +	if (!history || histpos + 1 == 0)
     97 +		return;
     98 +
     99 +	if (histsz == histpos) {
    100 +		strncpy(def, text, sizeof(def));
    101 +	}
    102 +
    103 +	switch(dir) {
    104 +	case 1:
    105 +		if (histpos < histsz - 1) {
    106 +			p = history[++histpos];
    107 +		} else if (histpos == histsz - 1) {
    108 +			p = def;
    109 +			histpos++;
    110 +		}
    111 +		break;
    112 +	case -1:
    113 +		if (histpos > 0) {
    114 +			p = history[--histpos];
    115 +		}
    116 +		break;
    117 +	}
    118 +	if (p == NULL) {
    119 +		return;
    120 +	}
    121 +
    122 +	len = MIN(strlen(p), BUFSIZ - 1);
    123 +	strncpy(text, p, len);
    124 +	text[len] = '\0';
    125 +	cursor = len;
    126 +	match();
    127 +}
    128 +
    129 +static void
    130 +savehistory(char *input)
    131 +{
    132 +	unsigned int i;
    133 +	FILE *fp;
    134 +
    135 +	if (!histfile ||
    136 +	    0 == maxhist ||
    137 +	    0 == strlen(input)) {
    138 +		goto out;
    139 +	}
    140 +
    141 +	fp = fopen(histfile, "w");
    142 +	if (!fp) {
    143 +		die("failed to open %s", histfile);
    144 +	}
    145 +	for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
    146 +		if (0 >= fprintf(fp, "%s\n", history[i])) {
    147 +			die("failed to write to %s", histfile);
    148 +		}
    149 +	}
    150 +	if (!histnodup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) { /* TODO */
    151 +		if (0 >= fputs(input, fp)) {
    152 +			die("failed to write to %s", histfile);
    153 +		}
    154 +	}
    155 +	if (fclose(fp)) {
    156 +		die("failed to close file %s", histfile);
    157 +	}
    158 +
    159 +out:
    160 +	for (i = 0; i < histsz; i++) {
    161 +		free(history[i]);
    162 +	}
    163 +	free(history);
    164 +}
    165 +
    166  static void
    167  keypress(XKeyEvent *ev)
    168  {
    169 @@ -388,6 +515,14 @@ keypress(XKeyEvent *ev)
    170  		case XK_j: ksym = XK_Next;  break;
    171  		case XK_k: ksym = XK_Prior; break;
    172  		case XK_l: ksym = XK_Down;  break;
    173 +		case XK_p:
    174 +			navhistory(-1);
    175 +			buf[0]=0;
    176 +			break;
    177 +		case XK_n:
    178 +			navhistory(1);
    179 +			buf[0]=0;
    180 +			break;
    181  		default:
    182  			return;
    183  		}
    184 @@ -466,6 +601,8 @@ insert:
    185  	case XK_KP_Enter:
    186  		puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
    187  		if (!(ev->state & ControlMask)) {
    188 +			savehistory((sel && !(ev->state & ShiftMask))
    189 +				    ? sel->text : text);
    190  			cleanup();
    191  			exit(0);
    192  		}
    193 @@ -690,7 +827,8 @@ static void
    194  usage(void)
    195  {
    196  	fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
    197 -	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
    198 +	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n"
    199 +	      "             [-H histfile]", stderr);
    200  	exit(1);
    201  }
    202 
    203 @@ -715,6 +853,8 @@ main(int argc, char *argv[])
    204  		} else if (i + 1 == argc)
    205  			usage();
    206  		/* these options take one argument */
    207 +		else if (!strcmp(argv[i], "-H"))
    208 +			histfile = argv[++i];
    209  		else if (!strcmp(argv[i], "-l"))   /* number of lines in vertical list */
    210  			lines = atoi(argv[++i]);
    211  		else if (!strcmp(argv[i], "-m"))
    212 @@ -757,6 +897,8 @@ main(int argc, char *argv[])
    213         die("no fonts could be loaded.");
    214     lrpad = drw->fonts->h;
    215 
    216 +	loadhistory();
    217 +
    218  	if (fast) {
    219  		grabkeyboard();
    220  		readstdin();
    221 diff --git a/dmenu_run b/dmenu_run
    222 index 834ede5..59ec622 100755
    223 --- a/dmenu_run
    224 +++ b/dmenu_run
    225 @@ -1,2 +1,2 @@
    226  #!/bin/sh
    227 -dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &
    228 +dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} &