Add dmenu's Meta (Alt) keybindings

This change adds dmenu's mixture of Emacs+vim-style Meta keybindings.

Also 'Page_Up' and 'Page_Down' were deprecated in upstream xkbcommon,
so replace them with the new 'Prior' and 'Next' names respectively.
This commit is contained in:
Amin Bandali 2024-02-27 00:49:58 -05:00 committed by adnano
parent 04dfc06379
commit c37c3fe38e
2 changed files with 86 additions and 18 deletions

View file

@ -148,3 +148,27 @@ arrow keys, page up, page down, home, and end.
|[ *C-w*
:[ Delete word left
|[ *M-b*
:[ Move cursor to the start of the current word.
|[ *M-f*
:[ Move cursor to the end of the current word.
|[ *M-g*
:[ Home
|[ *M-G*
:[ End
|[ *M-h*
:[ Up
|[ *M-j*
:[ Page down
|[ *M-k*
:[ Page up
|[ *M-l*
:[ Down

80
main.c
View file

@ -291,6 +291,27 @@ static size_t nextrune(struct menu *menu, int incr) {
return n;
}
static void movewordedge(struct menu *menu, int dir) {
if (dir < 0) {
// Move to beginning of word
while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] == ' ') {
menu->cursor = nextrune(menu, -1);
}
while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] != ' ') {
menu->cursor = nextrune(menu, -1);
}
} else {
// Move to end of word
size_t len = strlen(menu->input);
while (menu->cursor < len && menu->input[menu->cursor] == ' ') {
menu->cursor = nextrune(menu, +1);
}
while (menu->cursor < len && menu->input[menu->cursor] != ' ') {
menu->cursor = nextrune(menu, +1);
}
}
}
// Calculate text widths.
static void calc_widths(struct menu *menu) {
cairo_t *cairo = menu->current->cairo;
@ -573,6 +594,9 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
bool ctrl = xkb_state_mod_name_is_active(menu->xkb_state,
XKB_MOD_NAME_CTRL,
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
bool meta = xkb_state_mod_name_is_active(menu->xkb_state,
XKB_MOD_NAME_ALT,
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
bool shift = xkb_state_mod_name_is_active(menu->xkb_state,
XKB_MOD_NAME_SHIFT,
XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
@ -682,24 +706,12 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
return;
case XKB_KEY_Left:
case XKB_KEY_KP_Left:
// Move to beginning of word
while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] == ' ') {
menu->cursor = nextrune(menu, -1);
}
while (menu->cursor > 0 && menu->input[nextrune(menu, -1)] != ' ') {
menu->cursor = nextrune(menu, -1);
}
movewordedge(menu, -1);
render_frame(menu);
return;
case XKB_KEY_Right:
case XKB_KEY_KP_Right:
// Move to end of word
while (menu->cursor < len && menu->input[menu->cursor] == ' ') {
menu->cursor = nextrune(menu, +1);
}
while (menu->cursor < len && menu->input[menu->cursor] != ' ') {
menu->cursor = nextrune(menu, +1);
}
movewordedge(menu, +1);
render_frame(menu);
return;
@ -709,6 +721,38 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
default:
return;
}
} else if (meta) {
// Emacs-style line editing bindings
switch (sym) {
case XKB_KEY_b:
movewordedge(menu, -1);
render_frame(menu);
return;
case XKB_KEY_f:
movewordedge(menu, +1);
render_frame(menu);
return;
case XKB_KEY_g:
sym = XKB_KEY_Home;
break;
case XKB_KEY_G:
sym = XKB_KEY_End;
break;
case XKB_KEY_h:
sym = XKB_KEY_Up;
break;
case XKB_KEY_j:
sym = XKB_KEY_Next;
break;
case XKB_KEY_k:
sym = XKB_KEY_Prior;
break;
case XKB_KEY_l:
sym = XKB_KEY_Down;
break;
default:
return;
}
}
char buf[8];
@ -752,15 +796,15 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
render_frame(menu);
}
break;
case XKB_KEY_Page_Up:
case XKB_KEY_KP_Page_Up:
case XKB_KEY_Prior:
case XKB_KEY_KP_Prior:
if (menu->sel && menu->sel->page->prev) {
menu->sel = menu->sel->page->prev->first;
render_frame(menu);
}
break;
case XKB_KEY_Page_Down:
case XKB_KEY_KP_Page_Down:
case XKB_KEY_Next:
case XKB_KEY_KP_Next:
if (menu->sel && menu->sel->page->next) {
menu->sel = menu->sel->page->next->first;
render_frame(menu);