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.
This commit is contained in:
Nicholas Marriott 2009-07-27 19:29:35 +00:00
parent 13e29dd7b5
commit d95274c5f2
7 changed files with 316 additions and 274 deletions

View File

@ -20,198 +20,182 @@
#include "tmux.h" #include "tmux.h"
enum mode_key_cmd mode_key_lookup_vi(struct mode_key_data *, int); /* vi editing keys. */
enum mode_key_cmd mode_key_lookup_emacs(struct mode_key_data *, int); 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 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; mdata->table = table;
mdata->mode = 0;
if (flags & MODEKEY_CANEDIT)
flags |= MODEKEY_EDITMODE;
mdata->flags = flags;
} }
enum mode_key_cmd enum mode_key_cmd
mode_key_lookup(struct mode_key_data *mdata, int key) mode_key_lookup(struct mode_key_data *mdata, int key)
{ {
switch (mdata->type) { const struct mode_key_entry *ment;
case MODEKEY_VI: int mode;
return (mode_key_lookup_vi(mdata, key));
case MODEKEY_EMACS: mode = mdata->mode;
return (mode_key_lookup_emacs(mdata, key)); 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: default:
fatalx("unknown mode key type"); return (ment->cmd);
} }
} }
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 (mode != 0)
return (MODEKEY_NONE);
if (mdata->flags & MODEKEY_EDITMODE) { return (MODEKEY_OTHER);
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);
}
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);
} }

View File

