From 24281f7120e11ec318aabcba38e73dff57328ff1 Mon Sep 17 00:00:00 2001 From: Out Of Ideas Date: Mon, 13 Nov 2023 16:16:51 -0600 Subject: [PATCH] Switch completion movement keys --- Patches/dmenu-caseinsensitive-5.0.diff | 53 +++++++ dmenu | Bin 42640 -> 42656 bytes dmenu.1 | 6 +- dmenu.1.orig | 194 ++++++++++++++++++++++ dmenu.c | 15 +- dmenu.c.orig | 212 ++++++++++++++++++++++++- dmenu.c.rej | 13 ++ dmenu.o | Bin 38104 -> 38128 bytes 8 files changed, 481 insertions(+), 12 deletions(-) create mode 100644 Patches/dmenu-caseinsensitive-5.0.diff create mode 100644 dmenu.1.orig create mode 100644 dmenu.c.rej diff --git a/Patches/dmenu-caseinsensitive-5.0.diff b/Patches/dmenu-caseinsensitive-5.0.diff new file mode 100644 index 0000000..f476bc9 --- /dev/null +++ b/Patches/dmenu-caseinsensitive-5.0.diff @@ -0,0 +1,53 @@ +diff --git a/dmenu.1 b/dmenu.1 +index 323f93c..3e3b31b 100644 +--- a/dmenu.1 ++++ b/dmenu.1 +@@ -3,7 +3,7 @@ + dmenu \- dynamic menu + .SH SYNOPSIS + .B dmenu +-.RB [ \-bfiv ] ++.RB [ \-bfsv ] + .RB [ \-l + .IR lines ] + .RB [ \-m +@@ -44,8 +44,8 @@ dmenu appears at the bottom of the screen. + 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. ++.B \-s ++dmenu matches menu items case sensitively. + .TP + .BI \-l " lines" + dmenu lists items vertically, with the given number of lines. +diff --git a/dmenu.c b/dmenu.c +index 65f25ce..855df59 100644 +--- a/dmenu.c ++++ b/dmenu.c +@@ -55,8 +55,9 @@ static Clr *scheme[SchemeLast]; + + #include "config.h" + +-static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; +-static char *(*fstrstr)(const char *, const char *) = strstr; ++static char * cistrstr(const char *s, const char *sub); ++static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp; ++static char *(*fstrstr)(const char *, const char *) = cistrstr; + + static void + appenditem(struct item *item, struct item **list, struct item **last) +@@ -709,9 +710,9 @@ main(int argc, char *argv[]) + topbar = 0; + else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ + fast = 1; +- else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ +- fstrncmp = strncasecmp; +- fstrstr = cistrstr; ++ else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */ ++ fstrncmp = strncmp; ++ fstrstr = strstr; + } else if (i + 1 == argc) + usage(); + /* these options take one argument */ diff --git a/dmenu b/dmenu index 174aa6b62a14922dad420ad07622a56c8f895326..6b078e27f17119319ae677c6cdfedabaf2dccc19 100755 GIT binary patch delta 9726 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 delta 9751 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 diff --git a/dmenu.1 b/dmenu.1 index 323f93c..3e3b31b 100644 --- a/dmenu.1 +++ b/dmenu.1 @@ -3,7 +3,7 @@ dmenu \- dynamic menu .SH SYNOPSIS .B dmenu -.RB [ \-bfiv ] +.RB [ \-bfsv ] .RB [ \-l .IR lines ] .RB [ \-m @@ -44,8 +44,8 @@ dmenu appears at the bottom of the screen. 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. +.B \-s +dmenu matches menu items case sensitively. .TP .BI \-l " lines" dmenu lists items vertically, with the given number of lines. diff --git a/dmenu.1.orig b/dmenu.1.orig new file mode 100644 index 0000000..323f93c --- /dev/null +++ b/dmenu.1.orig @@ -0,0 +1,194 @@ +.TH DMENU 1 dmenu\-VERSION +.SH NAME +dmenu \- dynamic menu +.SH SYNOPSIS +.B dmenu +.RB [ \-bfiv ] +.RB [ \-l +.IR lines ] +.RB [ \-m +.IR monitor ] +.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 [ \-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 +.BI \-l " lines" +dmenu lists items vertically, with the given number of lines. +.TP +.BI \-m " monitor" +dmenu is displayed on the monitor number supplied. Monitor numbers are starting +from 0. +.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 +.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) diff --git a/dmenu.c b/dmenu.c index 29dceb3..7a5a5f4 100644 --- a/dmenu.c +++ b/dmenu.c @@ -60,8 +60,9 @@ static Clr *scheme[SchemeLast]; #include "config.h" -static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; -static char *(*fstrstr)(const char *, const char *) = strstr; +static char * cistrstr(const char *s, const char *sub); +static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp; +static char *(*fstrstr)(const char *, const char *) = cistrstr; static unsigned int textw_clamp(const char *str, unsigned int n) @@ -413,13 +414,13 @@ vi_keypress(KeySym ksym, const XKeyEvent *ev) if (cursor) cursor = nextrune(-1); break; - case XK_t: + case XK_h: if (sel && sel->right && (sel = sel->right) == next) { curr = next; calcoffsets(); } break; - case XK_h: + case XK_t: if (sel && sel->left && (sel = sel->left)->right == curr) { curr = prev; calcoffsets(); @@ -937,9 +938,9 @@ main(int argc, char *argv[]) topbar = 0; else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ fast = 1; - else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ - fstrncmp = strncasecmp; - fstrstr = cistrstr; + else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */ + fstrncmp = strncmp; + fstrstr = strstr; } else if (!strcmp(argv[i], "-vi")) { vi_mode = 1; using_vi_mode = start_mode; diff --git a/dmenu.c.orig b/dmenu.c.orig index 40f93e0..29dceb3 100644 --- a/dmenu.c.orig +++ b/dmenu.c.orig @@ -25,7 +25,7 @@ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) /* enums */ -enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ +enum { SchemeNorm, SchemeSel, SchemeOut, SchemeCursor, SchemeLast }; /* color schemes */ struct item { char *text; @@ -33,6 +33,11 @@ struct item { int out; }; +typedef struct { + KeySym ksym; + unsigned int state; +} Key; + static char text[BUFSIZ] = ""; static char *embed; static int bh, mw, mh; @@ -43,6 +48,7 @@ static struct item *items = NULL; static struct item *matches, *matchend; static struct item *prev, *curr, *next, *sel; static int mon = -1, screen; +static unsigned int using_vi_mode = 0; static Atom clip, utf8; static Display *dpy; @@ -162,8 +168,16 @@ drawmenu(void) drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); curpos = TEXTW(text) - TEXTW(&text[cursor]); - if ((curpos += lrpad / 2 - 1) < w) { + curpos += lrpad / 2 - 1; + if (using_vi_mode && text[0] != '\0') { + drw_setscheme(drw, scheme[SchemeCursor]); + char vi_char[] = {text[cursor], '\0'}; + drw_text(drw, x + curpos, 0, TEXTW(vi_char) - lrpad, bh, 0, vi_char, 0); + } else if (using_vi_mode) { drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x + curpos, 2, lrpad / 2, bh - 4, 1, 0); + } else if (curpos < w) { + drw_setscheme(drw, scheme[SchemeSel]); drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); } @@ -320,6 +334,181 @@ movewordedge(int dir) } } +static void +vi_keypress(KeySym ksym, const XKeyEvent *ev) +{ + static const size_t quit_len = LENGTH(quit_keys); + if (ev->state & ControlMask) { + switch(ksym) { + /* movement */ + case XK_d: /* fallthrough */ + if (next) { + sel = curr = next; + calcoffsets(); + goto draw; + } else + ksym = XK_G; + break; + case XK_u: + if (prev) { + sel = curr = prev; + calcoffsets(); + goto draw; + } else + ksym = XK_g; + break; + case XK_p: /* fallthrough */ + case XK_P: break; + case XK_c: + cleanup(); + exit(1); + case XK_Return: /* fallthrough */ + case XK_KP_Enter: break; + default: return; + } + } + + switch(ksym) { + /* movement */ + case XK_0: + cursor = 0; + break; + case XK_dollar: + if (text[cursor + 1] != '\0') { + cursor = strlen(text) - 1; + break; + } + break; + case XK_b: + movewordedge(-1); + break; + case XK_e: + cursor = nextrune(+1); + movewordedge(+1); + if (text[cursor] == '\0') + --cursor; + else + cursor = nextrune(-1); + break; + case XK_g: + if (sel == matches) { + break; + } + sel = curr = matches; + calcoffsets(); + break; + case XK_G: + if (next) { + /* jump to end of list and position items in reverse */ + curr = matchend; + calcoffsets(); + curr = prev; + calcoffsets(); + while (next && (curr = curr->right)) + calcoffsets(); + } + sel = matchend; + break; + case XK_d: + if (cursor) + cursor = nextrune(-1); + break; + case XK_t: + if (sel && sel->right && (sel = sel->right) == next) { + curr = next; + calcoffsets(); + } + break; + case XK_h: + if (sel && sel->left && (sel = sel->left)->right == curr) { + curr = prev; + calcoffsets(); + } + break; + case XK_n: + if (text[cursor] != '\0' && text[cursor + 1] != '\0') + cursor = nextrune(+1); + else if (text[cursor] == '\0' && cursor) + --cursor; + break; + case XK_w: + movewordedge(+1); + if (text[cursor] != '\0' && text[cursor + 1] != '\0') + cursor = nextrune(+1); + else if (cursor) + --cursor; + break; + /* insertion */ + case XK_a: + cursor = nextrune(+1); + /* fallthrough */ + case XK_i: + using_vi_mode = 0; + break; + case XK_A: + if (text[cursor] != '\0') + cursor = strlen(text); + using_vi_mode = 0; + break; + case XK_I: + cursor = using_vi_mode = 0; + break; + case XK_p: + if (text[cursor] != '\0') + cursor = nextrune(+1); + XConvertSelection(dpy, (ev->state & ControlMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + return; + case XK_P: + XConvertSelection(dpy, (ev->state & ControlMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + return; + /* deletion */ + case XK_K: + text[cursor] = '\0'; + if (cursor) + cursor = nextrune(-1); + match(); + break; + case XK_x: + cursor = nextrune(+1); + insert(NULL, nextrune(-1) - cursor); + if (text[cursor] == '\0' && text[0] != '\0') + --cursor; + match(); + break; + /* misc. */ + case XK_Return: + case XK_KP_Enter: + puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); + if (!(ev->state & ControlMask)) { + cleanup(); + exit(0); + } + if (sel) + sel->out = 1; + break; + case XK_Tab: + if (!sel) + return; + strncpy(text, sel->text, sizeof text - 1); + text[sizeof text - 1] = '\0'; + cursor = strlen(text) - 1; + match(); + break; + default: + for (size_t i = 0; i < quit_len; ++i) + if (quit_keys[i].ksym == ksym && + (quit_keys[i].state & ev->state) == quit_keys[i].state) { + cleanup(); + exit(1); + } + } + +draw: + drawmenu(); +} + static void keypress(XKeyEvent *ev) { @@ -339,6 +528,18 @@ keypress(XKeyEvent *ev) break; } + if (using_vi_mode) { + vi_keypress(ksym, ev); + return; + } else if (vi_mode && + (ksym == global_esc.ksym && + (ev->state & global_esc.state) == global_esc.state)) { + using_vi_mode = 1; + if (cursor) + cursor = nextrune(-1); + goto draw; + } + if (ev->state & ControlMask) { switch(ksym) { case XK_a: ksym = XK_Home; break; @@ -542,6 +743,8 @@ paste(void) insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); XFree(p); } + if (using_vi_mode && text[cursor] == '\0') + --cursor; drawmenu(); } @@ -737,6 +940,11 @@ main(int argc, char *argv[]) else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ fstrncmp = strncasecmp; fstrstr = cistrstr; + } else if (!strcmp(argv[i], "-vi")) { + vi_mode = 1; + using_vi_mode = start_mode; + global_esc.ksym = XK_Escape; + global_esc.state = 0; } else if (i + 1 == argc) usage(); /* these options take one argument */ diff --git a/dmenu.c.rej b/dmenu.c.rej new file mode 100644 index 0000000..57c42c8 --- /dev/null +++ b/dmenu.c.rej @@ -0,0 +1,13 @@ +@@ -714,9 +715,9 @@ + topbar = 0; + else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ + fast = 1; +- else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ +- fstrncmp = strncasecmp; +- fstrstr = cistrstr; ++ else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */ ++ fstrncmp = strncmp; ++ fstrstr = strstr; + } else if (i + 1 == argc) + usage(); + /* these options take one argument */ diff --git a/dmenu.o b/dmenu.o index 18e3db39fb3593498d5c3feab3bfe081daa7c14c..36bb1bd91d27e85b8ad8eab0d5afa792bb64c3d5 100644 GIT binary patch delta 2306 zcmZ`)Yiv|i5Wcf*5y&pkLb+V*BgU<~giA?K!B(lTUP^aq>5FQ>t{uuM`)ae#DQV*N|rmvbnwWe#{&bS1-q9{&;GG|a7k{8TKNa6WO z3}wD-W-YjGF{dpY8#n!IDuYZl6d68XAIWoB;kC{8KOOcqZn&r!S$rg%)P{#3C zfsn&X6H)oTPLt5XJQ0J;lQ7DBGBOOEqm(dDMho+)xWZh;9mAkX%w4WCU%PyO(vX^~ z!kKHe^;;t0xd3GYT)C>PilxU-BlHsz*=~QX6&Km|7s+-Lg1I`qf|1++ZASG9FAn5c z@nD6WGLW3-rD}BK8QK;p){k+Kl|+yk2<5qH7F$Gv8`!j2D(yl`ksE7@xi>`~+Ksiv2Kmv)ydI&jys$*)l`2cz@RVBdYl$6M zrPhO`S@bEgOLZ|pW2pzPujUYpevY}T&%s${#qHG|+6z~is_o)#SE`wrl6DPiqoI`YC@x}lOI};hU8(w;B(If{wpsG}M8c0q_Hu6h5)R4!MiduY zF5j7v2tGU9;zN?d!xuPALgEHhOHX4{CQ(cef3e2BCbYQ=qFT|Q0!f=CdCA2rjpENI zw+7AYRaz%v^2NBkUe%gj5TRMvWFD2YaxLFU_z@|eAB2~GII0!diVYJr3Hs*+_yFcGGE;Y;m)EWlMm*f@AABmP1>;ELYa({22Ar zxS5aE1Q>7GCZ4CEZ8~e8uzU)R?E)X(Zs2j96*Frevp%EFiQ}=MxUL&#&MrY z7jVU=Kl6C)nG;SUoW}(`@#%CCb9bxM3CC`of~em;pat0^*5in^qKJR#OK|zsF`|O0 z>EFkH+Fin?_f0xosca#-jE- zEbE$L_O?$WD#PUi15}P}9lui-20Q1Vrn8s;M_>*fu+$5Ozyig5dIkf2K0S^uKb^#2 qmmk-=r=YCc!`&L}e#-R^9`tin4&38NnTOsT_ib||wQ<;S$o)S(izbNx delta 2322 zcmZ`*YfMyE5Z+nXg7mJ{in%NmPy@b*y~VcnwbW|V%gV0EQ%t3c6)Nb0>jSSZTrm|< z#AW@^Vufn0)<;2YZraoz1lyEY6G@sF8=FX~Nl8eRXwqP60&V9kcjJwTL(a^cZysl6 z?%}|r^VZwvt<5v2_}iIQif*#mCg}<#M@>jev{(lG4vXb}+(0FZf%rtdG&&{Dde^4c zjSWRx8?Ac$gp4?prySL@lM=0=oUwY;WY<`#)IG26h_X$xSS)T#ne&P*l{FuFGp17u zhBBt>&N)9@$M=!NV&$L5!jGw0fAYplQHgVtN4I`93rdO}b*oR(r@mburC)t-Hz8|b zg6_|ZjgA?Pu~?>9$6?-rnK4(x`pXE+S1BIX=5Np|7ThI#kolTky0DcnZm|y?izPHH zPQ@LTKd_Wk2?H#hEECjJ_*iDKY-72VgBdSPS z)=gW`zsyTDSd^=hhNj$yIGD?`&2wUB9@n3j>ez0o=>^d|lW6u`*z;BR@+JFJ6Y4}& zzU;_kdt@?B!z!k^1MT@6H<|c(jxxmyl*b@(H@KxsTgK-+445}6obn(JXkK-J0w1cNt{=Y+G3gZ=|_s+ zB5FYI3Ylv3{uL=i`*quge-Ir&|H_AKxmBW3gYNn05>X>Yyb43JOI3zyO0_6Dh{4r7 z%+);1vI4lv_|lb04i6s?Y4T6w_KQOgps$RtOqsOmiGhl71x?6hh@Pbt0o&UiG8NXC?a>M_V2lxTx%~DfV9z4ig?{{Njola!mMmj9(+W zrkkwhO5QQyEvBdn0~ejHG2vCn{X}-uJ;!w; z6Du`3j;2a+`@1T=%#+r7sSUMjRpvcmZePc`UbrrY9LG33lJ57Z;cVds+R^1x`2n(3 zsq_UrRWbqPthb|+^%Lk}{Uq$wUP#saJXaU+uD3c!r%+!RA>&fKgq^xbB!aHd})HKH)Qxnr>JZ<6xdNr9&qhIS5Ikt*2Y}?M#SLodKka_!d&2ickdwu59 z*fW^DLo{-0hu3k+