mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
Revamp extended keys support to more closely match xterm and support
mode 2 as well as mode 1. From Stanislav Kljuhhin (GitHub issue 4038). This changes tmux to always request mode 2 from parent terminal, change to an unambiguous internal representation of keys, and adds an option (extended-keys-format) to control the format similar to the xterm(1) formatOtherKeys resource.
This commit is contained in:
parent
de6bce057a
commit
c7e61a01e5
20
format.c
20
format.c
@ -1962,6 +1962,23 @@ format_cb_pane_unseen_changes(struct format_tree *ft)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for pane_key_mode. */
|
||||
static void *
|
||||
format_cb_pane_key_mode(struct format_tree *ft)
|
||||
{
|
||||
if (ft->wp != NULL && ft->wp->screen != NULL) {
|
||||
switch (ft->wp->screen->mode & EXTENDED_KEY_MODES) {
|
||||
case MODE_KEYS_EXTENDED:
|
||||
return (xstrdup("Ext 1"));
|
||||
case MODE_KEYS_EXTENDED_2:
|
||||
return (xstrdup("Ext 2"));
|
||||
default:
|
||||
return (xstrdup("VT10x"));
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for pane_last. */
|
||||
static void *
|
||||
format_cb_pane_last(struct format_tree *ft)
|
||||
@ -2997,6 +3014,9 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "pane_input_off", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_input_off
|
||||
},
|
||||
{ "pane_key_mode", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_key_mode
|
||||
},
|
||||
{ "pane_last", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_last
|
||||
},
|
||||
|
77
key-string.c
77
key-string.c
@ -56,12 +56,47 @@ static const struct {
|
||||
{ "PPage", KEYC_PPAGE|KEYC_IMPLIED_META },
|
||||
{ "PageUp", KEYC_PPAGE|KEYC_IMPLIED_META },
|
||||
{ "PgUp", KEYC_PPAGE|KEYC_IMPLIED_META },
|
||||
{ "Tab", '\011' },
|
||||
{ "BTab", KEYC_BTAB },
|
||||
{ "Space", ' ' },
|
||||
{ "BSpace", KEYC_BSPACE },
|
||||
{ "Enter", '\r' },
|
||||
{ "Escape", '\033' },
|
||||
|
||||
/*
|
||||
* C0 control characters, with the exception of Tab, Enter,
|
||||
* and Esc, should never appear as keys. We still render them,
|
||||
* so to be able to spot them in logs in case of an abnormality.
|
||||
*/
|
||||
{ "[NUL]", C0_NUL },
|
||||
{ "[SOH]", C0_SOH },
|
||||
{ "[STX]", C0_STX },
|
||||
{ "[ETX]", C0_ETX },
|
||||
{ "[EOT]", C0_EOT },
|
||||
{ "[ENQ]", C0_ENQ },
|
||||
{ "[ASC]", C0_ASC },
|
||||
{ "[BEL]", C0_BEL },
|
||||
{ "[BS]", C0_BS },
|
||||
{ "Tab", C0_HT },
|
||||
{ "[LF]", C0_LF },
|
||||
{ "[VT]", C0_VT },
|
||||
{ "[FF]", C0_FF },
|
||||
{ "Enter", C0_CR },
|
||||
{ "[SO]", C0_SO },
|
||||
{ "[SI]", C0_SI },
|
||||
{ "[DLE]", C0_DLE },
|
||||
{ "[DC1]", C0_DC1 },
|
||||
{ "[DC2]", C0_DC2 },
|
||||
{ "[DC3]", C0_DC3 },
|
||||
{ "[DC4]", C0_DC4 },
|
||||
{ "[NAK]", C0_NAK },
|
||||
{ "[SYN]", C0_SYN },
|
||||
{ "[ETB]", C0_ETB },
|
||||
{ "[CAN]", C0_CAN },
|
||||
{ "[EM]", C0_EM },
|
||||
{ "[SUB]", C0_SUB },
|
||||
{ "Escape", C0_ESC },
|
||||
{ "[FS]", C0_FS },
|
||||
{ "[GS]", C0_GS },
|
||||
{ "[RS]", C0_RS },
|
||||
{ "[US]", C0_US },
|
||||
|
||||
/* Arrow keys. */
|
||||
{ "Up", KEYC_UP|KEYC_CURSOR|KEYC_IMPLIED_META },
|
||||
@ -206,7 +241,6 @@ key_string_get_modifiers(const char **string)
|
||||
key_code
|
||||
key_string_lookup_string(const char *string)
|
||||
{
|
||||
static const char *other = "!#()+,-.0123456789:;<=>'\r\t\177`/";
|
||||
key_code key, modifiers;
|
||||
u_int u, i;
|
||||
struct utf8_data ud, *udp;
|
||||
@ -281,26 +315,6 @@ key_string_lookup_string(const char *string)
|
||||
key &= ~KEYC_IMPLIED_META;
|
||||
}
|
||||
|
||||
/* Convert the standard control keys. */
|
||||
if (key <= 127 &&
|
||||
(modifiers & KEYC_CTRL) &&
|
||||
strchr(other, key) == NULL &&
|
||||
key != 9 &&
|
||||
key != 13 &&
|
||||
key != 27) {
|
||||
if (key >= 97 && key <= 122)
|
||||
key -= 96;
|
||||
else if (key >= 64 && key <= 95)
|
||||
key -= 64;
|
||||
else if (key == 32)
|
||||
key = 0;
|
||||
else if (key == 63)
|
||||
key = 127;
|
||||
else
|
||||
return (KEYC_UNKNOWN);
|
||||
modifiers &= ~KEYC_CTRL;
|
||||
}
|
||||
|
||||
return (key|modifiers);
|
||||
}
|
||||
|
||||
@ -324,10 +338,6 @@ key_string_lookup_key(key_code key, int with_flags)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Display C-@ as C-Space. */
|
||||
if ((key & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS)) == 0)
|
||||
key = ' '|KEYC_CTRL;
|
||||
|
||||
/* Fill in the modifiers. */
|
||||
if (key & KEYC_CTRL)
|
||||
strlcat(out, "C-", sizeof out);
|
||||
@ -427,13 +437,8 @@ key_string_lookup_key(key_code key, int with_flags)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check for standard or control key. */
|
||||
if (key <= 32) {
|
||||
if (key == 0 || key > 26)
|
||||
xsnprintf(tmp, sizeof tmp, "C-%c", (int)(64 + key));
|
||||
else
|
||||
xsnprintf(tmp, sizeof tmp, "C-%c", (int)(96 + key));
|
||||
} else if (key >= 32 && key <= 126) {
|
||||
/* Printable ASCII keys. */
|
||||
if (key > 32 && key <= 126) {
|
||||
tmp[0] = key;
|
||||
tmp[1] = '\0';
|
||||
} else if (key == 127)
|
||||
@ -460,8 +465,6 @@ out:
|
||||
strlcat(out, "I", sizeof out);
|
||||
if (saved & KEYC_BUILD_MODIFIERS)
|
||||
strlcat(out, "B", sizeof out);
|
||||
if (saved & KEYC_EXTENDED)
|
||||
strlcat(out, "E", sizeof out);
|
||||
if (saved & KEYC_SENT)
|
||||
strlcat(out, "S", sizeof out);
|
||||
strlcat(out, "]", sizeof out);
|
||||
|
8
menu.c
8
menu.c
@ -335,7 +335,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
|
||||
c->flags |= CLIENT_REDRAWOVERLAY;
|
||||
return (0);
|
||||
case KEYC_PPAGE:
|
||||
case '\002': /* C-b */
|
||||
case 'b'|KEYC_CTRL:
|
||||
if (md->choice < 6)
|
||||
md->choice = 0;
|
||||
else {
|
||||
@ -394,13 +394,13 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
|
||||
}
|
||||
c->flags |= CLIENT_REDRAWOVERLAY;
|
||||
break;
|
||||
case '\006': /* C-f */
|
||||
case 'f'|KEYC_CTRL:
|
||||
break;
|
||||
case '\r':
|
||||
goto chosen;
|
||||
case '\033': /* Escape */
|
||||
case '\003': /* C-c */
|
||||
case '\007': /* C-g */
|
||||
case 'c'|KEYC_CTRL:
|
||||
case 'g'|KEYC_CTRL:
|
||||
case 'q':
|
||||
return (1);
|
||||
}
|
||||
|
14
mode-tree.c
14
mode-tree.c
@ -1088,22 +1088,22 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
switch (*key) {
|
||||
case 'q':
|
||||
case '\033': /* Escape */
|
||||
case '\007': /* C-g */
|
||||
case 'g'|KEYC_CTRL:
|
||||
return (1);
|
||||
case KEYC_UP:
|
||||
case 'k':
|
||||
case KEYC_WHEELUP_PANE:
|
||||
case '\020': /* C-p */
|
||||
case 'p'|KEYC_CTRL:
|
||||
mode_tree_up(mtd, 1);
|
||||
break;
|
||||
case KEYC_DOWN:
|
||||
case 'j':
|
||||
case KEYC_WHEELDOWN_PANE:
|
||||
case '\016': /* C-n */
|
||||
case 'n'|KEYC_CTRL:
|
||||
mode_tree_down(mtd, 1);
|
||||
break;
|
||||
case KEYC_PPAGE:
|
||||
case '\002': /* C-b */
|
||||
case 'b'|KEYC_CTRL:
|
||||
for (i = 0; i < mtd->height; i++) {
|
||||
if (mtd->current == 0)
|
||||
break;
|
||||
@ -1111,7 +1111,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
}
|
||||
break;
|
||||
case KEYC_NPAGE:
|
||||
case '\006': /* C-f */
|
||||
case 'f'|KEYC_CTRL:
|
||||
for (i = 0; i < mtd->height; i++) {
|
||||
if (mtd->current == mtd->line_size - 1)
|
||||
break;
|
||||
@ -1155,7 +1155,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
for (i = 0; i < mtd->line_size; i++)
|
||||
mtd->line_list[i].item->tagged = 0;
|
||||
break;
|
||||
case '\024': /* C-t */
|
||||
case 't'|KEYC_CTRL:
|
||||
for (i = 0; i < mtd->line_size; i++) {
|
||||
if ((mtd->line_list[i].item->parent == NULL &&
|
||||
!mtd->line_list[i].item->no_tag) ||
|
||||
@ -1211,7 +1211,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
break;
|
||||
case '?':
|
||||
case '/':
|
||||
case '\023': /* C-s */
|
||||
case 's'|KEYC_CTRL:
|
||||
mtd->references++;
|
||||
status_prompt_set(c, NULL, "(search) ", "",
|
||||
mode_tree_search_callback, mode_tree_search_free, mtd,
|
||||
|
2
popup.c
2
popup.c
@ -543,7 +543,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
|
||||
}
|
||||
if ((((pd->flags & (POPUP_CLOSEEXIT|POPUP_CLOSEEXITZERO)) == 0) ||
|
||||
pd->job == NULL) &&
|
||||
(event->key == '\033' || event->key == '\003'))
|
||||
(event->key == '\033' || event->key == ('c'|KEYC_CTRL)))
|
||||
return (1);
|
||||
if (pd->job != NULL) {
|
||||
if (KEYC_IS_MOUSE(event->key)) {
|
||||
|
@ -326,8 +326,9 @@ screen_write_reset(struct screen_write_ctx *ctx)
|
||||
screen_write_scrollregion(ctx, 0, screen_size_y(s) - 1);
|
||||
|
||||
s->mode = MODE_CURSOR|MODE_WRAP;
|
||||
|
||||
if (options_get_number(global_options, "extended-keys") == 2)
|
||||
s->mode |= MODE_KEXTENDED;
|
||||
s->mode = (s->mode & ~EXTENDED_KEY_MODES)|MODE_KEYS_EXTENDED;
|
||||
|
||||
screen_write_clearscreen(ctx, 8);
|
||||
screen_write_set_cursor(ctx, 0, 0);
|
||||
|
9
screen.c
9
screen.c
@ -107,8 +107,9 @@ screen_reinit(struct screen *s)
|
||||
s->rlower = screen_size_y(s) - 1;
|
||||
|
||||
s->mode = MODE_CURSOR|MODE_WRAP|(s->mode & MODE_CRLF);
|
||||
|
||||
if (options_get_number(global_options, "extended-keys") == 2)
|
||||
s->mode |= MODE_KEXTENDED;
|
||||
s->mode = (s->mode & ~EXTENDED_KEY_MODES)|MODE_KEYS_EXTENDED;
|
||||
|
||||
if (s->saved_grid != NULL)
|
||||
screen_alternate_off(s, NULL, 0);
|
||||
@ -714,8 +715,10 @@ screen_mode_to_string(int mode)
|
||||
strlcat(tmp, "ORIGIN,", sizeof tmp);
|
||||
if (mode & MODE_CRLF)
|
||||
strlcat(tmp, "CRLF,", sizeof tmp);
|
||||
if (mode & MODE_KEXTENDED)
|
||||
strlcat(tmp, "KEXTENDED,", sizeof tmp);
|
||||
if (mode & MODE_KEYS_EXTENDED)
|
||||
strlcat(tmp, "KEYS_EXTENDED,", sizeof tmp);
|
||||
if (mode & MODE_KEYS_EXTENDED_2)
|
||||
strlcat(tmp, "KEYS_EXTENDED_2,", sizeof tmp);
|
||||
tmp[strlen(tmp) - 1] = '\0';
|
||||
return (tmp);
|
||||
}
|
||||
|
72
status.c
72
status.c
@ -839,19 +839,19 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
|
||||
{
|
||||
if (c->prompt_mode == PROMPT_ENTRY) {
|
||||
switch (key) {
|
||||
case '\001': /* C-a */
|
||||
case '\003': /* C-c */
|
||||
case '\005': /* C-e */
|
||||
case '\007': /* C-g */
|
||||
case '\010': /* C-h */
|
||||
case 'a'|KEYC_CTRL:
|
||||
case 'c'|KEYC_CTRL:
|
||||
case 'e'|KEYC_CTRL:
|
||||
case 'g'|KEYC_CTRL:
|
||||
case 'h'|KEYC_CTRL:
|
||||
case '\011': /* Tab */
|
||||
case '\013': /* C-k */
|
||||
case '\016': /* C-n */
|
||||
case '\020': /* C-p */
|
||||
case '\024': /* C-t */
|
||||
case '\025': /* C-u */
|
||||
case '\027': /* C-w */
|
||||
case '\031': /* C-y */
|
||||
case 'k'|KEYC_CTRL:
|
||||
case 'n'|KEYC_CTRL:
|
||||
case 'p'|KEYC_CTRL:
|
||||
case 't'|KEYC_CTRL:
|
||||
case 'u'|KEYC_CTRL:
|
||||
case 'w'|KEYC_CTRL:
|
||||
case 'y'|KEYC_CTRL:
|
||||
case '\n':
|
||||
case '\r':
|
||||
case KEYC_LEFT|KEYC_CTRL:
|
||||
@ -890,7 +890,7 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
|
||||
case 'S':
|
||||
c->prompt_mode = PROMPT_ENTRY;
|
||||
c->flags |= CLIENT_REDRAWSTATUS;
|
||||
*new_key = '\025'; /* C-u */
|
||||
*new_key = 'u'|KEYC_CTRL;
|
||||
return (1);
|
||||
case 'i':
|
||||
case '\033': /* Escape */
|
||||
@ -911,7 +911,7 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
|
||||
return (1);
|
||||
case 'C':
|
||||
case 'D':
|
||||
*new_key = '\013'; /* C-k */
|
||||
*new_key = 'k'|KEYC_CTRL;
|
||||
return (1);
|
||||
case KEYC_BSPACE:
|
||||
case 'X':
|
||||
@ -924,7 +924,7 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
|
||||
*new_key = 'B'|KEYC_VI;
|
||||
return (1);
|
||||
case 'd':
|
||||
*new_key = '\025'; /* C-u */
|
||||
*new_key = 'u'|KEYC_CTRL;
|
||||
return (1);
|
||||
case 'e':
|
||||
*new_key = 'e'|KEYC_VI;
|
||||
@ -939,10 +939,10 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
|
||||
*new_key = 'W'|KEYC_VI;
|
||||
return (1);
|
||||
case 'p':
|
||||
*new_key = '\031'; /* C-y */
|
||||
*new_key = 'y'|KEYC_CTRL;
|
||||
return (1);
|
||||
case 'q':
|
||||
*new_key = '\003'; /* C-c */
|
||||
*new_key = 'c'|KEYC_CTRL;
|
||||
return (1);
|
||||
case 's':
|
||||
case KEYC_DC:
|
||||
@ -966,8 +966,8 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
|
||||
case 'k':
|
||||
*new_key = KEYC_UP;
|
||||
return (1);
|
||||
case '\010' /* C-h */:
|
||||
case '\003' /* C-c */:
|
||||
case 'h'|KEYC_CTRL:
|
||||
case 'c'|KEYC_CTRL:
|
||||
case '\n':
|
||||
case '\r':
|
||||
return (1);
|
||||
@ -1263,28 +1263,28 @@ status_prompt_key(struct client *c, key_code key)
|
||||
process_key:
|
||||
switch (key) {
|
||||
case KEYC_LEFT:
|
||||
case '\002': /* C-b */
|
||||
case 'b'|KEYC_CTRL:
|
||||
if (c->prompt_index > 0) {
|
||||
c->prompt_index--;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case KEYC_RIGHT:
|
||||
case '\006': /* C-f */
|
||||
case 'f'|KEYC_CTRL:
|
||||
if (c->prompt_index < size) {
|
||||
c->prompt_index++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case KEYC_HOME:
|
||||
case '\001': /* C-a */
|
||||
case 'a'|KEYC_CTRL:
|
||||
if (c->prompt_index != 0) {
|
||||
c->prompt_index = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case KEYC_END:
|
||||
case '\005': /* C-e */
|
||||
case 'e'|KEYC_CTRL:
|
||||
if (c->prompt_index != size) {
|
||||
c->prompt_index = size;
|
||||
break;
|
||||
@ -1295,7 +1295,7 @@ process_key:
|
||||
goto changed;
|
||||
break;
|
||||
case KEYC_BSPACE:
|
||||
case '\010': /* C-h */
|
||||
case 'h'|KEYC_CTRL:
|
||||
if (c->prompt_index != 0) {
|
||||
if (c->prompt_index == size)
|
||||
c->prompt_buffer[--c->prompt_index].size = 0;
|
||||
@ -1310,7 +1310,7 @@ process_key:
|
||||
}
|
||||
break;
|
||||
case KEYC_DC:
|
||||
case '\004': /* C-d */
|
||||
case 'd'|KEYC_CTRL:
|
||||
if (c->prompt_index != size) {
|
||||
memmove(c->prompt_buffer + c->prompt_index,
|
||||
c->prompt_buffer + c->prompt_index + 1,
|
||||
@ -1319,17 +1319,17 @@ process_key:
|
||||
goto changed;
|
||||
}
|
||||
break;
|
||||
case '\025': /* C-u */
|
||||
case 'u'|KEYC_CTRL:
|
||||
c->prompt_buffer[0].size = 0;
|
||||
c->prompt_index = 0;
|
||||
goto changed;
|
||||
case '\013': /* C-k */
|
||||
case 'k'|KEYC_CTRL:
|
||||
if (c->prompt_index < size) {
|
||||
c->prompt_buffer[c->prompt_index].size = 0;
|
||||
goto changed;
|
||||
}
|
||||
break;
|
||||
case '\027': /* C-w */
|
||||
case 'w'|KEYC_CTRL:
|
||||
separators = options_get_string(oo, "word-separators");
|
||||
idx = c->prompt_index;
|
||||
|
||||
@ -1397,7 +1397,7 @@ process_key:
|
||||
status_prompt_backward_word(c, separators);
|
||||
goto changed;
|
||||
case KEYC_UP:
|
||||
case '\020': /* C-p */
|
||||
case 'p'|KEYC_CTRL:
|
||||
histstr = status_prompt_up_history(c->prompt_hindex,
|
||||
c->prompt_type);
|
||||
if (histstr == NULL)
|
||||
@ -1407,7 +1407,7 @@ process_key:
|
||||
c->prompt_index = utf8_strlen(c->prompt_buffer);
|
||||
goto changed;
|
||||
case KEYC_DOWN:
|
||||
case '\016': /* C-n */
|
||||
case 'n'|KEYC_CTRL:
|
||||
histstr = status_prompt_down_history(c->prompt_hindex,
|
||||
c->prompt_type);
|
||||
if (histstr == NULL)
|
||||
@ -1416,11 +1416,11 @@ process_key:
|
||||
c->prompt_buffer = utf8_fromcstr(histstr);
|
||||
c->prompt_index = utf8_strlen(c->prompt_buffer);
|
||||
goto changed;
|
||||
case '\031': /* C-y */
|
||||
case 'y'|KEYC_CTRL:
|
||||
if (status_prompt_paste(c))
|
||||
goto changed;
|
||||
break;
|
||||
case '\024': /* C-t */
|
||||
case 't'|KEYC_CTRL:
|
||||
idx = c->prompt_index;
|
||||
if (idx < size)
|
||||
idx++;
|
||||
@ -1443,12 +1443,12 @@ process_key:
|
||||
free(s);
|
||||
break;
|
||||
case '\033': /* Escape */
|
||||
case '\003': /* C-c */
|
||||
case '\007': /* C-g */
|
||||
case 'c'|KEYC_CTRL:
|
||||
case 'g'|KEYC_CTRL:
|
||||
if (c->prompt_inputcb(c, c->prompt_data, NULL, 1) == 0)
|
||||
status_prompt_clear(c);
|
||||
break;
|
||||
case '\022': /* C-r */
|
||||
case 'r'|KEYC_CTRL:
|
||||
if (~c->prompt_flags & PROMPT_INCREMENTAL)
|
||||
break;
|
||||
if (c->prompt_buffer[0].size == 0) {
|
||||
@ -1459,7 +1459,7 @@ process_key:
|
||||
} else
|
||||
prefix = '-';
|
||||
goto changed;
|
||||
case '\023': /* C-s */
|
||||
case 's'|KEYC_CTRL:
|
||||
if (~c->prompt_flags & PROMPT_INCREMENTAL)
|
||||
break;
|
||||
if (c->prompt_buffer[0].size == 0) {
|
||||
|
66
tmux.1
66
tmux.1
@ -3733,6 +3733,10 @@ Note that aliases are expanded when a command is parsed rather than when it is
|
||||
executed, so binding an alias with
|
||||
.Ic bind-key
|
||||
will bind the expanded form.
|
||||
.It Ic copy-command Ar shell-command
|
||||
Give the command to pipe to if the
|
||||
.Ic copy-pipe
|
||||
copy mode command is used without arguments.
|
||||
.It Ic default-terminal Ar terminal
|
||||
Set the default terminal for new windows created in this session - the
|
||||
default value of the
|
||||
@ -3746,10 +3750,6 @@ be set to
|
||||
.Ql screen ,
|
||||
.Ql tmux
|
||||
or a derivative of them.
|
||||
.It Ic copy-command Ar shell-command
|
||||
Give the command to pipe to if the
|
||||
.Ic copy-pipe
|
||||
copy mode command is used without arguments.
|
||||
.It Ic escape-time Ar time
|
||||
Set the time in milliseconds for which
|
||||
.Nm
|
||||
@ -3771,22 +3771,53 @@ If enabled, the server will exit when there are no attached clients.
|
||||
.It Xo Ic extended-keys
|
||||
.Op Ic on | off | always
|
||||
.Xc
|
||||
When
|
||||
.Ic on
|
||||
or
|
||||
.Ic always ,
|
||||
the escape sequence to enable extended keys is sent to the terminal, if
|
||||
.Nm
|
||||
knows that it is supported.
|
||||
.Nm
|
||||
always recognises extended keys itself.
|
||||
If this option is
|
||||
Controls how modified keys (keys pressed together with Control, Meta, or Shift)
|
||||
are reported.
|
||||
This is the equivalent of the
|
||||
.Ic modifyOtherKeys
|
||||
.Xr xterm 1
|
||||
resource.
|
||||
.Pp
|
||||
When set to
|
||||
.Ic on ,
|
||||
.Nm
|
||||
will only forward extended keys to applications when they request them; if
|
||||
the program inside the pane can request one of two modes: mode 1 which changes
|
||||
the sequence for only keys which lack an existing well-known representation; or
|
||||
mode 2 which changes the sequence for all keys.
|
||||
When set to
|
||||
.Ic always ,
|
||||
mode 1 output is forced and the program cannot change it.
|
||||
When set to
|
||||
.Ic off ,
|
||||
this feature is disabled and only standard keys are reported.
|
||||
.Pp
|
||||
.Nm
|
||||
will always forward the keys.
|
||||
will always request extended keys itself if the terminal supports them.
|
||||
See also the
|
||||
.Ic extkeys
|
||||
feature for the
|
||||
.Ic terminal-features
|
||||
option, the
|
||||
.Ic extended-keys-format
|
||||
option and the
|
||||
.Ic pane_key_mode
|
||||
variable.
|
||||
.It Xo Ic extended-keys-format
|
||||
.Op Ic csi-u | xterm
|
||||
.Xc
|
||||
Selects one of the two possible formats for reporting modified keys to
|
||||
applications.
|
||||
This is the equivalent of the
|
||||
.Ic formatOtherKeys
|
||||
.Xr xterm 1
|
||||
resource.
|
||||
For example, C-S-a will be reported as
|
||||
.Ql ^[[27;6;65~
|
||||
when set to
|
||||
.Ic xterm ,
|
||||
and as
|
||||
.Ql ^[[65;6u
|
||||
when set to
|
||||
.Ic csi-u .
|
||||
.It Xo Ic focus-events
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
@ -5512,6 +5543,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "pane_in_mode" Ta "" Ta "1 if pane is in a mode"
|
||||
.It Li "pane_index" Ta "#P" Ta "Index of pane"
|
||||
.It Li "pane_input_off" Ta "" Ta "1 if input to pane is disabled"
|
||||
.It Li "pane_key_mode" Ta "" Ta "Extended key reporting mode in this pane"
|
||||
.It Li "pane_last" Ta "" Ta "1 if last pane"
|
||||
.It Li "pane_left" Ta "" Ta "Left of pane"
|
||||
.It Li "pane_marked" Ta "" Ta "1 if this is the marked pane"
|
||||
|
43
tmux.h
43
tmux.h
@ -138,8 +138,7 @@ struct winlink;
|
||||
#define KEYC_IMPLIED_META 0x08000000000000ULL
|
||||
#define KEYC_BUILD_MODIFIERS 0x10000000000000ULL
|
||||
#define KEYC_VI 0x20000000000000ULL
|
||||
#define KEYC_EXTENDED 0x40000000000000ULL
|
||||
#define KEYC_SENT 0x80000000000000ULL
|
||||
#define KEYC_SENT 0x40000000000000ULL
|
||||
|
||||
/* Masks for key bits. */
|
||||
#define KEYC_MASK_MODIFIERS 0x00f00000000000ULL
|
||||
@ -187,6 +186,42 @@ struct winlink;
|
||||
*/
|
||||
typedef unsigned long long key_code;
|
||||
|
||||
/* C0 control characters */
|
||||
enum {
|
||||
C0_NUL,
|
||||
C0_SOH,
|
||||
C0_STX,
|
||||
C0_ETX,
|
||||
C0_EOT,
|
||||
C0_ENQ,
|
||||
C0_ASC,
|
||||
C0_BEL,
|
||||
C0_BS,
|
||||
C0_HT,
|
||||
C0_LF,
|
||||
C0_VT,
|
||||
C0_FF,
|
||||
C0_CR,
|
||||
C0_SO,
|
||||
C0_SI,
|
||||
C0_DLE,
|
||||
C0_DC1,
|
||||
C0_DC2,
|
||||
C0_DC3,
|
||||
C0_DC4,
|
||||
C0_NAK,
|
||||
C0_SYN,
|
||||
C0_ETB,
|
||||
C0_CAN,
|
||||
C0_EM,
|
||||
C0_SUB,
|
||||
C0_ESC,
|
||||
C0_FS,
|
||||
C0_GS,
|
||||
C0_RS,
|
||||
C0_US
|
||||
};
|
||||
|
||||
/* Special key codes. */
|
||||
enum {
|
||||
/* Focus events. */
|
||||
@ -582,14 +617,16 @@ enum tty_code_code {
|
||||
#define MODE_MOUSE_ALL 0x1000
|
||||
#define MODE_ORIGIN 0x2000
|
||||
#define MODE_CRLF 0x4000
|
||||
#define MODE_KEXTENDED 0x8000
|
||||
#define MODE_KEYS_EXTENDED 0x8000
|
||||
#define MODE_CURSOR_VERY_VISIBLE 0x10000
|
||||
#define MODE_CURSOR_BLINKING_SET 0x20000
|
||||
#define MODE_KEYS_EXTENDED_2 0x40000
|
||||
|
||||
#define ALL_MODES 0xffffff
|
||||
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
|
||||
#define MOTION_MOUSE_MODES (MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
|
||||
#define CURSOR_MODES (MODE_CURSOR|MODE_CURSOR_BLINKING|MODE_CURSOR_VERY_VISIBLE)
|
||||
#define EXTENDED_KEY_MODES (MODE_KEYS_EXTENDED|MODE_KEYS_EXTENDED_2)
|
||||
|
||||
/* Mouse protocol constants. */
|
||||
#define MOUSE_PARAM_MAX 0xff
|
||||
|
@ -227,7 +227,7 @@ static const struct tty_feature tty_feature_sync = {
|
||||
|
||||
/* Terminal supports extended keys. */
|
||||
static const char *const tty_feature_extkeys_capabilities[] = {
|
||||
"Eneks=\\E[>4;1m",
|
||||
"Eneks=\\E[>4;2m",
|
||||
"Dseks=\\E[>4m",
|
||||
NULL
|
||||
};
|
||||
|
58
tty-keys.c
58
tty-keys.c
@ -664,7 +664,7 @@ tty_keys_next(struct tty *tty)
|
||||
size_t len, size;
|
||||
cc_t bspace;
|
||||
int delay, expired = 0, n;
|
||||
key_code key;
|
||||
key_code key, onlykey;
|
||||
struct mouse_event m = { 0 };
|
||||
struct key_event *event;
|
||||
|
||||
@ -801,6 +801,26 @@ first_key:
|
||||
key = (u_char)buf[0];
|
||||
size = 1;
|
||||
}
|
||||
|
||||
/* C-Space is special. */
|
||||
if ((key & KEYC_MASK_KEY) == C0_NUL)
|
||||
key = ' ' | KEYC_CTRL | (key & KEYC_META);
|
||||
|
||||
/*
|
||||
* Fix up all C0 control codes that don't have a dedicated key into
|
||||
* corresponding Ctrl keys. Convert characters in the A-Z range into
|
||||
* lowercase, so ^A becomes a|CTRL.
|
||||
*/
|
||||
onlykey = key & KEYC_MASK_KEY;
|
||||
if (onlykey < 0x20 && onlykey != C0_BS &&
|
||||
onlykey != C0_HT && onlykey != C0_CR &&
|
||||
onlykey != C0_ESC) {
|
||||
onlykey |= 0x40;
|
||||
if (onlykey >= 'A' && onlykey <= 'Z')
|
||||
onlykey |= 0x20;
|
||||
key = onlykey | KEYC_CTRL | (key & KEYC_META);
|
||||
}
|
||||
|
||||
goto complete_key;
|
||||
|
||||
partial_key:
|
||||
@ -910,7 +930,6 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
|
||||
char tmp[64];
|
||||
cc_t bspace;
|
||||
key_code nkey;
|
||||
key_code onlykey;
|
||||
struct utf8_data ud;
|
||||
utf8_char uc;
|
||||
|
||||
@ -974,7 +993,13 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
|
||||
/* Update the modifiers. */
|
||||
if (modifiers > 0) {
|
||||
modifiers--;
|
||||
if (modifiers & 1)
|
||||
/*
|
||||
* The Shift modifier may not be reported in some input modes,
|
||||
* which is unfortunate, as in general case determining if a
|
||||
* character is shifted or not requires knowing the input
|
||||
* keyboard layout. So we only fix up the trivial case.
|
||||
*/
|
||||
if (modifiers & 1 || (nkey >= 'A' && nkey <= 'Z'))
|
||||
nkey |= KEYC_SHIFT;
|
||||
if (modifiers & 2)
|
||||
nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Alt */
|
||||
@ -984,34 +1009,15 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
|
||||
nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Meta */
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't allow both KEYC_CTRL and as an implied modifier. Also convert
|
||||
* C-X into C-x and so on.
|
||||
*/
|
||||
if (nkey & KEYC_CTRL) {
|
||||
onlykey = (nkey & KEYC_MASK_KEY);
|
||||
if (onlykey < 32 &&
|
||||
onlykey != 9 &&
|
||||
onlykey != 13 &&
|
||||
onlykey != 27)
|
||||
/* nothing */;
|
||||
else if (onlykey >= 97 && onlykey <= 122)
|
||||
onlykey -= 96;
|
||||
else if (onlykey >= 64 && onlykey <= 95)
|
||||
onlykey -= 64;
|
||||
else if (onlykey == 32)
|
||||
onlykey = 0;
|
||||
else if (onlykey == 63)
|
||||
onlykey = 127;
|
||||
else
|
||||
onlykey |= KEYC_CTRL;
|
||||
nkey = onlykey|((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL);
|
||||
}
|
||||
/* Convert S-Tab into Backtab. */
|
||||
if ((nkey & KEYC_MASK_KEY) == '\011' && (nkey & KEYC_SHIFT))
|
||||
nkey = KEYC_BTAB | (nkey & ~KEYC_MASK_KEY & ~KEYC_SHIFT);
|
||||
|
||||
if (log_get_level() != 0) {
|
||||
log_debug("%s: extended key %.*s is %llx (%s)", c->name,
|
||||
(int)*size, buf, nkey, key_string_lookup_key(nkey, 1));
|
||||
}
|
||||
|
||||
*key = nkey;
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user