commit a1bd5162112beefbbc1ecd902f144b254e506533 from: Omar Polo date: Wed Dec 01 10:06:02 2021 UTC rewrite the keybindings management use a table to define all the keys and split actions into separate functions. It's cleaner to support multiple keys bound to the same action this way (like for e.g. PAGE_DOWN and C-v.) commit - 0db009bca77db64ec36af221d77c8e669e089389 commit + a1bd5162112beefbbc1ecd902f144b254e506533 blob - ebdadcf261d06a846158e3c43b82491307f36d43 blob + f1f0329c5438ff23d5298ca56a330434fc42181f --- fm.c +++ fm.c @@ -1155,44 +1155,113 @@ update_input(const char *prompt, enum color c) } static void -loop(void) +cmd_down(void) { - int ch; - - for (;;) { - ch = fm_getch(); - clear_message(); - switch (ch) { - case 'j': - case 'n': - case CTRL('n'): - if (!fm.nfiles) - continue; - ESEL = MIN(ESEL + 1, fm.nfiles - 1); - update_view(); - break; + if (fm.nfiles) + ESEL = MIN(ESEL + 1, fm.nfiles - 1); +} - case 'k': - case 'p': - case CTRL('p'): - if (!fm.nfiles) - continue; - ESEL = MAX(ESEL - 1, 0); - update_view(); - break; +static void +cmd_up(void) +{ + if (fm.nfiles) + ESEL = MAX(ESEL - 1, 0); +} - case 'q': - return; +static void +cmd_scroll_down(void) +{ + if (!fm.nfiles) + return; + ESEL = MIN(ESEL + HEIGHT, fm.nfiles - 1); + if (fm.nfiles > HEIGHT) + SCROLL = MIN(SCROLL + HEIGHT, fm.nfiles - HEIGHT); +} - case '?': - spawn("man", "fm", NULL); - break; +static void +cmd_scroll_up(void) +{ + if (!fm.nfiles) + return; + ESEL = MAX(ESEL - HEIGHT, 0); + SCROLL = MAX(SCROLL - HEIGHT, 0); +} - default: - message(RED, "%s is undefined", keyname(ch)); - refresh(); - break; +static void +cmd_man(void) +{ + spawn("man", "fm", NULL); +} + +static void +loop(void) +{ + int meta, ch, c; + struct binding { + int ch; +#define K_META 1 +#define K_CTRL 2 + int chflags; + void (*fn)(void); +#define X_UPDV 1 +#define X_QUIT 2 + int flags; + } bindings[] = { + {'?', 0, cmd_man, 0}, + {'J', 0, cmd_scroll_down, X_UPDV}, + {'K', 0, cmd_scroll_up, X_UPDV}, + {'V', K_CTRL, cmd_scroll_down, X_UPDV}, + {'g', K_CTRL, NULL, X_UPDV}, + {'j', 0, cmd_down, X_UPDV}, + {'k', 0, cmd_up, X_UPDV}, + {'n', 0, cmd_down, X_UPDV}, + {'n', K_CTRL, cmd_down, X_UPDV}, + {'p', 0, cmd_up, X_UPDV}, + {'p', K_CTRL, cmd_up, X_UPDV}, + {'q', 0, NULL, X_QUIT}, + {'v', K_META, cmd_scroll_up, X_UPDV}, + {KEY_NPAGE, 0, cmd_scroll_down, X_UPDV}, + {KEY_PPAGE, 0, cmd_scroll_up, X_UPDV}, + {KEY_RESIZE, 0, NULL, X_UPDV}, + {KEY_RESIZE, K_META, NULL, X_UPDV}, + }, *b; + size_t i; + + for (;;) { + again: + meta = 0; + ch = fm_getch(); + if (ch == '\e') { + meta = 1; + if ((ch = fm_getch()) == '\e') { + meta = 0; + ch = '\e'; + } } + + clear_message(); + + for (i = 0; i < nitems(bindings); ++i) { + b = &bindings[i]; + c = b->ch; + if (b->chflags & K_CTRL) + c = CTRL(c); + if ((!meta && b->chflags & K_META) || ch != c) + continue; + + if (b->flags & X_QUIT) + return; + if (b->fn != NULL) + b->fn(); + if (b->flags & X_UPDV) + update_view(); + + goto again; + } + + message(RED, "%s%s is undefined", + meta ? "M-": "", keyname(ch)); + refresh(); } }