@ -0,0 +1,246 @@ | |||
.TH DMENU 1 dmenu\-VERSION | |||
.SH NAME | |||
dmenu \- dynamic menu | |||
.SH SYNOPSIS | |||
.B dmenu | |||
.RB [ \-bfivP ] | |||
.RB [ \-l | |||
.IR lines ] | |||
.RB [ \-h | |||
.IR height ] | |||
.RB [ \-m | |||
.IR monitor ] | |||
.RB [ \-x | |||
.IR xoffset ] | |||
.RB [ \-y | |||
.IR yoffset ] | |||
.RB [ \-z | |||
.IR width ] | |||
.RB [ \-p | |||
.IR prompt ] | |||
.RB [ \-fn | |||
.IR font ] | |||
.RB [ \-nb | |||
.IR color ] | |||
.RB [ \-nf | |||
.IR color ] | |||
.RB [ \-sb | |||
.IR color ] | |||
.RB [ \-sf | |||
.IR color ] | |||
.RB [ \-nhb | |||
.IR color ] | |||
.RB [ \-nhf | |||
.IR color ] | |||
.RB [ \-shb | |||
.IR color ] | |||
.RB [ \-shf | |||
.IR color ] | |||
.RB [ \-w | |||
.IR windowid ] | |||
.P | |||
.BR dmenu_run " ..." | |||
.SH DESCRIPTION | |||
.B dmenu | |||
is a dynamic menu for X, which reads a list of newline\-separated items from | |||
stdin. When the user selects an item and presses Return, their choice is printed | |||
to stdout and dmenu terminates. Entering text will narrow the items to those | |||
matching the tokens in the input. | |||
.P | |||
.B dmenu_run | |||
is a script used by | |||
.IR dwm (1) | |||
which lists programs in the user's $PATH and runs the result in their $SHELL. | |||
.SH OPTIONS | |||
.TP | |||
.B \-b | |||
dmenu appears at the bottom of the screen. | |||
.TP | |||
.B \-f | |||
dmenu grabs the keyboard before reading stdin if not reading from a tty. This | |||
is faster, but will lock up X until stdin reaches end\-of\-file. | |||
.TP | |||
.B \-i | |||
dmenu matches menu items case insensitively. | |||
.TP | |||
.B \-P | |||
dmenu will not directly display the keyboard input, but instead replace it with dots. All data from stdin will be ignored. | |||
.TP | |||
.BI \-l " lines" | |||
dmenu lists items vertically, with the given number of lines. | |||
.TP | |||
.BI \-h " height" | |||
dmenu uses a menu line of at least 'height' pixels tall, but no less than 8. | |||
.TP | |||
.BI \-m " monitor" | |||
dmenu is displayed on the monitor number supplied. Monitor numbers are starting | |||
from 0. | |||
.TP | |||
.BI \-x " xoffset" | |||
dmenu is placed at this offset measured from the left side of the monitor. | |||
Can be negative. | |||
If option | |||
.B \-m | |||
is present, the measurement will use the given monitor. | |||
.TP | |||
.BI \-y " yoffset" | |||
dmenu is placed at this offset measured from the top of the monitor. If the | |||
.B \-b | |||
option is used, the offset is measured from the bottom. Can be negative. | |||
If option | |||
.B \-m | |||
is present, the measurement will use the given monitor. | |||
.TP | |||
.BI \-z " width" | |||
sets the width of the dmenu window. | |||
.TP | |||
.BI \-p " prompt" | |||
defines the prompt to be displayed to the left of the input field. | |||
.TP | |||
.BI \-fn " font" | |||
defines the font or font set used. | |||
.TP | |||
.BI \-nb " color" | |||
defines the normal background color. | |||
.IR #RGB , | |||
.IR #RRGGBB , | |||
and X color names are supported. | |||
.TP | |||
.BI \-nf " color" | |||
defines the normal foreground color. | |||
.TP | |||
.BI \-sb " color" | |||
defines the selected background color. | |||
.TP | |||
.BI \-sf " color" | |||
defines the selected foreground color. | |||
.TP | |||
.BI \-nhb " color" | |||
defines the normal highlight background color. | |||
.TP | |||
.BI \-nhf " color" | |||
defines the normal highlight foreground color. | |||
.TP | |||
.BI \-shb " color" | |||
defines the selected highlight background color. | |||
.TP | |||
.BI \-shf " color" | |||
defines the selected highlight foreground color. | |||
.TP | |||
.B \-v | |||
prints version information to stdout, then exits. | |||
.TP | |||
.BI \-w " windowid" | |||
embed into windowid. | |||
.SH USAGE | |||
dmenu is completely controlled by the keyboard. Items are selected using the | |||
arrow keys, page up, page down, home, and end. | |||
.TP | |||
.B Tab | |||
Copy the selected item to the input field. | |||
.TP | |||
.B Return | |||
Confirm selection. Prints the selected item to stdout and exits, returning | |||
success. | |||
.TP | |||
.B Ctrl-Return | |||
Confirm selection. Prints the selected item to stdout and continues. | |||
.TP | |||
.B Shift\-Return | |||
Confirm input. Prints the input text to stdout and exits, returning success. | |||
.TP | |||
.B Escape | |||
Exit without selecting an item, returning failure. | |||
.TP | |||
.B Ctrl-Left | |||
Move cursor to the start of the current word | |||
.TP | |||
.B Ctrl-Right | |||
Move cursor to the end of the current word | |||
.TP | |||
.B C\-a | |||
Home | |||
.TP | |||
.B C\-b | |||
Left | |||
.TP | |||
.B C\-c | |||
Escape | |||
.TP | |||
.B C\-d | |||
Delete | |||
.TP | |||
.B C\-e | |||
End | |||
.TP | |||
.B C\-f | |||
Right | |||
.TP | |||
.B C\-g | |||
Escape | |||
.TP | |||
.B C\-h | |||
Backspace | |||
.TP | |||
.B C\-i | |||
Tab | |||
.TP | |||
.B C\-j | |||
Return | |||
.TP | |||
.B C\-J | |||
Shift-Return | |||
.TP | |||
.B C\-k | |||
Delete line right | |||
.TP | |||
.B C\-m | |||
Return | |||
.TP | |||
.B C\-M | |||
Shift-Return | |||
.TP | |||
.B C\-n | |||
Down | |||
.TP | |||
.B C\-p | |||
Up | |||
.TP | |||
.B C\-u | |||
Delete line left | |||
.TP | |||
.B C\-w | |||
Delete word left | |||
.TP | |||
.B C\-y | |||
Paste from primary X selection | |||
.TP | |||
.B C\-Y | |||
Paste from X clipboard | |||
.TP | |||
.B M\-b | |||
Move cursor to the start of the current word | |||
.TP | |||
.B M\-f | |||
Move cursor to the end of the current word | |||
.TP | |||
.B M\-g | |||
Home | |||
.TP | |||
.B M\-G | |||
End | |||
.TP | |||
.B M\-h | |||
Up | |||
.TP | |||
.B M\-j | |||
Page down | |||
.TP | |||
.B M\-k | |||
Page up | |||
.TP | |||
.B M\-l | |||
Down | |||
.SH SEE ALSO | |||
.IR dwm (1), | |||
.IR stest (1) |
@ -0,0 +1,24 @@ | |||
--- dmenu.c | |||
+++ dmenu.c | |||
@@ -637,7 +637,8 @@ static void | |||
usage(void) | |||
{ | |||
fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" | |||
- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); | |||
+ " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n" | |||
+ " [-it text]\n", stderr); | |||
exit(1); | |||
} | |||
@@ -680,7 +681,10 @@ main(int argc, char *argv[]) | |||
colors[SchemeSel][ColFg] = argv[++i]; | |||
else if (!strcmp(argv[i], "-w")) /* embedding window id */ | |||
embed = argv[++i]; | |||
- else | |||
+ else if (!strcmp(argv[i], "-it")) { /* embedding window id */ | |||
+ const char * text = argv[++i]; | |||
+ insert(text, strlen(text)); | |||
+ } else | |||
usage(); | |||
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) |
@ -0,0 +1,49 @@ | |||
diff --git a/dmenu.1 b/dmenu.1 | |||
index 9eab758..b4947f9 100644 | |||
--- a/dmenu.1 | |||
+++ b/dmenu.1 | |||
@@ -22,6 +22,8 @@ dmenu \- dynamic menu | |||
.IR color ] | |||
.RB [ \-w | |||
.IR windowid ] | |||
+.RB [ \-it | |||
+.IR text ] | |||
.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 \-it " text". | |||
+start with initial text input. | |||
.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 d605ab4..0564dfe 100644 | |||
--- a/dmenu.c | |||
+++ b/dmenu.c | |||
@@ -637,7 +637,8 @@ static void | |||
usage(void) | |||
{ | |||
fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" | |||
- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); | |||
+ " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n" | |||
+ " [-it text]\n", stderr); | |||
exit(1); | |||
} | |||
@@ -680,7 +681,10 @@ main(int argc, char *argv[]) | |||
colors[SchemeSel][ColFg] = argv[++i]; | |||
else if (!strcmp(argv[i], "-w")) /* embedding window id */ | |||
embed = argv[++i]; | |||
- else | |||
+ else if (!strcmp(argv[i], "-it")) { /* embedding window id */ | |||
+ const char * text = argv[++i]; | |||
+ insert(text, strlen(text)); | |||
+ } else | |||
usage(); | |||
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) |
@ -0,0 +1,108 @@ | |||
diff --git a/dmenu.c b/dmenu.c | |||
index 6b8f51b..6544112 100644 | |||
--- a/dmenu.c | |||
+++ b/dmenu.c | |||
@@ -31,7 +31,8 @@ enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ | |||
struct item { | |||
char *text; | |||
struct item *left, *right; | |||
- int out; | |||
+ | |||
+ int id; /* for multiselect */ | |||
}; | |||
static char text[BUFSIZ] = ""; | |||
@@ -45,6 +46,9 @@ static struct item *matches, *matchend; | |||
static struct item *prev, *curr, *next, *sel; | |||
static int mon = -1, screen; | |||
+static int *selid = NULL; | |||
+static unsigned int selidsize = 0; | |||
+ | |||
static Atom clip, utf8; | |||
static Display *dpy; | |||
static Window root, parentwin, win; | |||
@@ -58,6 +62,15 @@ static Clr *scheme[SchemeLast]; | |||
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; | |||
static char *(*fstrstr)(const char *, const char *) = strstr; | |||
+static int | |||
+issel(size_t id) | |||
+{ | |||
+ for (int i = 0;i < selidsize;i++) | |||
+ if (selid[i] == id) | |||
+ return 1; | |||
+ return 0; | |||
+} | |||
+ | |||
static void | |||
appenditem(struct item *item, struct item **list, struct item **last) | |||
{ | |||
@@ -100,6 +113,7 @@ cleanup(void) | |||
drw_free(drw); | |||
XSync(dpy, False); | |||
XCloseDisplay(dpy); | |||
+ free(selid); | |||
} | |||
static char * | |||
@@ -118,7 +132,7 @@ drawitem(struct item *item, int x, int y, int w) | |||
{ | |||
if (item == sel) | |||
drw_setscheme(drw, scheme[SchemeSel]); | |||
- else if (item->out) | |||
+ else if (issel(item->id)) | |||
drw_setscheme(drw, scheme[SchemeOut]); | |||
else | |||
drw_setscheme(drw, scheme[SchemeNorm]); | |||
@@ -367,6 +381,20 @@ keypress(XKeyEvent *ev) | |||
goto draw; | |||
case XK_Return: | |||
case XK_KP_Enter: | |||
+ if (sel && issel(sel->id)) { | |||
+ for (int i = 0;i < selidsize;i++) | |||
+ if (selid[i] == sel->id) | |||
+ selid[i] = -1; | |||
+ } else { | |||
+ for (int i = 0;i < selidsize;i++) | |||
+ if (selid[i] == -1) { | |||
+ selid[i] = sel->id; | |||
+ return; | |||
+ } | |||
+ selidsize++; | |||
+ selid = realloc(selid, (selidsize + 1) * sizeof(int)); | |||
+ selid[selidsize - 1] = sel->id; | |||
+ } | |||
break; | |||
case XK_bracketleft: | |||
cleanup(); | |||
@@ -464,13 +492,17 @@ insert: | |||
break; | |||
case XK_Return: | |||
case XK_KP_Enter: | |||
- puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); | |||
if (!(ev->state & ControlMask)) { | |||
+ for (int i = 0;i < selidsize;i++) | |||
+ if (selid[i] != -1 && (!sel || sel->id != selid[i])) | |||
+ puts(items[selid[i]].text); | |||
+ if (sel && !(ev->state & ShiftMask)) | |||
+ puts(sel->text); | |||
+ else | |||
+ puts(text); | |||
cleanup(); | |||
exit(0); | |||
} | |||
- if (sel) | |||
- sel->out = 1; | |||
break; | |||
case XK_Right: | |||
if (text[cursor] != '\0') { | |||
@@ -534,7 +566,7 @@ readstdin(void) | |||
*p = '\0'; | |||
if (!(items[i].text = strdup(buf))) | |||
die("cannot strdup %u bytes:", strlen(buf) + 1); | |||
- items[i].out = 0; | |||
+ items[i].id = i; /* for multiselect */ | |||
drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); | |||
if (tmpmax > inputw) { | |||
inputw = tmpmax; |
@ -0,0 +1,3 @@ | |||
let g:netrw_dirhistmax =10 | |||
let g:netrw_dirhistcnt =1 | |||
let g:netrw_dirhist_1='/mnt/remote/home' |