diff options
author | Amin Bandali <bandali@kelar.org> | 2024-02-27 00:49:58 -0500 |
---|---|---|
committer | adnano <me@adnano.co> | 2024-02-27 07:54:20 -0500 |
commit | c37c3fe38e77398fba65d169c664f569fbab9760 (patch) | |
tree | 6fecdd75c3320e7321970ad6c3f355e12ffe56dc | |
parent | 04dfc063795c56a5fdb3096bf8fe0b4123c3c28d (diff) | |
download | wmenu-c37c3fe38e77398fba65d169c664f569fbab9760.tar.gz |
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.
-rw-r--r-- | docs/wmenu.1.scd | 24 | ||||
-rw-r--r-- | main.c | 80 |
2 files changed, 86 insertions, 18 deletions
diff --git a/docs/wmenu.1.scd b/docs/wmenu.1.scd index 5fbf50e..56d3865 100644 --- a/docs/wmenu.1.scd +++ b/docs/wmenu.1.scd @@ -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 + @@ -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); |