Skip to content

Commit

Permalink
Add -U flag to def-mode, to allow disabling fallback text insertion
Browse files Browse the repository at this point in the history
Sometimes it may be useful to use an existing mode as a fallback, as a
succinct way to inherit lots of bindings. However the mode in question
may also have text insertion for the Unicode range enabled, which the
"parent" mode may want to disable regardless of what the fallback does.
Using the `-U` flag is like recursively applying `-u` to all fallback
modes, but only in that context (i.e. still working as usual if `-U`
isn't used higher up the chain of inheritance).

Example use case:

    def-mode -U pager normal
    bind -T pager up scroll-up
    bind -T pager down scroll-down
    bind -T pager delete ''
    bind -T pager backspace ''
    bind -T pager C-e 'mode normal'
    mode pager

This pattern allows defining a mode that overrides just a few bindings
from the fallback ("normal") while inheriting most others and overriding
the fallback's text insertion flags (force disabling it).
  • Loading branch information
craigbarnes committed Jan 22, 2025
1 parent 9ca0720 commit b96e307
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 13 deletions.
9 changes: 7 additions & 2 deletions src/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,13 @@ static bool cmd_def_mode(EditorState *e, const CommandArgs *a)
ptr_array_append(&ftmodes, mode);
}

static const FlagMapping map[] = {
{'u', MHF_NO_TEXT_INSERTION},
{'U', MHF_NO_TEXT_INSERTION | MHF_NO_TEXT_INSERTION_RECURSIVE},
};

ModeHandler *mode = new_mode(modes, xstrdup(name), &normal_commands);
mode->insert_text_for_unicode_range = !has_flag(a, 'u');
mode->flags = cmdargs_convert_flags(a, map, ARRAYLEN(map));
mode->fallthrough_modes = ftmodes;
return true;
}
Expand Down Expand Up @@ -2637,7 +2642,7 @@ static const Command cmds[] = {
{"copy", "bikp", NA, 0, 1, cmd_copy},
{"cursor", "", RC, 0, 3, cmd_cursor},
{"cut", "", NA, 0, 0, cmd_cut},
{"def-mode", "u", RC, 1, 16, cmd_def_mode},
{"def-mode", "Uu", RC, 1, 16, cmd_def_mode},
{"delete", "", NA, 0, 0, cmd_delete},
{"delete-eol", "n", NA, 0, 0, cmd_delete_eol},
{"delete-line", "S", NA, 0, 0, cmd_delete_line},
Expand Down
28 changes: 19 additions & 9 deletions src/mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ ModeHandler *new_mode(HashMap *modes, char *name, const CommandSet *cmds)
ModeHandler *mode = xnew0(ModeHandler, 1);
mode->name = name;
mode->cmds = cmds;
mode->insert_text_for_unicode_range = true;
return hashmap_insert(modes, name, mode);
}

Expand All @@ -42,14 +41,22 @@ static bool insert_paste(EditorState *e, const ModeHandler *handler, bool bracke
return true;
}

static bool handle_input_single(EditorState *e, const ModeHandler *handler, KeyCode key)
{
static bool handle_input_single (
EditorState *e,
const ModeHandler *handler,
KeyCode key,
ModeHandlerFlags inherited_flags
) {
if (key == KEYCODE_DETECTED_PASTE || key == KEYCODE_BRACKETED_PASTE) {
return insert_paste(e, handler, key == KEYCODE_BRACKETED_PASTE);
}

const CommandSet *cmds = handler->cmds;
if (handler->insert_text_for_unicode_range) {
ModeHandlerFlags noinsert_flags = MHF_NO_TEXT_INSERTION | MHF_NO_TEXT_INSERTION_RECURSIVE;
ModeHandlerFlags flag_union = handler->flags | inherited_flags;
bool insert_unicode_range = !(flag_union & noinsert_flags);

if (insert_unicode_range) {
const CommandSet *cmds = handler->cmds;
if (cmds == &normal_commands) {
View *view = e->view;
KeyCode shift = key & MOD_SHIFT;
Expand Down Expand Up @@ -84,16 +91,19 @@ static bool handle_input_single(EditorState *e, const ModeHandler *handler, KeyC
static bool handle_input_recursive (
EditorState *e,
const ModeHandler *handler,
KeyCode key
KeyCode key,
ModeHandlerFlags inherited_flags
) {
if (handle_input_single(e, handler, key)) {
if (handle_input_single(e, handler, key, inherited_flags)) {
return true;
}

const PointerArray *ftmodes = &handler->fallthrough_modes;
inherited_flags |= (handler->flags & MHF_NO_TEXT_INSERTION_RECURSIVE);

for (size_t i = 0, n = ftmodes->count; i < n; i++) {
const ModeHandler *h = ftmodes->ptrs[i];
if (handle_input_recursive(e, h, key)) {
if (handle_input_recursive(e, h, key, inherited_flags)) {
return true;
}
}
Expand All @@ -103,5 +113,5 @@ static bool handle_input_recursive (

bool handle_input(EditorState *e, KeyCode key)
{
return handle_input_recursive(e, e->mode, key);
return handle_input_recursive(e, e->mode, key, 0);
}
7 changes: 6 additions & 1 deletion src/mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@
#include "util/macros.h"
#include "util/ptr-array.h"

typedef enum {
MHF_NO_TEXT_INSERTION = 1 << 0, // Don't insert text for keys in the Unicode range
MHF_NO_TEXT_INSERTION_RECURSIVE = 1 << 1, // As above, but also overriding all fallback modes
} ModeHandlerFlags;

typedef struct {
const char *name;
const CommandSet *cmds;
IntMap key_bindings;
bool insert_text_for_unicode_range;
ModeHandlerFlags flags;
PointerArray fallthrough_modes;
} ModeHandler;

Expand Down
4 changes: 3 additions & 1 deletion src/show.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,9 @@ static String dump_modes(EditorState *e)
for (HashMapIter it = hashmap_iter(&e->modes); hashmap_next(&it); ) {
const ModeHandler *mode = it.entry->value;
string_append_literal(&buf, "def-mode ");
if (!mode->insert_text_for_unicode_range) {
if (mode->flags & MHF_NO_TEXT_INSERTION_RECURSIVE) {
string_append_literal(&buf, "-U ");
} else if (mode->flags & MHF_NO_TEXT_INSERTION) {
string_append_literal(&buf, "-u ");
}
string_append_cstring(&buf, mode->name);
Expand Down

0 comments on commit b96e307

Please sign in to comment.