From 04191564946d3ba6c1c49e5041e4bd0cda819043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 18 Mar 2020 15:30:14 +0100 Subject: [PATCH] search: replace hard-coded key bindings with "user configurable" ones They aren't really user configurable. At least not yet. However, with this, we now handle raw key codes just like the normal key bindings. Meaning, e.g. ctrl+g, ctrl+a, ctrl+e etc now works while searching with e.g. a russian layout. --- config.c | 34 ++++++-- config.h | 2 +- input.c | 64 ++++++++------ input.h | 8 +- search.c | 248 +++++++++++++++++++++++++++--------------------------- wayland.c | 4 +- wayland.h | 55 +++++++++--- 7 files changed, 238 insertions(+), 177 deletions(-) diff --git a/config.c b/config.c index 11f4efdb..80163e2e 100644 --- a/config.c +++ b/config.c @@ -455,9 +455,10 @@ parse_section_csd(const char *key, const char *value, struct config *conf, } static bool -verify_key_combo(const struct config *conf, const char *combo, const char *path, unsigned lineno) +verify_key_combo(const struct config *conf, const char *combo, const char *path, + unsigned lineno) { - for (enum binding_action action = 0; action < BIND_ACTION_COUNT; action++) { + for (enum bind_action_normal action = 0; action < BIND_ACTION_COUNT; action++) { if (conf->bindings.key[action] == NULL) continue; @@ -481,8 +482,7 @@ verify_key_combo(const struct config *conf, const char *combo, const char *path, struct xkb_keymap *keymap = xkb_keymap_new_from_names( ctx, &(struct xkb_rule_names){0}, XKB_KEYMAP_COMPILE_NO_FLAGS); - bool valid_combo = input_parse_key_binding_for_action( - keymap, BIND_ACTION_NONE, combo, NULL); + bool valid_combo = input_parse_key_binding(keymap, combo, NULL); xkb_keymap_unref(keymap); xkb_context_unref(ctx); @@ -500,7 +500,7 @@ parse_section_key_bindings( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { - for (enum binding_action action = 0; action < BIND_ACTION_COUNT; action++) { + for (enum bind_action_normal action = 0; action < BIND_ACTION_COUNT; action++) { if (binding_action_map[action] == NULL) continue; @@ -532,7 +532,7 @@ parse_section_mouse_bindings( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { - for (enum binding_action action = 0; action < BIND_ACTION_COUNT; action++) { + for (enum bind_action_normal action = 0; action < BIND_ACTION_COUNT; action++) { if (binding_action_map[action] == NULL) continue; @@ -562,7 +562,7 @@ parse_section_mouse_bindings( const int count = 1; /* Make sure button isn't already mapped to another action */ - for (enum binding_action j = 0; j < BIND_ACTION_COUNT; j++) { + for (enum bind_action_normal j = 0; j < BIND_ACTION_COUNT; j++) { const struct mouse_binding *collision = &conf->bindings.mouse[j]; if (collision->button == i && collision->count == count) { LOG_ERR("%s:%d: %s already mapped to %s", path, lineno, @@ -856,6 +856,22 @@ config_load(struct config *conf, const char *conf_path) [BIND_ACTION_PRIMARY_PASTE] = {BTN_MIDDLE, 1, BIND_ACTION_PRIMARY_PASTE}, }, .search = { + [BIND_ACTION_SEARCH_CANCEL] = strdup("Control+g Escape"), + [BIND_ACTION_SEARCH_COMMIT] = strdup("Return"), + [BIND_ACTION_SEARCH_FIND_PREV] = strdup("Control+r"), + [BIND_ACTION_SEARCH_FIND_NEXT] = strdup("Control+s"), + [BIND_ACTION_SEARCH_EDIT_LEFT] = strdup("Left Control+b"), + [BIND_ACTION_SEARCH_EDIT_LEFT_WORD] = strdup("Control+Left Mod1+b"), + [BIND_ACTION_SEARCH_EDIT_RIGHT] = strdup("Right Control+f"), + [BIND_ACTION_SEARCH_EDIT_RIGHT_WORD] = strdup("Control+Right Mod1+f"), + [BIND_ACTION_SEARCH_EDIT_HOME] = strdup("Home Control+a"), + [BIND_ACTION_SEARCH_EDIT_END] = strdup("End Control+e"), + [BIND_ACTION_SEARCH_DELETE_PREV] = strdup("BackSpace"), + [BIND_ACTION_SEARCH_DELETE_PREV_WORD] = strdup("Mod1+BackSpace Control+BackSpace"), + [BIND_ACTION_SEARCH_DELETE_NEXT] = strdup("Delete "), + [BIND_ACTION_SEARCH_DELETE_NEXT_WORD] = strdup("Mod1+d Control+Delete"), + [BIND_ACTION_SEARCH_EXTEND_WORD] = strdup("Control+w"), + [BIND_ACTION_SEARCH_EXTEND_WORD_WS] = strdup("Control+Shift+W"), }, }, @@ -917,8 +933,8 @@ config_free(struct config conf) tll_free_and_free(conf.fonts, free); free(conf.server_socket_path); - for (size_t i = 0; i < BIND_ACTION_COUNT; i++) { + for (enum bind_action_normal i = 0; i < BIND_ACTION_COUNT; i++) free(conf.bindings.key[i]); + for (enum bind_action_search i = 0; i < BIND_ACTION_SEARCH_COUNT; i++) free(conf.bindings.search[i]); - } } diff --git a/config.h b/config.h index 5d6ec0f0..596aa368 100644 --- a/config.h +++ b/config.h @@ -47,7 +47,7 @@ struct config { /* While searching (not - action to *start* a search is in the * 'key' bindings above */ - char *search[BIND_ACTION_COUNT]; + char *search[BIND_ACTION_SEARCH_COUNT]; } bindings; struct { diff --git a/input.c b/input.c index 492080a1..4fff710f 100644 --- a/input.c +++ b/input.c @@ -33,9 +33,9 @@ #define ALEN(v) (sizeof(v) / sizeof(v[0])) -void -input_execute_binding(struct terminal *term, enum binding_action action, - uint32_t serial) +static void +execute_binding(struct terminal *term, enum bind_action_normal action, + uint32_t serial) { switch (action) { case BIND_ACTION_NONE: @@ -109,14 +109,12 @@ input_execute_binding(struct terminal *term, enum binding_action action, } bool -input_parse_key_binding_for_action( - struct xkb_keymap *keymap, enum binding_action action, - const char *combos, key_binding_list_t *bindings) +input_parse_key_binding(struct xkb_keymap *keymap, const char *combos, + key_binding_list_t *bindings) { if (combos == NULL) return true; - xkb_mod_mask_t mod_mask = 0; xkb_keysym_t sym = XKB_KEY_NoSymbol; char *copy = strdup(combos); @@ -125,6 +123,7 @@ input_parse_key_binding_for_action( combo != NULL; combo = strtok_r(NULL, " ", &save1)) { + xkb_mod_mask_t mod_mask = 0; xkb_keycode_list_t key_codes = tll_init(); LOG_DBG("%s", combo); @@ -177,7 +176,7 @@ input_parse_key_binding_for_action( } } - LOG_DBG("action=%u: mods=0x%08x, sym=%d", action, mod_mask, sym); + LOG_DBG("mods=0x%08x, sym=%d", mod_mask, sym); if (sym == XKB_KEY_NoSymbol) { assert(tll_length(key_codes) == 0); @@ -191,7 +190,6 @@ input_parse_key_binding_for_action( .mods = mod_mask, .sym = sym, .key_codes = key_codes, - .action = action, }; tll_push_back(*bindings, binding); @@ -235,11 +233,11 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, } tll_foreach(wayl->kbd.bindings.key, it) - tll_free(it->item.key_codes); + tll_free(it->item.bind.key_codes); tll_free(wayl->kbd.bindings.key); tll_foreach(wayl->kbd.bindings.search, it) - tll_free(it->item.key_codes); + tll_free(it->item.bind.key_codes); tll_free(wayl->kbd.bindings.search); wayl->kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS); @@ -264,14 +262,32 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, munmap(map_str, size); close(fd); - for (size_t i = 0; i < BIND_ACTION_COUNT; i++) { - input_parse_key_binding_for_action( - wayl->kbd.xkb_keymap, i, - wayl->conf->bindings.key[i], &wayl->kbd.bindings.key); + for (enum bind_action_normal i = 0; i < BIND_ACTION_COUNT; i++) { + key_binding_list_t bindings = tll_init(); + input_parse_key_binding( + wayl->kbd.xkb_keymap, wayl->conf->bindings.key[i], &bindings); - input_parse_key_binding_for_action( - wayl->kbd.xkb_keymap, i, - wayl->conf->bindings.search[i], &wayl->kbd.bindings.search); + tll_foreach(bindings, it) { + tll_push_back( + wayl->kbd.bindings.key, + ((struct key_binding_normal){.bind = it->item, .action = i})); + } + + tll_free(bindings); + } + + for (enum bind_action_search i = 0; i < BIND_ACTION_SEARCH_COUNT; i++) { + key_binding_list_t bindings = tll_init(); + input_parse_key_binding( + wayl->kbd.xkb_keymap, wayl->conf->bindings.search[i], &bindings); + + tll_foreach(bindings, it) { + tll_push_back( + wayl->kbd.bindings.search, + ((struct key_binding_search){.bind = it->item, .action = i})); + } + + tll_free(bindings); } } @@ -558,19 +574,19 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, * User configurable bindings */ tll_foreach(wayl->kbd.bindings.key, it) { - if (it->item.mods != effective_mods) + if (it->item.bind.mods != effective_mods) continue; /* Match symbol */ - if (it->item.sym == sym) { - input_execute_binding(term, it->item.action, serial); + if (it->item.bind.sym == sym) { + execute_binding(term, it->item.action, serial); goto maybe_repeat; } /* Match raw key code */ - tll_foreach(it->item.key_codes, code) { + tll_foreach(it->item.bind.key_codes, code) { if (code->item == key) { - input_execute_binding(term, it->item.action, serial); + execute_binding(term, it->item.action, serial); goto maybe_repeat; } } @@ -1192,7 +1208,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, continue; } - input_execute_binding(term, binding->action, serial); + execute_binding(term, binding->action, serial); break; } selection_cancel(term); diff --git a/input.h b/input.h index 9c274964..553a6249 100644 --- a/input.h +++ b/input.h @@ -10,9 +10,5 @@ extern const struct wl_pointer_listener pointer_listener; void input_repeat(struct wayland *wayl, uint32_t key); -bool input_parse_key_binding_for_action( - struct xkb_keymap *keymap, enum binding_action action, - const char *combos, key_binding_list_t *bindings); - -void input_execute_binding( - struct terminal *term, enum binding_action action, uint32_t serial); +bool input_parse_key_binding(struct xkb_keymap *keymap, const char *combos, + key_binding_list_t *bindings); diff --git a/search.c b/search.c index 1968565a..9304ab48 100644 --- a/search.c +++ b/search.c @@ -412,63 +412,29 @@ distance_prev_word(const struct terminal *term) return term->search.cursor - cursor; } -void -search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, - xkb_mod_mask_t mods, uint32_t serial) +static bool +execute_binding(struct terminal *term, enum bind_action_search action, + uint32_t serial) { - LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x", sym, sym, mods); + switch (action) { + case BIND_ACTION_SEARCH_NONE: + return false; - const xkb_mod_mask_t ctrl = 1 << term->wl->kbd.mod_ctrl; - const xkb_mod_mask_t alt = 1 << term->wl->kbd.mod_alt; - const xkb_mod_mask_t shift = 1 << term->wl->kbd.mod_shift; - //const xkb_mod_mask_t meta = 1 << term->wl->kbd.mod_meta; - - enum xkb_compose_status compose_status = xkb_compose_state_get_status( - term->wl->kbd.xkb_compose_state); - - /* - * User configurable bindings - */ - tll_foreach(term->wl->kbd.bindings.search, it) { - if (it->item.mods != mods) - continue; - - /* Match symbol */ - if (it->item.sym == sym) { - input_execute_binding(term, it->item.action, serial); - return; - } - - /* Match raw key code */ - tll_foreach(it->item.key_codes, code) { - if (code->item == key) { - input_execute_binding(term, it->item.action, serial); - return; - } - } - } - - /* Cancel search */ - if ((mods == 0 && sym == XKB_KEY_Escape) || - (mods == ctrl && sym == XKB_KEY_g)) - { + case BIND_ACTION_SEARCH_CANCEL: if (term->search.view_followed_offset) term->grid->view = term->grid->offset; else term->grid->view = term->search.original_view; term_damage_view(term); search_cancel(term); - return; - } + return true; - /* "Commit" search - copy selection to primary and cancel search */ - else if (mods == 0 && sym == XKB_KEY_Return) { + case BIND_ACTION_SEARCH_COMMIT: selection_finalize(term, term->wl->input_serial); search_cancel_keep_selection(term); - return; - } + return true; - else if (mods == ctrl && sym == XKB_KEY_r) { + case BIND_ACTION_SEARCH_FIND_PREV: if (term->search.match_len > 0) { int new_col = term->search.match.col - 1; int new_row = term->search.match.row; @@ -483,9 +449,9 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, term->search.match.row = new_row; } } - } + return false; - else if (mods == ctrl && sym == XKB_KEY_s) { + case BIND_ACTION_SEARCH_FIND_NEXT: if (term->search.match_len > 0) { int new_col = term->search.match.col + 1; int new_row = term->search.match.row; @@ -501,49 +467,43 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, term->search.direction = SEARCH_FORWARD; } } - } + return false; - else if ((mods == 0 && sym == XKB_KEY_Left) || - (mods == ctrl && sym == XKB_KEY_b)) - { + case BIND_ACTION_SEARCH_EDIT_LEFT: if (term->search.cursor > 0) term->search.cursor--; - } + return false; - else if ((mods == ctrl && sym == XKB_KEY_Left) || - (mods == alt && sym == XKB_KEY_b)) - { + case BIND_ACTION_SEARCH_EDIT_LEFT_WORD: { size_t diff = distance_prev_word(term); term->search.cursor -= diff; assert(term->search.cursor >= 0); assert(term->search.cursor <= term->search.len); + return false; } - else if ((mods == 0 && sym == XKB_KEY_Right) || - (mods == ctrl && sym == XKB_KEY_f)) - { + case BIND_ACTION_SEARCH_EDIT_RIGHT: if (term->search.cursor < term->search.len) term->search.cursor++; - } + return false; - else if ((mods == ctrl && sym == XKB_KEY_Right) || - (mods == alt && sym == XKB_KEY_f)) - { + case BIND_ACTION_SEARCH_EDIT_RIGHT_WORD: { size_t diff = distance_next_word(term); term->search.cursor += diff; assert(term->search.cursor >= 0); assert(term->search.cursor <= term->search.len); + return false; } - else if ((mods == 0 && sym == XKB_KEY_Home) || - (mods == ctrl && sym == XKB_KEY_a)) + case BIND_ACTION_SEARCH_EDIT_HOME: term->search.cursor = 0; + return false; - else if ((mods == 0 && sym == XKB_KEY_End) || - (mods == ctrl && sym == XKB_KEY_e)) + case BIND_ACTION_SEARCH_EDIT_END: term->search.cursor = term->search.len; + return false; - else if (mods == 0 && sym == XKB_KEY_BackSpace) { + case BIND_ACTION_SEARCH_DELETE_PREV: if (term->search.cursor > 0) { memmove( &term->search.buf[term->search.cursor - 1], @@ -552,9 +512,9 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, term->search.cursor--; term->search.buf[--term->search.len] = L'\0'; } - } + return false; - else if ((mods == alt || mods == ctrl) && sym == XKB_KEY_BackSpace) { + case BIND_ACTION_SEARCH_DELETE_PREV_WORD: { size_t diff = distance_prev_word(term); size_t old_cursor = term->search.cursor; size_t new_cursor = old_cursor - diff; @@ -565,10 +525,20 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, term->search.len -= diff; term->search.cursor = new_cursor; + return false; } - else if ((mods == alt && sym == XKB_KEY_d) || - (mods == ctrl && sym == XKB_KEY_Delete)) { + case BIND_ACTION_SEARCH_DELETE_NEXT: + if (term->search.cursor < term->search.len) { + memmove( + &term->search.buf[term->search.cursor], + &term->search.buf[term->search.cursor + 1], + (term->search.len - term->search.cursor - 1) * sizeof(wchar_t)); + term->search.buf[--term->search.len] = L'\0'; + } + return false; + + case BIND_ACTION_SEARCH_DELETE_NEXT_WORD: { size_t diff = distance_next_word(term); size_t cursor = term->search.cursor; @@ -577,66 +547,98 @@ search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, (term->search.len - (cursor + diff)) * sizeof(wchar_t)); term->search.len -= diff; + return false; } - else if (mods == 0 && sym == XKB_KEY_Delete) { - if (term->search.cursor < term->search.len) { - memmove( - &term->search.buf[term->search.cursor], - &term->search.buf[term->search.cursor + 1], - (term->search.len - term->search.cursor - 1) * sizeof(wchar_t)); - term->search.buf[--term->search.len] = L'\0'; - } - } - - else if (mods == ctrl && sym == XKB_KEY_w) + case BIND_ACTION_SEARCH_EXTEND_WORD: search_match_to_end_of_word(term, false); + return false; - else if (mods == (ctrl | shift) && sym == XKB_KEY_W) + case BIND_ACTION_SEARCH_EXTEND_WORD_WS: search_match_to_end_of_word(term, true); + return false; - else { - uint8_t buf[64] = {0}; - int count = 0; - - if (compose_status == XKB_COMPOSE_COMPOSED) { - count = xkb_compose_state_get_utf8( - term->wl->kbd.xkb_compose_state, (char *)buf, sizeof(buf)); - xkb_compose_state_reset(term->wl->kbd.xkb_compose_state); - } else if (compose_status == XKB_COMPOSE_CANCELLED) { - count = 0; - } else { - count = xkb_state_key_get_utf8( - term->wl->kbd.xkb_state, key, (char *)buf, sizeof(buf)); - } - - const char *src = (const char *)buf; - mbstate_t ps = {0}; - size_t wchars = mbsnrtowcs(NULL, &src, count, 0, &ps); - - if (wchars == -1) { - LOG_ERRNO("failed to convert %.*s to wchars", count, buf); - return; - } - - if (!search_ensure_size(term, term->search.len + wchars)) - return; - - assert(term->search.len + wchars < term->search.sz); - - memmove(&term->search.buf[term->search.cursor + wchars], - &term->search.buf[term->search.cursor], - (term->search.len - term->search.cursor) * sizeof(wchar_t)); - - memset(&ps, 0, sizeof(ps)); - mbsnrtowcs(&term->search.buf[term->search.cursor], &src, count, - wchars, &ps); - - term->search.len += wchars; - term->search.cursor += wchars; - term->search.buf[term->search.len] = L'\0'; + case BIND_ACTION_SEARCH_COUNT: + assert(false); + return false; } + assert(false); + return false; +} + +void +search_input(struct terminal *term, uint32_t key, xkb_keysym_t sym, + xkb_mod_mask_t mods, uint32_t serial) +{ + LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x", sym, sym, mods); + + enum xkb_compose_status compose_status = xkb_compose_state_get_status( + term->wl->kbd.xkb_compose_state); + + /* Key bindings */ + tll_foreach(term->wl->kbd.bindings.search, it) { + if (it->item.bind.mods != mods) + continue; + + /* Match symbol */ + if (it->item.bind.sym == sym) { + if (!execute_binding(term, it->item.action, serial)) + goto update_search; + return; + } + + /* Match raw key code */ + tll_foreach(it->item.bind.key_codes, code) { + if (code->item == key) { + if (!execute_binding(term, it->item.action, serial)) + goto update_search; + return; + } + } + } + + uint8_t buf[64] = {0}; + int count = 0; + + if (compose_status == XKB_COMPOSE_COMPOSED) { + count = xkb_compose_state_get_utf8( + term->wl->kbd.xkb_compose_state, (char *)buf, sizeof(buf)); + xkb_compose_state_reset(term->wl->kbd.xkb_compose_state); + } else if (compose_status == XKB_COMPOSE_CANCELLED) { + count = 0; + } else { + count = xkb_state_key_get_utf8( + term->wl->kbd.xkb_state, key, (char *)buf, sizeof(buf)); + } + + const char *src = (const char *)buf; + mbstate_t ps = {0}; + size_t wchars = mbsnrtowcs(NULL, &src, count, 0, &ps); + + if (wchars == -1) { + LOG_ERRNO("failed to convert %.*s to wchars", count, buf); + return; + } + + if (!search_ensure_size(term, term->search.len + wchars)) + return; + + assert(term->search.len + wchars < term->search.sz); + + memmove(&term->search.buf[term->search.cursor + wchars], + &term->search.buf[term->search.cursor], + (term->search.len - term->search.cursor) * sizeof(wchar_t)); + + memset(&ps, 0, sizeof(ps)); + mbsnrtowcs(&term->search.buf[term->search.cursor], &src, count, + wchars, &ps); + + term->search.len += wchars; + term->search.cursor += wchars; + term->search.buf[term->search.len] = L'\0'; + +update_search: LOG_DBG("search: buffer: %S", term->search.buf); search_find_next(term); render_refresh_search(term); diff --git a/wayland.c b/wayland.c index e4907f96..4a553cc6 100644 --- a/wayland.c +++ b/wayland.c @@ -924,11 +924,11 @@ wayl_destroy(struct wayland *wayl) wp_presentation_destroy(wayl->presentation); tll_foreach(wayl->kbd.bindings.key, it) - tll_free(it->item.key_codes); + tll_free(it->item.bind.key_codes); tll_free(wayl->kbd.bindings.key); tll_foreach(wayl->kbd.bindings.search, it) - tll_free(it->item.key_codes); + tll_free(it->item.bind.key_codes); tll_free(wayl->kbd.bindings.search); if (wayl->kbd.xkb_compose_state != NULL) diff --git a/wayland.h b/wayland.h index 6ad46d83..d827708c 100644 --- a/wayland.h +++ b/wayland.h @@ -66,7 +66,17 @@ struct monitor { float inch; /* e.g. 24" */ }; -enum binding_action { + +typedef tll(xkb_keycode_t) xkb_keycode_list_t; + +struct key_binding { + xkb_mod_mask_t mods; + xkb_keysym_t sym; + xkb_keycode_list_t key_codes; +}; +typedef tll(struct key_binding) key_binding_list_t; + +enum bind_action_normal { BIND_ACTION_NONE, BIND_ACTION_SCROLLBACK_UP, BIND_ACTION_SCROLLBACK_DOWN, @@ -84,20 +94,41 @@ enum binding_action { BIND_ACTION_COUNT, }; -typedef tll(xkb_keycode_t) xkb_keycode_list_t; - -struct key_binding { - xkb_mod_mask_t mods; - xkb_keysym_t sym; - xkb_keycode_list_t key_codes; - enum binding_action action; +struct key_binding_normal { + struct key_binding bind; + enum bind_action_normal action; }; -typedef tll(struct key_binding) key_binding_list_t; struct mouse_binding { uint32_t button; int count; - enum binding_action action; + enum bind_action_normal action; +}; + +enum bind_action_search { + BIND_ACTION_SEARCH_NONE, + BIND_ACTION_SEARCH_CANCEL, + BIND_ACTION_SEARCH_COMMIT, + BIND_ACTION_SEARCH_FIND_PREV, + BIND_ACTION_SEARCH_FIND_NEXT, + BIND_ACTION_SEARCH_EDIT_LEFT, + BIND_ACTION_SEARCH_EDIT_LEFT_WORD, + BIND_ACTION_SEARCH_EDIT_RIGHT, + BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, + BIND_ACTION_SEARCH_EDIT_HOME, + BIND_ACTION_SEARCH_EDIT_END, + BIND_ACTION_SEARCH_DELETE_PREV, + BIND_ACTION_SEARCH_DELETE_PREV_WORD, + BIND_ACTION_SEARCH_DELETE_NEXT, + BIND_ACTION_SEARCH_DELETE_NEXT_WORD, + BIND_ACTION_SEARCH_EXTEND_WORD, + BIND_ACTION_SEARCH_EXTEND_WORD_WS, + BIND_ACTION_SEARCH_COUNT, +}; + +struct key_binding_search { + struct key_binding bind; + enum bind_action_search action; }; struct kbd { @@ -127,8 +158,8 @@ struct kbd { bool meta; struct { - key_binding_list_t key; - key_binding_list_t search; + tll(struct key_binding_normal) key; + tll(struct key_binding_search) search; } bindings; };