@ -589,6 +589,8 @@ status_prompt_set(struct client *c, const char *msg,
int (*callbackfn)(void *, const char *), void (*freefn)(void *), int (*callbackfn)(void *, const char *), void (*freefn)(void *),
void *data, int flags) void *data, int flags)
{ {
int keys;
status_message_clear(c); status_message_clear(c);
status_prompt_clear(c); status_prompt_clear(c);
@ -605,9 +607,11 @@ status_prompt_set(struct client *c, const char *msg,
c->prompt_flags = flags; c->prompt_flags = flags;
mode_key_init(&c->prompt_mdata, keys = options_get_number(&c->session->options, "status-keys");
options_get_number(&c->session->options, "status-keys"), if (keys == MODEKEY_EMACS)
MODEKEY_CANEDIT); 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->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
@ -727,32 +731,32 @@ status_prompt_key(struct client *c, int key)
size = strlen(c->prompt_buffer); size = strlen(c->prompt_buffer);
switch (mode_key_lookup(&c->prompt_mdata, key)) { switch (mode_key_lookup(&c->prompt_mdata, key)) {
case MODEKEYCMD_LEFT: case MODEKEYEDIT_CURSORLEFT:
if (c->prompt_index > 0) { if (c->prompt_index > 0) {
c->prompt_index--; c->prompt_index--;
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
break; break;
case MODEKEYCMD_RIGHT: case MODEKEYEDIT_SWITCHMODEAPPEND:
case MODEKEYEDIT_CURSORRIGHT:
if (c->prompt_index < size) { if (c->prompt_index < size) {
c->prompt_index++; c->prompt_index++;
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
break; break;
case MODEKEYCMD_STARTOFLINE: case MODEKEYEDIT_STARTOFLINE:
case MODEKEYCMD_BACKTOINDENTATION:
if (c->prompt_index != 0) { if (c->prompt_index != 0) {
c->prompt_index = 0; c->prompt_index = 0;
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
break; break;
case MODEKEYCMD_ENDOFLINE: case MODEKEYEDIT_ENDOFLINE:
if (c->prompt_index != size) { if (c->prompt_index != size) {
c->prompt_index = size; c->prompt_index = size;
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
break; break;
case MODEKEYCMD_COMPLETE: case MODEKEYEDIT_COMPLETE:
if (*c->prompt_buffer == '\0') if (*c->prompt_buffer == '\0')
break; break;
@ -800,7 +804,7 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
break; break;
case MODEKEYCMD_BACKSPACE: case MODEKEYEDIT_BACKSPACE:
if (c->prompt_index != 0) { if (c->prompt_index != 0) {
if (c->prompt_index == size) if (c->prompt_index == size)
c->prompt_buffer[--c->prompt_index] = '\0'; c->prompt_buffer[--c->prompt_index] = '\0';
@ -813,7 +817,7 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
break; break;
case MODEKEYCMD_DELETE: case MODEKEYEDIT_DELETE:
if (c->prompt_index != size) { if (c->prompt_index != size) {
memmove(c->prompt_buffer + c->prompt_index, memmove(c->prompt_buffer + c->prompt_index,
c->prompt_buffer + c->prompt_index + 1, c->prompt_buffer + c->prompt_index + 1,
@ -821,13 +825,13 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
break; break;
case MODEKEYCMD_DELETETOENDOFLINE: case MODEKEYEDIT_DELETETOENDOFLINE:
if (c->prompt_index < size) { if (c->prompt_index < size) {
c->prompt_buffer[c->prompt_index] = '\0'; c->prompt_buffer[c->prompt_index] = '\0';
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
break; break;
case MODEKEYCMD_UP: case MODEKEYEDIT_HISTORYUP:
if (server_locked) if (server_locked)
break; break;
@ -845,7 +849,7 @@ status_prompt_key(struct client *c, int key)
c->prompt_index = strlen(c->prompt_buffer); c->prompt_index = strlen(c->prompt_buffer);
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
break; break;
case MODEKEYCMD_DOWN: case MODEKEYEDIT_HISTORYDOWN:
if (server_locked) if (server_locked)
break; break;
@ -864,7 +868,7 @@ status_prompt_key(struct client *c, int key)
c->prompt_index = strlen(c->prompt_buffer); c->prompt_index = strlen(c->prompt_buffer);
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
break; break;
case MODEKEYCMD_PASTE: case MODEKEYEDIT_PASTE:
if ((pb = paste_get_top(&c->session->buffers)) == NULL) if ((pb = paste_get_top(&c->session->buffers)) == NULL)
break; break;
if ((last = strchr(pb->data, '\n')) == NULL) if ((last = strchr(pb->data, '\n')) == NULL)
@ -886,7 +890,7 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
break; break;
case MODEKEYCMD_CHOOSE: case MODEKEYEDIT_ENTER:
if (*c->prompt_buffer != '\0') { if (*c->prompt_buffer != '\0') {
status_prompt_add_history(c); status_prompt_add_history(c);
if (c->prompt_callbackfn( if (c->prompt_callbackfn(
@ -895,11 +899,11 @@ status_prompt_key(struct client *c, int key)
break; break;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case MODEKEYCMD_QUIT: case MODEKEYEDIT_CANCEL:
if (c->prompt_callbackfn(c->prompt_data, NULL) == 0) if (c->prompt_callbackfn(c->prompt_data, NULL) == 0)
status_prompt_clear(c); status_prompt_clear(c);
break; break;
case MODEKEYCMD_OTHERKEY: case MODEKEY_OTHER:
if (key < 32 || key > 126) if (key < 32 || key > 126)
break; break;
c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 2); c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 2);

100
tmux.h
View File

@ -358,40 +358,71 @@ struct msg_unlock_data {
/* Editing keys. */ /* Editing keys. */
enum mode_key_cmd { enum mode_key_cmd {
MODEKEYCMD_BACKSPACE = 0x1000, MODEKEY_NONE,
MODEKEYCMD_BACKTOINDENTATION, MODEKEY_OTHER,
MODEKEYCMD_CHOOSE,
MODEKEYCMD_CLEARSELECTION, /* Editing keys. */
MODEKEYCMD_COMPLETE, MODEKEYEDIT_BACKSPACE,
MODEKEYCMD_COPYSELECTION, MODEKEYEDIT_CANCEL,
MODEKEYCMD_DELETE, MODEKEYEDIT_COMPLETE,
MODEKEYCMD_DELETETOENDOFLINE, MODEKEYEDIT_CURSORLEFT,
MODEKEYCMD_DOWN, MODEKEYEDIT_CURSORRIGHT,
MODEKEYCMD_ENDOFLINE, MODEKEYEDIT_DELETE,
MODEKEYCMD_LEFT, MODEKEYEDIT_DELETETOENDOFLINE,
MODEKEYCMD_NEXTPAGE, MODEKEYEDIT_ENDOFLINE,
MODEKEYCMD_NEXTWORD, MODEKEYEDIT_ENTER,
MODEKEYCMD_NONE, MODEKEYEDIT_HISTORYDOWN,
MODEKEYCMD_OTHERKEY, MODEKEYEDIT_HISTORYUP,
MODEKEYCMD_PASTE, MODEKEYEDIT_PASTE,
MODEKEYCMD_PREVIOUSPAGE, MODEKEYEDIT_STARTOFLINE,
MODEKEYCMD_PREVIOUSWORD, MODEKEYEDIT_SWITCHMODE,
MODEKEYCMD_QUIT, MODEKEYEDIT_SWITCHMODEAPPEND,
MODEKEYCMD_RIGHT,
MODEKEYCMD_STARTOFLINE, /* Menu (choice) keys. */
MODEKEYCMD_STARTSELECTION, MODEKEYCHOICE_CANCEL,
MODEKEYCMD_UP, 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 { struct mode_key_data {
int type; const struct mode_key_entry *table;
int mode;
int flags;
#define MODEKEY_EDITMODE 0x1
#define MODEKEY_CANEDIT 0x2
#define MODEKEY_CHOOSEMODE 0x4
}; };
#define MODEKEY_EMACS 0 #define MODEKEY_EMACS 0
#define MODEKEY_VI 1 #define MODEKEY_VI 1
@ -1032,7 +1063,14 @@ void sighandler(int);
int load_cfg(const char *, char **x); int load_cfg(const char *, char **x);
/* mode-key.c */ /* 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); enum mode_key_cmd mode_key_lookup(struct mode_key_data *, int);
/* options.c */ /* options.c */

View File

@ -109,6 +109,7 @@ window_choose_init(struct window_pane *wp)
{ {
struct window_choose_mode_data *data; struct window_choose_mode_data *data;
struct screen *s; struct screen *s;
int keys;
wp->modedata = data = xmalloc(sizeof *data); wp->modedata = data = xmalloc(sizeof *data);
@ -124,9 +125,11 @@ window_choose_init(struct window_pane *wp)
s->mode &= ~MODE_CURSOR; s->mode &= ~MODE_CURSOR;
s->mode |= MODE_MOUSE; s->mode |= MODE_MOUSE;
mode_key_init(&data->mdata, keys = options_get_number(&wp->window->options, "mode-keys");
options_get_number(&wp->window->options, "mode-keys"), if (keys == MODEKEY_EMACS)
MODEKEY_CHOOSEMODE); mode_key_init(&data->mdata, mode_key_emacs_choice);
else
mode_key_init(&data->mdata, mode_key_vi_choice);
return (s); return (s);
} }
@ -174,16 +177,16 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key)
items = ARRAY_LENGTH(&data->list); items = ARRAY_LENGTH(&data->list);
switch (mode_key_lookup(&data->mdata, key)) { switch (mode_key_lookup(&data->mdata, key)) {
case MODEKEYCMD_QUIT: case MODEKEYCHOICE_CANCEL:
data->callbackfn(data->data, -1); data->callbackfn(data->data, -1);
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
break; break;
case MODEKEYCMD_CHOOSE: case MODEKEYCHOICE_CHOOSE:
item = &ARRAY_ITEM(&data->list, data->selected); item = &ARRAY_ITEM(&data->list, data->selected);
data->callbackfn(data->data, item->idx); data->callbackfn(data->data, item->idx);
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
break; break;
case MODEKEYCMD_UP: case MODEKEYCHOICE_UP:
if (items == 0) if (items == 0)
break; break;
if (data->selected == 0) { 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); screen_write_stop(&ctx);
} }
break; break;
case MODEKEYCMD_DOWN: case MODEKEYCHOICE_DOWN:
if (items == 0) if (items == 0)
break; break;
if (data->selected == items - 1) { if (data->selected == items - 1) {
@ -215,6 +218,7 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key)
break; break;
} }
data->selected++; data->selected++;
if (data->selected >= data->top + screen_size_y(&data->screen)) if (data->selected >= data->top + screen_size_y(&data->screen))
window_choose_scroll_down(wp); window_choose_scroll_down(wp);
else { else {
@ -226,7 +230,7 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key)
screen_write_stop(&ctx); screen_write_stop(&ctx);
} }
break; break;
case MODEKEYCMD_PREVIOUSPAGE: case MODEKEYCHOICE_PAGEUP:
if (data->selected < screen_size_y(s)) { if (data->selected < screen_size_y(s)) {
data->selected = 0; data->selected = 0;
data->top = 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); window_choose_redraw_screen(wp);
break; break;
case MODEKEYCMD_NEXTPAGE: case MODEKEYCHOICE_PAGEDOWN:
data->selected += screen_size_y(s); data->selected += screen_size_y(s);
if (data->selected > items - 1) if (data->selected > items - 1)
data->selected = items - 1; data->selected = items - 1;

View File

@ -94,6 +94,7 @@ window_copy_init(struct window_pane *wp)
struct screen *s; struct screen *s;
struct screen_write_ctx ctx; struct screen_write_ctx ctx;
u_int i; u_int i;
int keys;
wp->modedata = data = xmalloc(sizeof *data); wp->modedata = data = xmalloc(sizeof *data);
data->ox = 0; 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); screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
s->mode |= MODE_MOUSE; s->mode |= MODE_MOUSE;
mode_key_init(&data->mdata, keys = options_get_number(&wp->window->options, "mode-keys");
options_get_number(&wp->window->options, "mode-keys"), 0); 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->cx = data->cx;
s->cy = data->cy; 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; struct screen *s = &data->screen;
switch (mode_key_lookup(&data->mdata, key)) { switch (mode_key_lookup(&data->mdata, key)) {
case MODEKEYCMD_QUIT: case MODEKEYCOPY_QUIT:
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
break; break;
case MODEKEYCMD_LEFT: case MODEKEYCOPY_LEFT:
window_copy_cursor_left(wp); window_copy_cursor_left(wp);
return; return;
case MODEKEYCMD_RIGHT: case MODEKEYCOPY_RIGHT:
window_copy_cursor_right(wp); window_copy_cursor_right(wp);
return; return;
case MODEKEYCMD_UP: case MODEKEYCOPY_UP:
window_copy_cursor_up(wp); window_copy_cursor_up(wp);
return; return;
case MODEKEYCMD_DOWN: case MODEKEYCOPY_DOWN:
window_copy_cursor_down(wp); window_copy_cursor_down(wp);
return; return;
case MODEKEYCMD_PREVIOUSPAGE: case MODEKEYCOPY_PREVIOUSPAGE:
window_copy_pageup(wp); window_copy_pageup(wp);
break; break;
case MODEKEYCMD_NEXTPAGE: case MODEKEYCOPY_NEXTPAGE:
if (data->oy < screen_size_y(s)) if (data->oy < screen_size_y(s))
data->oy = 0; data->oy = 0;
else else
@ -190,33 +194,33 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
window_copy_update_selection(wp); window_copy_update_selection(wp);
window_copy_redraw_screen(wp); window_copy_redraw_screen(wp);
break; break;
case MODEKEYCMD_STARTSELECTION: case MODEKEYCOPY_STARTSELECTION:
window_copy_start_selection(wp); window_copy_start_selection(wp);
window_copy_redraw_screen(wp); window_copy_redraw_screen(wp);
break; break;
case MODEKEYCMD_CLEARSELECTION: case MODEKEYCOPY_CLEARSELECTION:
screen_clear_selection(&data->screen); screen_clear_selection(&data->screen);
window_copy_redraw_screen(wp); window_copy_redraw_screen(wp);
break; break;
case MODEKEYCMD_COPYSELECTION: case MODEKEYCOPY_COPYSELECTION:
if (c != NULL && c->session != NULL) { if (c != NULL && c->session != NULL) {
window_copy_copy_selection(wp, c); window_copy_copy_selection(wp, c);
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
} }
break; break;
case MODEKEYCMD_STARTOFLINE: case MODEKEYCOPY_STARTOFLINE:
window_copy_cursor_start_of_line(wp); window_copy_cursor_start_of_line(wp);
break; break;
case MODEKEYCMD_BACKTOINDENTATION: case MODEKEYCOPY_BACKTOINDENTATION:
window_copy_cursor_back_to_indentation(wp); window_copy_cursor_back_to_indentation(wp);
break; break;
case MODEKEYCMD_ENDOFLINE: case MODEKEYCOPY_ENDOFLINE:
window_copy_cursor_end_of_line(wp); window_copy_cursor_end_of_line(wp);
break; break;
case MODEKEYCMD_NEXTWORD: case MODEKEYCOPY_NEXTWORD:
window_copy_cursor_next_word(wp); window_copy_cursor_next_word(wp);
break; break;
case MODEKEYCMD_PREVIOUSWORD: case MODEKEYCOPY_PREVIOUSWORD:
window_copy_cursor_previous_word(wp); window_copy_cursor_previous_word(wp);
break; break;
default: default:

View File

@ -80,6 +80,7 @@ window_more_init(struct window_pane *wp)
{ {
struct window_more_mode_data *data; struct window_more_mode_data *data;
struct screen *s; struct screen *s;
int keys;
wp->modedata = data = xmalloc(sizeof *data); wp->modedata = data = xmalloc(sizeof *data);
ARRAY_INIT(&data->list); 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); screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
s->mode &= ~MODE_CURSOR; s->mode &= ~MODE_CURSOR;
mode_key_init(&data->mdata, keys = options_get_number(&wp->window->options, "mode-keys");
options_get_number(&wp->window->options, "mode-keys"), 0); 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); return (s);
} }
@ -126,23 +130,23 @@ window_more_key(struct window_pane *wp, unused struct client *c, int key)
struct screen *s = &data->screen; struct screen *s = &data->screen;
switch (mode_key_lookup(&data->mdata, key)) { switch (mode_key_lookup(&data->mdata, key)) {
case MODEKEYCMD_QUIT: case MODEKEYCHOICE_CANCEL:
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
break; break;
case MODEKEYCMD_UP: case MODEKEYCHOICE_UP:
window_more_scroll_up(wp); window_more_scroll_up(wp);
break; break;
case MODEKEYCMD_DOWN: case MODEKEYCHOICE_DOWN:
window_more_scroll_down(wp); window_more_scroll_down(wp);
break; break;
case MODEKEYCMD_PREVIOUSPAGE: case MODEKEYCHOICE_PAGEUP:
if (data->top < screen_size_y(s)) if (data->top < screen_size_y(s))
data->top = 0; data->top = 0;
else else
data->top -= screen_size_y(s); data->top -= screen_size_y(s);
window_more_redraw_screen(wp); window_more_redraw_screen(wp);
break; break;
case MODEKEYCMD_NEXTPAGE: case MODEKEYCHOICE_PAGEDOWN:
if (data->top + screen_size_y(s) > ARRAY_LENGTH(&data->list)) if (data->top + screen_size_y(s) > ARRAY_LENGTH(&data->list))
data->top = ARRAY_LENGTH(&data->list); data->top = ARRAY_LENGTH(&data->list);
else else

View File

@ -63,6 +63,7 @@ window_scroll_init(struct window_pane *wp)
struct screen *s; struct screen *s;
struct screen_write_ctx ctx; struct screen_write_ctx ctx;
u_int i; u_int i;
int keys;
wp->modedata = data = xmalloc(sizeof *data); wp->modedata = data = xmalloc(sizeof *data);
data->ox = 0; 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); screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
s->mode &= ~MODE_CURSOR; s->mode &= ~MODE_CURSOR;
mode_key_init(&data->mdata, keys = options_get_number(&wp->window->options, "mode-keys");
options_get_number(&wp->window->options, "mode-keys"), 0); 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); screen_write_start(&ctx, NULL, s);
for (i = 0; i < screen_size_y(s); i++) 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; struct screen *s = &data->screen;
switch (mode_key_lookup(&data->mdata, key)) { switch (mode_key_lookup(&data->mdata, key)) {
case MODEKEYCMD_QUIT: case MODEKEYCOPY_QUIT:
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
break; break;
case MODEKEYCMD_LEFT: case MODEKEYCOPY_LEFT:
window_scroll_scroll_left(wp); window_scroll_scroll_left(wp);
break; break;
case MODEKEYCMD_RIGHT: case MODEKEYCOPY_RIGHT:
window_scroll_scroll_right(wp); window_scroll_scroll_right(wp);
break; break;
case MODEKEYCMD_UP: case MODEKEYCOPY_UP:
window_scroll_scroll_up(wp); window_scroll_scroll_up(wp);
break; break;
case MODEKEYCMD_DOWN: case MODEKEYCOPY_DOWN:
window_scroll_scroll_down(wp); window_scroll_scroll_down(wp);
break; break;
case MODEKEYCMD_PREVIOUSPAGE: case MODEKEYCOPY_PREVIOUSPAGE:
window_scroll_pageup(wp); window_scroll_pageup(wp);
break; break;
case MODEKEYCMD_NEXTPAGE: case MODEKEYCOPY_NEXTPAGE:
if (data->oy < screen_size_y(s)) if (data->oy < screen_size_y(s))
data->oy = 0; data->oy = 0;
else else