From d95274c5f294ddf1341f66019fee47a35b4f2561 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 27 Jul 2009 19:29:35 +0000 Subject: [PATCH] Change mode key bindings from big switches into a set of tables. Rather than lumping them all together, split editing keys from those used in choice/more mode and those for copy/scroll mode. Tidier and clearer, and the first step towards customisable mode keys. --- mode-key.c | 350 +++++++++++++++++++++++------------------------- status.c | 40 +++--- tmux.h | 100 +++++++++----- window-choose.c | 22 +-- window-copy.c | 38 +++--- window-more.c | 18 ++- window-scroll.c | 22 +-- 7 files changed, 316 insertions(+), 274 deletions(-) diff --git a/mode-key.c b/mode-key.c index a4a534b9..58769eda 100644 --- a/mode-key.c +++ b/mode-key.c @@ -20,198 +20,182 @@ #include "tmux.h" -enum mode_key_cmd mode_key_lookup_vi(struct mode_key_data *, int); -enum mode_key_cmd mode_key_lookup_emacs(struct mode_key_data *, int); +/* vi editing keys. */ +const struct mode_key_entry mode_key_vi_edit[] = { + { '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL }, + { '\010' /* C-h */, 0, MODEKEYEDIT_BACKSPACE }, + { '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE }, + { '\033' /* Escape */, 0, MODEKEYEDIT_SWITCHMODE }, + { '\r', 0, MODEKEYEDIT_ENTER }, + { KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE }, + { KEYC_DC, 0, MODEKEYEDIT_DELETE }, + + { '$', 1, MODEKEYEDIT_ENDOFLINE }, + { '0', 1, MODEKEYEDIT_STARTOFLINE }, + { 'D', 1, MODEKEYEDIT_DELETETOENDOFLINE }, + { '\003' /* C-c */, 1, MODEKEYEDIT_CANCEL }, + { '\010' /* C-h */, 1, MODEKEYEDIT_BACKSPACE }, + { '\r', 1, MODEKEYEDIT_ENTER }, + { '^', 1, MODEKEYEDIT_STARTOFLINE }, + { 'a', 1, MODEKEYEDIT_SWITCHMODEAPPEND }, + { 'h', 1, MODEKEYEDIT_CURSORLEFT }, + { 'i', 1, MODEKEYEDIT_SWITCHMODE }, + { 'j', 1, MODEKEYEDIT_HISTORYDOWN }, + { 'k', 1, MODEKEYEDIT_HISTORYUP }, + { 'l', 1, MODEKEYEDIT_CURSORRIGHT }, + { 'p', 1, MODEKEYEDIT_PASTE }, + { KEYC_BSPACE, 1, MODEKEYEDIT_BACKSPACE }, + { KEYC_DC, 1, MODEKEYEDIT_DELETE }, + { KEYC_DOWN, 1, MODEKEYEDIT_HISTORYDOWN }, + { KEYC_LEFT, 1, MODEKEYEDIT_CURSORLEFT }, + { KEYC_RIGHT, 1, MODEKEYEDIT_CURSORRIGHT }, + { KEYC_UP, 1, MODEKEYEDIT_HISTORYUP }, + + { 0, -1, 0 } +}; + +/* vi choice selection keys. */ +const struct mode_key_entry mode_key_vi_choice[] = { + { '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL }, + { '\r', 0, MODEKEYCHOICE_CHOOSE }, + { 'j', 0, MODEKEYCHOICE_DOWN }, + { 'k', 0, MODEKEYCHOICE_UP }, + { 'q', 0, MODEKEYCHOICE_CANCEL }, + { KEYC_DOWN, 0, MODEKEYCHOICE_DOWN }, + { KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN }, + { KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP }, + { KEYC_UP, 0, MODEKEYCHOICE_UP }, + + { 0, -1, 0 } +}; + +/* vi copy mode keys. */ +const struct mode_key_entry mode_key_vi_copy[] = { + { ' ', 0, MODEKEYCOPY_STARTSELECTION }, + { '$', 0, MODEKEYCOPY_ENDOFLINE }, + { '0', 0, MODEKEYCOPY_STARTOFLINE }, + { '\003' /* C-c */, 0, MODEKEYCOPY_QUIT }, + { '\006' /* C-f */, 0, MODEKEYCOPY_NEXTPAGE }, + { '\010' /* C-h */, 0, MODEKEYCOPY_LEFT }, + { '\025' /* C-u */, 0, MODEKEYCOPY_PREVIOUSPAGE }, + { '\033' /* Escape */, 0, MODEKEYCOPY_CLEARSELECTION }, + { '\r', 0, MODEKEYCOPY_COPYSELECTION }, + { '^', 0, MODEKEYCOPY_BACKTOINDENTATION }, + { 'b', 0, MODEKEYCOPY_PREVIOUSWORD }, + { 'h', 0, MODEKEYCOPY_LEFT }, + { 'j', 0, MODEKEYCOPY_DOWN }, + { 'k', 0, MODEKEYCOPY_UP }, + { 'l', 0, MODEKEYCOPY_RIGHT }, + { 'q', 0, MODEKEYCOPY_QUIT }, + { 'w', 0, MODEKEYCOPY_NEXTWORD }, + { KEYC_BSPACE, 0, MODEKEYCOPY_LEFT }, + { KEYC_DOWN, 0, MODEKEYCOPY_DOWN }, + { KEYC_LEFT, 0, MODEKEYCOPY_LEFT }, + { KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE }, + { KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE }, + { KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT }, + { KEYC_UP, 0, MODEKEYCOPY_UP }, + + { 0, -1, 0 } +}; + +/* emacs editing keys. */ +const struct mode_key_entry mode_key_emacs_edit[] = { + { '\001' /* C-a */, 0, MODEKEYEDIT_STARTOFLINE }, + { '\002' /* C-p */, 0, MODEKEYEDIT_CURSORLEFT }, + { '\004' /* C-d */, 0, MODEKEYEDIT_DELETE }, + { '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE }, + { '\006' /* C-f */, 0, MODEKEYEDIT_CURSORRIGHT }, + { '\010' /* C-H */, 0, MODEKEYEDIT_BACKSPACE }, + { '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE }, + { '\013' /* C-k */, 0, MODEKEYEDIT_DELETETOENDOFLINE }, + { '\016' /* C-n */, 0, MODEKEYEDIT_HISTORYDOWN }, + { '\020' /* C-p */, 0, MODEKEYEDIT_HISTORYUP }, + { '\031' /* C-y */, 0, MODEKEYEDIT_PASTE }, + { '\r', 0, MODEKEYEDIT_ENTER }, + { 'm' | KEYC_ESCAPE, 0, MODEKEYEDIT_STARTOFLINE }, + { KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE }, + { KEYC_DC, 0, MODEKEYEDIT_DELETE }, + { KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN }, + { KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT }, + { KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT }, + { KEYC_UP, 0, MODEKEYEDIT_HISTORYUP }, + + { 0, -1, 0 } +}; + +/* emacs choice selection keys. */ +const struct mode_key_entry mode_key_emacs_choice[] = { + { '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL }, + { '\033' /* Escape */, 0, MODEKEYCHOICE_CANCEL }, + { '\r', 0, MODEKEYCHOICE_CHOOSE }, + { 'q', 0, MODEKEYCHOICE_CANCEL }, + { KEYC_DOWN, 0, MODEKEYCHOICE_DOWN }, + { KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN }, + { KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP }, + { KEYC_UP, 0, MODEKEYCHOICE_UP }, + + { 0, -1, 0 } +}; + +/* emacs copy mode keys. */ +const struct mode_key_entry mode_key_emacs_copy[] = { + { ' ', 0, MODEKEYCOPY_NEXTPAGE }, + { '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION }, + { '\001' /* C-a */, 0, MODEKEYCOPY_STARTOFLINE }, + { '\002' /* C-b */, 0, MODEKEYCOPY_LEFT }, + { '\003' /* C-c */, 0, MODEKEYCOPY_QUIT }, + { '\005' /* C-e */, 0, MODEKEYCOPY_ENDOFLINE }, + { '\006' /* C-f */, 0, MODEKEYCOPY_RIGHT }, + { '\007' /* C-g */, 0, MODEKEYCOPY_CLEARSELECTION }, + { '\016' /* C-n */, 0, MODEKEYCOPY_DOWN }, + { '\020' /* C-p */, 0, MODEKEYCOPY_UP }, + { '\026' /* C-v */, 0, MODEKEYCOPY_NEXTPAGE }, + { '\027' /* C-w */, 0, MODEKEYCOPY_COPYSELECTION }, + { '\033' /* Escape */, 0, MODEKEYCOPY_QUIT }, + { 'b' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSWORD }, + { 'f' | KEYC_ESCAPE, 0, MODEKEYCOPY_NEXTWORD }, + { 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION }, + { 'q', 0, MODEKEYCOPY_QUIT }, + { 'v' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPAGE }, + { 'w' | KEYC_ESCAPE, 0, MODEKEYCOPY_COPYSELECTION }, + { KEYC_DOWN, 0, MODEKEYCOPY_DOWN }, + { KEYC_LEFT, 0, MODEKEYCOPY_LEFT }, + { KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE }, + { KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE }, + { KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT }, + { KEYC_UP, 0, MODEKEYCOPY_UP }, + + { 0, -1, 0 } +}; void -mode_key_init(struct mode_key_data *mdata, int type, int flags) +mode_key_init(struct mode_key_data *mdata, const struct mode_key_entry *table) { - mdata->type = type; - - if (flags & MODEKEY_CANEDIT) - flags |= MODEKEY_EDITMODE; - mdata->flags = flags; + mdata->table = table; + mdata->mode = 0; } enum mode_key_cmd mode_key_lookup(struct mode_key_data *mdata, int key) { - switch (mdata->type) { - case MODEKEY_VI: - return (mode_key_lookup_vi(mdata, key)); - case MODEKEY_EMACS: - return (mode_key_lookup_emacs(mdata, key)); - default: - fatalx("unknown mode key type"); - } -} + const struct mode_key_entry *ment; + int mode; -enum mode_key_cmd -mode_key_lookup_vi(struct mode_key_data *mdata, int key) -{ - if (key & KEYC_ESCAPE) { - key &= ~KEYC_ESCAPE; - if (mdata->flags & MODEKEY_CANEDIT) - mdata->flags ^= MODEKEY_EDITMODE; - } - - - if (mdata->flags & MODEKEY_EDITMODE) { - switch (key) { - case '\003': - return (MODEKEYCMD_QUIT); - case '\033': - if (mdata->flags & MODEKEY_CANEDIT) - mdata->flags &= ~MODEKEY_EDITMODE; - return (MODEKEYCMD_NONE); - case '\010': - case KEYC_BSPACE: - return (MODEKEYCMD_BACKSPACE); - case '\011': - return (MODEKEYCMD_COMPLETE); - case KEYC_DC: - return (MODEKEYCMD_DELETE); - case '\r': - return (MODEKEYCMD_CHOOSE); + mode = mdata->mode; + for (ment = mdata->table; ment->mode != -1; ment++) { + if (ment->mode == mode && key == ment->key) { + switch (ment->cmd) { + case MODEKEYEDIT_SWITCHMODE: + case MODEKEYEDIT_SWITCHMODEAPPEND: + mdata->mode = 1 - mdata->mode; + /* FALLTHROUGH */ + default: + return (ment->cmd); + } } - return (MODEKEYCMD_OTHERKEY); } - - switch (key) { - case '\010': - case KEYC_BSPACE: - return (MODEKEYCMD_LEFT); - case KEYC_DC: - return (MODEKEYCMD_DELETE); - case '\011': - return (MODEKEYCMD_COMPLETE); - case 'i': - if (mdata->flags & MODEKEY_CANEDIT) - mdata->flags |= MODEKEY_EDITMODE; - break; - case 'a': - if (mdata->flags & MODEKEY_CANEDIT) { - mdata->flags |= MODEKEY_EDITMODE; - return (MODEKEYCMD_RIGHT); - } - break; - case '\r': - if (mdata->flags & (MODEKEY_CANEDIT|MODEKEY_CHOOSEMODE)) - return (MODEKEYCMD_CHOOSE); - return (MODEKEYCMD_COPYSELECTION); - case '0': - return (MODEKEYCMD_STARTOFLINE); - case '^': - return (MODEKEYCMD_BACKTOINDENTATION); - case '\033': - return (MODEKEYCMD_CLEARSELECTION); - case 'C': - if (mdata->flags & MODEKEY_CANEDIT) - mdata->flags |= MODEKEY_EDITMODE; - return (MODEKEYCMD_DELETETOENDOFLINE); - case 'D': - return (MODEKEYCMD_DELETETOENDOFLINE); - case 'j': - case KEYC_DOWN: - return (MODEKEYCMD_DOWN); - case '$': - return (MODEKEYCMD_ENDOFLINE); - case 'h': - case KEYC_LEFT: - return (MODEKEYCMD_LEFT); - case '\006': - case KEYC_NPAGE: - return (MODEKEYCMD_NEXTPAGE); - case 'w': - return (MODEKEYCMD_NEXTWORD); - case '\025': - case KEYC_PPAGE: - return (MODEKEYCMD_PREVIOUSPAGE); - case 'b': - return (MODEKEYCMD_PREVIOUSWORD); - case 'q': - case '\003': - return (MODEKEYCMD_QUIT); - case 'l': - case KEYC_RIGHT: - return (MODEKEYCMD_RIGHT); - case ' ': - return (MODEKEYCMD_STARTSELECTION); - case 'k': - case KEYC_UP: - return (MODEKEYCMD_UP); - case 'p': - return (MODEKEYCMD_PASTE); - } - - return (MODEKEYCMD_NONE); -} - -enum mode_key_cmd -mode_key_lookup_emacs(struct mode_key_data *mdata, int key) -{ - switch (key) { - case '\010': - case KEYC_BSPACE: - return (MODEKEYCMD_BACKSPACE); - case '\004': - case KEYC_DC: - return (MODEKEYCMD_DELETE); - case '\011': - return (MODEKEYCMD_COMPLETE); - case '\r': - return (MODEKEYCMD_CHOOSE); - case '\001': - return (MODEKEYCMD_STARTOFLINE); - case 'm' | KEYC_ESCAPE: - return (MODEKEYCMD_BACKTOINDENTATION); - case '\007': - return (MODEKEYCMD_CLEARSELECTION); - case '\027': - case 'w' | KEYC_ESCAPE: - return (MODEKEYCMD_COPYSELECTION); - case '\013': - return (MODEKEYCMD_DELETETOENDOFLINE); - case '\016': - case KEYC_DOWN: - return (MODEKEYCMD_DOWN); - case '\005': - return (MODEKEYCMD_ENDOFLINE); - case '\002': - case KEYC_LEFT: - return (MODEKEYCMD_LEFT); - case ' ': - if (mdata->flags & MODEKEY_CANEDIT) - break; - /* FALLTHROUGH */ - case '\026': - case KEYC_NPAGE: - return (MODEKEYCMD_NEXTPAGE); - case 'f' | KEYC_ESCAPE: - return (MODEKEYCMD_NEXTWORD); - case '\031': - return (MODEKEYCMD_PASTE); - case 'v' | KEYC_ESCAPE: - case KEYC_PPAGE: - return (MODEKEYCMD_PREVIOUSPAGE); - case 'b' | KEYC_ESCAPE: - return (MODEKEYCMD_PREVIOUSWORD); - case '\006': - case KEYC_RIGHT: - return (MODEKEYCMD_RIGHT); - case '\000': - return (MODEKEYCMD_STARTSELECTION); - case '\020': - case KEYC_UP: - return (MODEKEYCMD_UP); - case 'q': - if (mdata->flags & MODEKEY_CANEDIT) - break; - /* FALLTHROUGH */ - case '\003': - case '\033': - return (MODEKEYCMD_QUIT); - } - - return (MODEKEYCMD_OTHERKEY); + if (mode != 0) + return (MODEKEY_NONE); + return (MODEKEY_OTHER); } diff --git a/status.c b/status.c index 98f7967b..fef440eb 100644 --- a/status.c +++ b/status.c @@ -589,6 +589,8 @@ status_prompt_set(struct client *c, const char *msg, int (*callbackfn)(void *, const char *), void (*freefn)(void *), void *data, int flags) { + int keys; + status_message_clear(c); status_prompt_clear(c); @@ -605,9 +607,11 @@ status_prompt_set(struct client *c, const char *msg, c->prompt_flags = flags; - mode_key_init(&c->prompt_mdata, - options_get_number(&c->session->options, "status-keys"), - MODEKEY_CANEDIT); + keys = options_get_number(&c->session->options, "status-keys"); + if (keys == MODEKEY_EMACS) + mode_key_init(&c->prompt_mdata, mode_key_emacs_edit); + else + mode_key_init(&c->prompt_mdata, mode_key_vi_edit); c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE); c->flags |= CLIENT_STATUS; @@ -727,32 +731,32 @@ status_prompt_key(struct client *c, int key) size = strlen(c->prompt_buffer); switch (mode_key_lookup(&c->prompt_mdata, key)) { - case MODEKEYCMD_LEFT: + case MODEKEYEDIT_CURSORLEFT: if (c->prompt_index > 0) { c->prompt_index--; c->flags |= CLIENT_STATUS; } break; - case MODEKEYCMD_RIGHT: + case MODEKEYEDIT_SWITCHMODEAPPEND: + case MODEKEYEDIT_CURSORRIGHT: if (c->prompt_index < size) { c->prompt_index++; c->flags |= CLIENT_STATUS; } break; - case MODEKEYCMD_STARTOFLINE: - case MODEKEYCMD_BACKTOINDENTATION: + case MODEKEYEDIT_STARTOFLINE: if (c->prompt_index != 0) { c->prompt_index = 0; c->flags |= CLIENT_STATUS; } break; - case MODEKEYCMD_ENDOFLINE: + case MODEKEYEDIT_ENDOFLINE: if (c->prompt_index != size) { c->prompt_index = size; c->flags |= CLIENT_STATUS; } break; - case MODEKEYCMD_COMPLETE: + case MODEKEYEDIT_COMPLETE: if (*c->prompt_buffer == '\0') break; @@ -800,7 +804,7 @@ status_prompt_key(struct client *c, int key) c->flags |= CLIENT_STATUS; break; - case MODEKEYCMD_BACKSPACE: + case MODEKEYEDIT_BACKSPACE: if (c->prompt_index != 0) { if (c->prompt_index == size) c->prompt_buffer[--c->prompt_index] = '\0'; @@ -813,7 +817,7 @@ status_prompt_key(struct client *c, int key) c->flags |= CLIENT_STATUS; } break; - case MODEKEYCMD_DELETE: + case MODEKEYEDIT_DELETE: if (c->prompt_index != size) { memmove(c->prompt_buffer + c->prompt_index, c->prompt_buffer + c->prompt_index + 1, @@ -821,13 +825,13 @@ status_prompt_key(struct client *c, int key) c->flags |= CLIENT_STATUS; } break; - case MODEKEYCMD_DELETETOENDOFLINE: + case MODEKEYEDIT_DELETETOENDOFLINE: if (c->prompt_index < size) { c->prompt_buffer[c->prompt_index] = '\0'; c->flags |= CLIENT_STATUS; } break; - case MODEKEYCMD_UP: + case MODEKEYEDIT_HISTORYUP: if (server_locked) break; @@ -845,7 +849,7 @@ status_prompt_key(struct client *c, int key) c->prompt_index = strlen(c->prompt_buffer); c->flags |= CLIENT_STATUS; break; - case MODEKEYCMD_DOWN: + case MODEKEYEDIT_HISTORYDOWN: if (server_locked) break; @@ -864,7 +868,7 @@ status_prompt_key(struct client *c, int key) c->prompt_index = strlen(c->prompt_buffer); c->flags |= CLIENT_STATUS; break; - case MODEKEYCMD_PASTE: + case MODEKEYEDIT_PASTE: if ((pb = paste_get_top(&c->session->buffers)) == NULL) break; if ((last = strchr(pb->data, '\n')) == NULL) @@ -886,7 +890,7 @@ status_prompt_key(struct client *c, int key) c->flags |= CLIENT_STATUS; break; - case MODEKEYCMD_CHOOSE: + case MODEKEYEDIT_ENTER: if (*c->prompt_buffer != '\0') { status_prompt_add_history(c); if (c->prompt_callbackfn( @@ -895,11 +899,11 @@ status_prompt_key(struct client *c, int key) break; } /* FALLTHROUGH */ - case MODEKEYCMD_QUIT: + case MODEKEYEDIT_CANCEL: if (c->prompt_callbackfn(c->prompt_data, NULL) == 0) status_prompt_clear(c); break; - case MODEKEYCMD_OTHERKEY: + case MODEKEY_OTHER: if (key < 32 || key > 126) break; c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 2); diff --git a/tmux.h b/tmux.h index 3dc82eca..505e3d68 100644 --- a/tmux.h +++ b/tmux.h @@ -358,40 +358,71 @@ struct msg_unlock_data { /* Editing keys. */ enum mode_key_cmd { - MODEKEYCMD_BACKSPACE = 0x1000, - MODEKEYCMD_BACKTOINDENTATION, - MODEKEYCMD_CHOOSE, - MODEKEYCMD_CLEARSELECTION, - MODEKEYCMD_COMPLETE, - MODEKEYCMD_COPYSELECTION, - MODEKEYCMD_DELETE, - MODEKEYCMD_DELETETOENDOFLINE, - MODEKEYCMD_DOWN, - MODEKEYCMD_ENDOFLINE, - MODEKEYCMD_LEFT, - MODEKEYCMD_NEXTPAGE, - MODEKEYCMD_NEXTWORD, - MODEKEYCMD_NONE, - MODEKEYCMD_OTHERKEY, - MODEKEYCMD_PASTE, - MODEKEYCMD_PREVIOUSPAGE, - MODEKEYCMD_PREVIOUSWORD, - MODEKEYCMD_QUIT, - MODEKEYCMD_RIGHT, - MODEKEYCMD_STARTOFLINE, - MODEKEYCMD_STARTSELECTION, - MODEKEYCMD_UP, + MODEKEY_NONE, + MODEKEY_OTHER, + + /* Editing keys. */ + MODEKEYEDIT_BACKSPACE, + MODEKEYEDIT_CANCEL, + MODEKEYEDIT_COMPLETE, + MODEKEYEDIT_CURSORLEFT, + MODEKEYEDIT_CURSORRIGHT, + MODEKEYEDIT_DELETE, + MODEKEYEDIT_DELETETOENDOFLINE, + MODEKEYEDIT_ENDOFLINE, + MODEKEYEDIT_ENTER, + MODEKEYEDIT_HISTORYDOWN, + MODEKEYEDIT_HISTORYUP, + MODEKEYEDIT_PASTE, + MODEKEYEDIT_STARTOFLINE, + MODEKEYEDIT_SWITCHMODE, + MODEKEYEDIT_SWITCHMODEAPPEND, + + /* Menu (choice) keys. */ + MODEKEYCHOICE_CANCEL, + MODEKEYCHOICE_CHOOSE, + MODEKEYCHOICE_DOWN, + MODEKEYCHOICE_PAGEDOWN, + MODEKEYCHOICE_PAGEUP, + MODEKEYCHOICE_UP, + + /* Copy keys. */ + MODEKEYCOPY_CANCEL, + MODEKEYCOPY_BACKTOINDENTATION, + MODEKEYCOPY_CLEARSELECTION, + MODEKEYCOPY_COPYSELECTION, + MODEKEYCOPY_DOWN, + MODEKEYCOPY_ENDOFLINE, + MODEKEYCOPY_LEFT, + MODEKEYCOPY_NEXTPAGE, + MODEKEYCOPY_NEXTWORD, + MODEKEYCOPY_NONE, + MODEKEYCOPY_PREVIOUSPAGE, + MODEKEYCOPY_PREVIOUSWORD, + MODEKEYCOPY_QUIT, + MODEKEYCOPY_RIGHT, + MODEKEYCOPY_STARTOFLINE, + MODEKEYCOPY_STARTSELECTION, + MODEKEYCOPY_UP, }; +struct mode_key_entry { + int key; + + /* + * Editing mode for vi: 0 is edit mode, keys not in the table are + * returned as MODEKEY_OTHER; 1 is command mode, keys not in the table + * are returned as MODEKEY_NONE. This is also matched on, allowing some + * keys to be bound in edit mode. + */ + int mode; + + enum mode_key_cmd cmd; +}; struct mode_key_data { - int type; - - int flags; -#define MODEKEY_EDITMODE 0x1 -#define MODEKEY_CANEDIT 0x2 -#define MODEKEY_CHOOSEMODE 0x4 + const struct mode_key_entry *table; + int mode; }; - #define MODEKEY_EMACS 0 #define MODEKEY_VI 1 @@ -1032,7 +1063,14 @@ void sighandler(int); int load_cfg(const char *, char **x); /* mode-key.c */ -void mode_key_init(struct mode_key_data *, int, int); +extern const struct mode_key_entry mode_key_vi_edit[]; +extern const struct mode_key_entry mode_key_vi_choice[]; +extern const struct mode_key_entry mode_key_vi_copy[]; +extern const struct mode_key_entry mode_key_emacs_edit[]; +extern const struct mode_key_entry mode_key_emacs_choice[]; +extern const struct mode_key_entry mode_key_emacs_copy[]; +void mode_key_init( + struct mode_key_data *, const struct mode_key_entry *); enum mode_key_cmd mode_key_lookup(struct mode_key_data *, int); /* options.c */ diff --git a/window-choose.c b/window-choose.c index 8439c9a0..b1ae3bc5 100644 --- a/window-choose.c +++ b/window-choose.c @@ -109,6 +109,7 @@ window_choose_init(struct window_pane *wp) { struct window_choose_mode_data *data; struct screen *s; + int keys; wp->modedata = data = xmalloc(sizeof *data); @@ -124,9 +125,11 @@ window_choose_init(struct window_pane *wp) s->mode &= ~MODE_CURSOR; s->mode |= MODE_MOUSE; - mode_key_init(&data->mdata, - options_get_number(&wp->window->options, "mode-keys"), - MODEKEY_CHOOSEMODE); + keys = options_get_number(&wp->window->options, "mode-keys"); + if (keys == MODEKEY_EMACS) + mode_key_init(&data->mdata, mode_key_emacs_choice); + else + mode_key_init(&data->mdata, mode_key_vi_choice); return (s); } @@ -174,16 +177,16 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key) items = ARRAY_LENGTH(&data->list); switch (mode_key_lookup(&data->mdata, key)) { - case MODEKEYCMD_QUIT: + case MODEKEYCHOICE_CANCEL: data->callbackfn(data->data, -1); window_pane_reset_mode(wp); break; - case MODEKEYCMD_CHOOSE: + case MODEKEYCHOICE_CHOOSE: item = &ARRAY_ITEM(&data->list, data->selected); data->callbackfn(data->data, item->idx); window_pane_reset_mode(wp); break; - case MODEKEYCMD_UP: + case MODEKEYCHOICE_UP: if (items == 0) break; if (data->selected == 0) { @@ -205,7 +208,7 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key) screen_write_stop(&ctx); } break; - case MODEKEYCMD_DOWN: + case MODEKEYCHOICE_DOWN: if (items == 0) break; if (data->selected == items - 1) { @@ -215,6 +218,7 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key) break; } data->selected++; + if (data->selected >= data->top + screen_size_y(&data->screen)) window_choose_scroll_down(wp); else { @@ -226,7 +230,7 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key) screen_write_stop(&ctx); } break; - case MODEKEYCMD_PREVIOUSPAGE: + case MODEKEYCHOICE_PAGEUP: if (data->selected < screen_size_y(s)) { data->selected = 0; data->top = 0; @@ -239,7 +243,7 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key) } window_choose_redraw_screen(wp); break; - case MODEKEYCMD_NEXTPAGE: + case MODEKEYCHOICE_PAGEDOWN: data->selected += screen_size_y(s); if (data->selected > items - 1) data->selected = items - 1; diff --git a/window-copy.c b/window-copy.c index d87a645e..7ca4cd34 100644 --- a/window-copy.c +++ b/window-copy.c @@ -94,6 +94,7 @@ window_copy_init(struct window_pane *wp) struct screen *s; struct screen_write_ctx ctx; u_int i; + int keys; wp->modedata = data = xmalloc(sizeof *data); data->ox = 0; @@ -105,8 +106,11 @@ window_copy_init(struct window_pane *wp) screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); s->mode |= MODE_MOUSE; - mode_key_init(&data->mdata, - options_get_number(&wp->window->options, "mode-keys"), 0); + keys = options_get_number(&wp->window->options, "mode-keys"); + if (keys == MODEKEY_EMACS) + mode_key_init(&data->mdata, mode_key_emacs_copy); + else + mode_key_init(&data->mdata, mode_key_vi_copy); s->cx = data->cx; s->cy = data->cy; @@ -164,25 +168,25 @@ window_copy_key(struct window_pane *wp, struct client *c, int key) struct screen *s = &data->screen; switch (mode_key_lookup(&data->mdata, key)) { - case MODEKEYCMD_QUIT: + case MODEKEYCOPY_QUIT: window_pane_reset_mode(wp); break; - case MODEKEYCMD_LEFT: + case MODEKEYCOPY_LEFT: window_copy_cursor_left(wp); return; - case MODEKEYCMD_RIGHT: + case MODEKEYCOPY_RIGHT: window_copy_cursor_right(wp); return; - case MODEKEYCMD_UP: + case MODEKEYCOPY_UP: window_copy_cursor_up(wp); return; - case MODEKEYCMD_DOWN: + case MODEKEYCOPY_DOWN: window_copy_cursor_down(wp); return; - case MODEKEYCMD_PREVIOUSPAGE: + case MODEKEYCOPY_PREVIOUSPAGE: window_copy_pageup(wp); break; - case MODEKEYCMD_NEXTPAGE: + case MODEKEYCOPY_NEXTPAGE: if (data->oy < screen_size_y(s)) data->oy = 0; else @@ -190,33 +194,33 @@ window_copy_key(struct window_pane *wp, struct client *c, int key) window_copy_update_selection(wp); window_copy_redraw_screen(wp); break; - case MODEKEYCMD_STARTSELECTION: + case MODEKEYCOPY_STARTSELECTION: window_copy_start_selection(wp); window_copy_redraw_screen(wp); break; - case MODEKEYCMD_CLEARSELECTION: + case MODEKEYCOPY_CLEARSELECTION: screen_clear_selection(&data->screen); window_copy_redraw_screen(wp); break; - case MODEKEYCMD_COPYSELECTION: + case MODEKEYCOPY_COPYSELECTION: if (c != NULL && c->session != NULL) { window_copy_copy_selection(wp, c); window_pane_reset_mode(wp); } break; - case MODEKEYCMD_STARTOFLINE: + case MODEKEYCOPY_STARTOFLINE: window_copy_cursor_start_of_line(wp); break; - case MODEKEYCMD_BACKTOINDENTATION: + case MODEKEYCOPY_BACKTOINDENTATION: window_copy_cursor_back_to_indentation(wp); break; - case MODEKEYCMD_ENDOFLINE: + case MODEKEYCOPY_ENDOFLINE: window_copy_cursor_end_of_line(wp); break; - case MODEKEYCMD_NEXTWORD: + case MODEKEYCOPY_NEXTWORD: window_copy_cursor_next_word(wp); break; - case MODEKEYCMD_PREVIOUSWORD: + case MODEKEYCOPY_PREVIOUSWORD: window_copy_cursor_previous_word(wp); break; default: diff --git a/window-more.c b/window-more.c index d92a06a2..a113c4ba 100644 --- a/window-more.c +++ b/window-more.c @@ -80,6 +80,7 @@ window_more_init(struct window_pane *wp) { struct window_more_mode_data *data; struct screen *s; + int keys; wp->modedata = data = xmalloc(sizeof *data); ARRAY_INIT(&data->list); @@ -89,8 +90,11 @@ window_more_init(struct window_pane *wp) screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); s->mode &= ~MODE_CURSOR; - mode_key_init(&data->mdata, - options_get_number(&wp->window->options, "mode-keys"), 0); + keys = options_get_number(&wp->window->options, "mode-keys"); + if (keys == MODEKEY_EMACS) + mode_key_init(&data->mdata, mode_key_emacs_choice); + else + mode_key_init(&data->mdata, mode_key_vi_choice); return (s); } @@ -126,23 +130,23 @@ window_more_key(struct window_pane *wp, unused struct client *c, int key) struct screen *s = &data->screen; switch (mode_key_lookup(&data->mdata, key)) { - case MODEKEYCMD_QUIT: + case MODEKEYCHOICE_CANCEL: window_pane_reset_mode(wp); break; - case MODEKEYCMD_UP: + case MODEKEYCHOICE_UP: window_more_scroll_up(wp); break; - case MODEKEYCMD_DOWN: + case MODEKEYCHOICE_DOWN: window_more_scroll_down(wp); break; - case MODEKEYCMD_PREVIOUSPAGE: + case MODEKEYCHOICE_PAGEUP: if (data->top < screen_size_y(s)) data->top = 0; else data->top -= screen_size_y(s); window_more_redraw_screen(wp); break; - case MODEKEYCMD_NEXTPAGE: + case MODEKEYCHOICE_PAGEDOWN: if (data->top + screen_size_y(s) > ARRAY_LENGTH(&data->list)) data->top = ARRAY_LENGTH(&data->list); else diff --git a/window-scroll.c b/window-scroll.c index ecc76306..c14d1ab0 100644 --- a/window-scroll.c +++ b/window-scroll.c @@ -63,6 +63,7 @@ window_scroll_init(struct window_pane *wp) struct screen *s; struct screen_write_ctx ctx; u_int i; + int keys; wp->modedata = data = xmalloc(sizeof *data); data->ox = 0; @@ -72,8 +73,11 @@ window_scroll_init(struct window_pane *wp) screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); s->mode &= ~MODE_CURSOR; - mode_key_init(&data->mdata, - options_get_number(&wp->window->options, "mode-keys"), 0); + keys = options_get_number(&wp->window->options, "mode-keys"); + if (keys == MODEKEY_EMACS) + mode_key_init(&data->mdata, mode_key_emacs_copy); + else + mode_key_init(&data->mdata, mode_key_vi_copy); screen_write_start(&ctx, NULL, s); for (i = 0; i < screen_size_y(s); i++) @@ -128,25 +132,25 @@ window_scroll_key(struct window_pane *wp, unused struct client *c, int key) struct screen *s = &data->screen; switch (mode_key_lookup(&data->mdata, key)) { - case MODEKEYCMD_QUIT: + case MODEKEYCOPY_QUIT: window_pane_reset_mode(wp); break; - case MODEKEYCMD_LEFT: + case MODEKEYCOPY_LEFT: window_scroll_scroll_left(wp); break; - case MODEKEYCMD_RIGHT: + case MODEKEYCOPY_RIGHT: window_scroll_scroll_right(wp); break; - case MODEKEYCMD_UP: + case MODEKEYCOPY_UP: window_scroll_scroll_up(wp); break; - case MODEKEYCMD_DOWN: + case MODEKEYCOPY_DOWN: window_scroll_scroll_down(wp); break; - case MODEKEYCMD_PREVIOUSPAGE: + case MODEKEYCOPY_PREVIOUSPAGE: window_scroll_pageup(wp); break; - case MODEKEYCMD_NEXTPAGE: + case MODEKEYCOPY_NEXTPAGE: if (data->oy < screen_size_y(s)) data->oy = 0; else