Merge branch 'master' into sixel

pull/3363/head
Nicholas Marriott 2020-02-20 20:37:32 +00:00
commit 90dc05191c
18 changed files with 238 additions and 149 deletions

View File

@ -14,8 +14,8 @@ Before opening an issue, please ensure that:
- Your question or issue is not covered [in the
manual](https://man.openbsd.org/tmux.1) (run `man tmux`).
- Your problem is not mentioned in the [CHANGES
file](https://raw.githubusercontent.com/tmux/tmux/master/CHANGES) file.
- Your problem is not mentioned in [the CHANGES
file](https://raw.githubusercontent.com/tmux/tmux/master/CHANGES).
- Nobody else has opened the same issue recently.

1
.github/FUNDING.yml vendored
View File

@ -1 +1,2 @@
github: nicm
liberapay: tmux

10
.github/lock.yml vendored Normal file
View File

@ -0,0 +1,10 @@
daysUntilLock: 180
skipCreatedBefore: false
exemptLabels: []
lockLabel: false
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
setLockReason: false
#only: issues

58
CHANGES
View File

@ -1,4 +1,8 @@
CHANGES FROM 3.0 to X.X
CHANGES FROM 3.1 TO 3.2
XXX
CHANGES FROM 3.0a to 3.1
* Add support for adding a note to a key binding (with bind-key -N) and use
this to add descriptions to the default key bindings. A new -N flag to
@ -10,7 +14,7 @@ CHANGES FROM 3.0 to X.X
* Add support for the iTerm2 DSR 1337 sequence to get the terminal version.
* Treat plausible but invalid keys (like C-BSpace) as literal like any other
unrecognised string passed to send-keys
unrecognised string passed to send-keys.
* Detect iTerm2 and enable use of DECSLRM (much faster with horizontally split
windows).
@ -42,11 +46,6 @@ CHANGES FROM 3.0 to X.X
* Add push-default to status-left and status-right in status-format[0].
* Add -F flag to send-keys to expand formats in search-backward and forward
copy mode commands and copy_cursor_word and copy_cursor_line formats for word
and line at cursor in copy mode. Use for default # and * binding with vi(1)
keys.
* Do not clear search marks on cursor movement with vi(1) keys.
* Add p format modifier for padding to width and allow multiple substitutions
@ -54,32 +53,9 @@ CHANGES FROM 3.0 to X.X
* Add -f for full size to join-pane (like split-window).
* Handle OSC 7 (a VTE extension) and put the result in a new format (pane_path).
* Change new-session -A without a session name (that is, no -s option also) to
attach to the best existing session like attach-session rather than creating
a new one.
* Add an option to set the key sent by backspace for those whose system uses ^H
rather than ^?.
* Add formats for cursor and selection position in copy mode.
* Add support for percentage sizes for resize-pane ("-x 10%"). Also change
split-window and join-pane -l to accept similar percentages and no longer
document -p.
* Turn automatic-rename back on if the rename escape sequence is used with an
empty name.
* Make select-pane -P set window-active-style also to match previous behaviour.
* Do not use bright when emulating 256 colours on an 8 colour terminal because
it is also bold on some terminals.
* Add a "latest" window-size option which tries to size windows based on the
most recently used client. This is now the default.
* Make select-pane -P set window-active-style also to match previous behaviour.
* Do not truncate list-keys output.
@ -92,17 +68,18 @@ CHANGES FROM 3.0 to X.X
-p flag.
* Add -F flag to send-keys to expand formats in search-backward and forward
copy mode commands, this makes it easier to use the cursor_word and
cursor_line formats.
copy mode commands and copy_cursor_word and copy_cursor_line formats for word
and line at cursor in copy mode. Use for default # and * binding with vi(1)
keys.
* Add formats for word and line at cursor position in copy mode.
* Add formats for cursor and selection position in copy mode
* Add formats for cursor and selection position in copy mode.
* Support all the forms of RGB colour strings in OSC sequences rather than
requiring two digits.
* Limit lazy resize to panes in attached sessions only
* Limit lazy resize to panes in attached sessions only.
* Add an option to set the key sent by backspace for those whose system uses ^H
rather than ^?.
@ -111,7 +88,8 @@ CHANGES FROM 3.0 to X.X
attach to the best existing session like attach-session rather than a new
one.
* Change window-size default from smallest to latest.
* Add a "latest" window-size option which tries to size windows based on the
most recently used client. This is now the default.
* Add simple support for OSC 7 (result is available in the pane_path format).
@ -133,7 +111,7 @@ CHANGES FROM 3.0 to X.X
* Add reverse sorting in tree, client and buffer modes.
CHANGES FROM 3.0 to 3.0a
CHANGES FROM 3.0 TO 3.0a
* Do not require REG_STARTEND.
@ -147,7 +125,7 @@ CHANGES FROM 3.0 to 3.0a
* Do not crash when restoring a layout with only one pane.
CHANGES FROM 2.9 to 3.0
CHANGES FROM 2.9 TO 3.0
* Workaround invalid layout strings generated by older tmux versions and add
some additional sanity checks
@ -272,11 +250,11 @@ CHANGES FROM 2.9 to 3.0
* Add the ability to infer an option type (server, session, window) from its
name to show-options (it was already present in set-option).
CHANGES FROM 2.9 to 2.9a
CHANGES FROM 2.9 TO 2.9a
* Fix bugs in select-pane and the main-horizontal and main-vertical layouts.
CHANGES FROM 2.8 to 2.9
CHANGES FROM 2.8 TO 2.9
* Attempt to preserve horizontal cursor position as well as vertical with
reflow.
@ -401,7 +379,7 @@ CHANGES FROM 2.8 to 2.9
moves up, down, left or right and -c returns to automatic cursor
tracking. The position is reset when the current window is changed.
CHANGES FROM 2.7 to 2.8
CHANGES FROM 2.7 TO 2.8
* Make display-panes block the client until a pane is chosen or it
times out.

View File

@ -33,8 +33,8 @@ const struct cmd_entry cmd_bind_key_entry = {
.name = "bind-key",
.alias = "bind",
.args = { "cnrN:T:", 2, -1 },
.usage = "[-cnr] [-T key-table] [-N note] key "
.args = { "nrN:T:", 2, -1 },
.usage = "[-nr] [-T key-table] [-N note] key "
"command [arguments]",
.flags = CMD_AFTERHOOK,

View File

@ -36,8 +36,8 @@ const struct cmd_entry cmd_list_keys_entry = {
.name = "list-keys",
.alias = "lsk",
.args = { "1NP:T:", 0, 1 },
.usage = "[-1N] [-P prefix-string] [-T key-table] [key]",
.args = { "1aNP:T:", 0, 1 },
.usage = "[-1aN] [-P prefix-string] [-T key-table] [key]",
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
.exec = cmd_list_keys_exec
@ -89,7 +89,7 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
struct key_table *table;
struct key_binding *bd;
const char *key;
char *tmp;
char *tmp, *note;
int found = 0;
table = key_bindings_get_table(tablename, 0);
@ -99,19 +99,24 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
while (bd != NULL) {
if ((only != KEYC_UNKNOWN && bd->key != only) ||
KEYC_IS_MOUSE(bd->key) ||
bd->note == NULL) {
(bd->note == NULL && !args_has(args, 'a'))) {
bd = key_bindings_next(table, bd);
continue;
}
found = 1;
key = key_string_lookup_key(bd->key);
if (bd->note == NULL)
note = cmd_list_print(bd->cmdlist, 1);
else
note = xstrdup(bd->note);
tmp = utf8_padcstr(key, keywidth + 1);
if (args_has(args, '1') && c != NULL)
status_message_set(c, "%s%s%s", prefix, tmp, bd->note);
status_message_set(c, "%s%s%s", prefix, tmp, note);
else
cmdq_print(item, "%s%s%s", prefix, tmp, bd->note);
cmdq_print(item, "%s%s%s", prefix, tmp, note);
free(tmp);
free(note);
if (args_has(args, '1'))
break;

View File

@ -197,8 +197,8 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(self->args, 'T')) {
pane_title = format_single(item, args_get(self->args, 'T'),
c, s, wl, wp);
screen_set_title(&wp->base, pane_title);
server_status_window(wp->window);
if (screen_set_title(&wp->base, pane_title))
server_status_window(wp->window);
free(pane_title);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,6 +1,6 @@
# configure.ac
AC_INIT([tmux], next-3.1)
AC_INIT([tmux], next-3.2)
AC_PREREQ([2.60])
AC_CONFIG_AUX_DIR(etc)

View File

@ -895,6 +895,44 @@ format_cb_pane_in_mode(struct format_tree *ft, struct format_entry *fe)
xasprintf(&fe->value, "%u", n);
}
/* Callback for pane_at_top. */
static void
format_cb_pane_at_top(struct format_tree *ft, struct format_entry *fe)
{
struct window_pane *wp = ft->wp;
struct window *w = wp->window;
int status, flag;
if (wp == NULL)
return;
status = options_get_number(w->options, "pane-border-status");
if (status == PANE_STATUS_TOP)
flag = (wp->yoff == 1);
else
flag = (wp->yoff == 0);
xasprintf(&fe->value, "%d", flag);
}
/* Callback for pane_at_bottom. */
static void
format_cb_pane_at_bottom(struct format_tree *ft, struct format_entry *fe)
{
struct window_pane *wp = ft->wp;
struct window *w = wp->window;
int status, flag;
if (wp == NULL)
return;
status = options_get_number(w->options, "pane-border-status");
if (status == PANE_STATUS_BOTTOM)
flag = (wp->yoff + wp->sy == w->sy - 1);
else
flag = (wp->yoff + wp->sy == w->sy);
xasprintf(&fe->value, "%d", flag);
}
/* Callback for cursor_character. */
static void
format_cb_cursor_character(struct format_tree *ft, struct format_entry *fe)
@ -2546,9 +2584,9 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_right", "%u", wp->xoff + wp->sx - 1);
format_add(ft, "pane_bottom", "%u", wp->yoff + wp->sy - 1);
format_add(ft, "pane_at_left", "%d", wp->xoff == 0);
format_add(ft, "pane_at_top", "%d", wp->yoff == 0);
format_add_cb(ft, "pane_at_top", format_cb_pane_at_top);
format_add(ft, "pane_at_right", "%d", wp->xoff + wp->sx == w->sx);
format_add(ft, "pane_at_bottom", "%d", wp->yoff + wp->sy == w->sy);
format_add_cb(ft, "pane_at_bottom", format_cb_pane_at_bottom);
wme = TAILQ_FIRST(&wp->modes);
if (wme != NULL) {

10
input.c
View File

@ -2225,10 +2225,8 @@ input_exit_osc(struct input_ctx *ictx)
switch (option) {
case 0:
case 2:
if (utf8_isvalid(p)) {
screen_set_title(sctx->s, p);
if (screen_set_title(sctx->s, p))
server_status_window(ictx->wp->window);
}
break;
case 4:
input_osc_4(ictx, p);
@ -2286,10 +2284,8 @@ input_exit_apc(struct input_ctx *ictx)
return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
if (!utf8_isvalid(ictx->input_buf))
return;
screen_set_title(sctx->s, ictx->input_buf);
server_status_window(ictx->wp->window);
if (screen_set_title(sctx->s, ictx->input_buf))
server_status_window(ictx->wp->window);
}
/* Rename string started. */

View File

@ -242,53 +242,90 @@ key_string_lookup_string(const char *string)
const char *
key_string_lookup_key(key_code key)
{
static char out[32];
char tmp[8];
u_int i;
struct utf8_data ud;
size_t off;
static char out[32];
char tmp[8];
const char *s;
u_int i;
struct utf8_data ud;
size_t off;
*out = '\0';
/* Literal keys are themselves. */
if (key & KEYC_LITERAL) {
snprintf(out, sizeof out, "%c", (int)(key & 0xff));
return (out);
}
/* Fill in the modifiers. */
if (key & KEYC_CTRL)
strlcat(out, "C-", sizeof out);
if (key & KEYC_ESCAPE)
strlcat(out, "M-", sizeof out);
if (key & KEYC_SHIFT)
strlcat(out, "S-", sizeof out);
key &= KEYC_MASK_KEY;
/* Handle no key. */
if (key == KEYC_NONE)
return ("None");
/* Handle special keys. */
if (key == KEYC_UNKNOWN)
return ("Unknown");
if (key == KEYC_ANY)
return ("Any");
if (key == KEYC_FOCUS_IN)
return ("FocusIn");
if (key == KEYC_FOCUS_OUT)
return ("FocusOut");
if (key == KEYC_PASTE_START)
return ("PasteStart");
if (key == KEYC_PASTE_END)
return ("PasteEnd");
if (key == KEYC_MOUSE)
return ("Mouse");
if (key == KEYC_DRAGGING)
return ("Dragging");
if (key == KEYC_MOUSEMOVE_PANE)
return ("MouseMovePane");
if (key == KEYC_MOUSEMOVE_STATUS)
return ("MouseMoveStatus");
if (key == KEYC_MOUSEMOVE_STATUS_LEFT)
return ("MouseMoveStatusLeft");
if (key == KEYC_MOUSEMOVE_STATUS_RIGHT)
return ("MouseMoveStatusRight");
if (key == KEYC_MOUSEMOVE_BORDER)
return ("MouseMoveBorder");
if (key >= KEYC_USER && key < KEYC_USER + KEYC_NUSER) {
snprintf(out, sizeof out, "User%u", (u_int)(key - KEYC_USER));
return (out);
if (key == KEYC_UNKNOWN) {
s = "Unknown";
goto append;
}
/* Literal keys are themselves. */
if (key & KEYC_LITERAL) {
snprintf(out, sizeof out, "%c", (int)(key & 0xff));
if (key == KEYC_ANY) {
s = "Any";
goto append;
}
if (key == KEYC_FOCUS_IN) {
s = "FocusIn";
goto append;
}
if (key == KEYC_FOCUS_OUT) {
s = "FocusOut";
goto append;
}
if (key == KEYC_PASTE_START) {
s = "PasteStart";
goto append;
}
if (key == KEYC_PASTE_END) {
s = "PasteEnd";
goto append;
}
if (key == KEYC_MOUSE) {
s = "Mouse";
goto append;
}
if (key == KEYC_DRAGGING) {
s = "Dragging";
goto append;
}
if (key == KEYC_MOUSEMOVE_PANE) {
s = "MouseMovePane";
goto append;
}
if (key == KEYC_MOUSEMOVE_STATUS) {
s = "MouseMoveStatus";
goto append;
}
if (key == KEYC_MOUSEMOVE_STATUS_LEFT) {
s = "MouseMoveStatusLeft";
goto append;
}
if (key == KEYC_MOUSEMOVE_STATUS_RIGHT) {
s = "MouseMoveStatusRight";
goto append;
}
if (key == KEYC_MOUSEMOVE_BORDER) {
s = "MouseMoveBorder";
goto append;
}
if (key >= KEYC_USER && key < KEYC_USER + KEYC_NUSER) {
snprintf(tmp, sizeof tmp, "User%u", (u_int)(key - KEYC_USER));
strlcat(out, tmp, sizeof out);
return (out);
}
@ -301,15 +338,6 @@ key_string_lookup_key(key_code key)
if ((key & KEYC_MASK_KEY) == 0)
key = ' ' | KEYC_CTRL | (key & KEYC_MASK_MOD);
/* Fill in the modifiers. */
if (key & KEYC_CTRL)
strlcat(out, "C-", sizeof out);
if (key & KEYC_ESCAPE)
strlcat(out, "M-", sizeof out);
if (key & KEYC_SHIFT)
strlcat(out, "S-", sizeof out);
key &= KEYC_MASK_KEY;
/* Try the key against the string table. */
for (i = 0; i < nitems(key_string_table); i++) {
if (key == key_string_table[i].key)
@ -352,4 +380,8 @@ key_string_lookup_key(key_code key)
strlcat(out, tmp, sizeof out);
return (out);
append:
strlcat(out, s, sizeof out);
return (out);
}

View File

@ -155,11 +155,14 @@ screen_set_cursor_colour(struct screen *s, const char *colour)
}
/* Set screen title. */
void
int
screen_set_title(struct screen *s, const char *title)
{
if (!utf8_isvalid(title))
return (0);
free(s->title);
utf8_stravis(&s->title, title, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
s->title = xstrdup(title);
return (1);
}
/* Set screen path. */

View File

@ -660,8 +660,7 @@ have_event:
break;
}
c->tty.mouse_drag_flag = 0;
return (key);
goto out;
}
/* Convert to a key binding. */
@ -956,6 +955,7 @@ have_event:
if (key == KEYC_UNKNOWN)
return (KEYC_UNKNOWN);
out:
/* Apply modifiers if any. */
if (b & MOUSE_MASK_META)
key |= KEYC_ESCAPE;
@ -964,6 +964,8 @@ have_event:
if (b & MOUSE_MASK_SHIFT)
key |= KEYC_SHIFT;
if (log_get_level() != 0)
log_debug("mouse key is %s", key_string_lookup_key (key));
return (key);
}
@ -1057,7 +1059,7 @@ server_client_key_callback(struct cmdq_item *item, void *data)
* Mouse drag is in progress, so fire the callback (now that
* the mouse event is valid).
*/
if (key == KEYC_DRAGGING) {
if ((key & KEYC_MASK_KEY) == KEYC_DRAGGING) {
c->tty.mouse_drag_update(c, m);
goto out;
}
@ -1704,7 +1706,6 @@ static void
server_client_dispatch(struct imsg *imsg, void *arg)
{
struct client *c = arg;
const char *data;
ssize_t datalen;
struct session *s;
@ -1716,7 +1717,6 @@ server_client_dispatch(struct imsg *imsg, void *arg)
return;
}
data = imsg->data;
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
switch (imsg->hdr.type) {

46
tmux.1
View File

@ -2686,37 +2686,40 @@ To view the default bindings and possible commands, see the
.Ic list-keys
command.
.It Xo Ic list-keys
.Op Fl 1N
.Op Fl 1aN
.Op Fl P Ar prefix-string Fl T Ar key-table
.Op key
.Xc
.D1 (alias: Ic lsk )
List all key bindings.
By default this shows all keys or any bindings for
.Ar key
in the syntax of the
List key bindings.
There are two forms: the default lists keys as
.Ic bind-key
command.
commands;
.Fl N
instead show keys and attached notes, i
.Ar key-table
if given or in the
lists only keys with attached notes and shows only the key and note for each
key.
.Pp
With the default form, all key tables are listed by default.
.Fl T
lists only keys in
.Ar key-table .
.Pp
With the
.Fl N
form, only keys in the
.Em root
and
.Em prefix
key tables by default.
.Fl P
specifies a prefix to print before each key.
With
.Fl 1
only the first matching key and note is shown.
.Pp
Without
.Fl N ,
key tables are listed by default;
.Fl T
prints only keys in
.Ar key-table ,
otherwise all key tables are printed.
also lists only keys in
.Ar key-table .
.Fl P
specifies a prefix to print before each key and
.Fl 1
lists only the first matching key.
.Fl a
lists the command for keys that do have a note rather than skipping them.
.It Xo Ic send-keys
.Op Fl FHlMRX
.Op Fl N Ar repeat-count
@ -4348,6 +4351,7 @@ The following variables are available, where appropriate:
.It Li "scroll_position" Ta "" Ta "Scroll position in copy mode"
.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
.It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane"
.It Li "selection_active" Ta "" Ta "1 if selection started and changes with the cursor in copy mode"
.It Li "selection_end_x" Ta "" Ta "X position of the end of the selection"
.It Li "selection_end_y" Ta "" Ta "Y position of the end of the selection"
.It Li "selection_present" Ta "" Ta "1 if selection started in copy mode"

2
tmux.h
View File

@ -2450,7 +2450,7 @@ void screen_free(struct screen *);
void screen_reset_tabs(struct screen *);
void screen_set_cursor_style(struct screen *, u_int);
void screen_set_cursor_colour(struct screen *, const char *);
void screen_set_title(struct screen *, const char *);
int screen_set_title(struct screen *, const char *);
void screen_set_path(struct screen *, const char *);
void screen_push_title(struct screen *);
void screen_pop_title(struct screen *);

View File

@ -209,7 +209,7 @@ window_buffer_draw(__unused void *modedata, void *itemdata,
struct paste_buffer *pb;
const char *pdata, *start, *end;
char *buf = NULL;
size_t psize, len;
size_t psize;
u_int i, cx = ctx->s->cx, cy = ctx->s->cy;
pb = paste_get_name(item->name);
@ -222,7 +222,7 @@ window_buffer_draw(__unused void *modedata, void *itemdata,
while (end != pdata + psize && *end != '\n')
end++;
buf = xreallocarray(buf, 4, end - start + 1);
len = utf8_strvis(buf, start, end - start, VIS_OCTAL|VIS_TAB);
utf8_strvis(buf, start, end - start, VIS_OCTAL|VIS_TAB);
if (*buf != '\0') {
screen_write_cursormove(ctx, cx, cy + i, 0);
screen_write_nputs(ctx, sx, &grid_default_cell, "%s",

View File

@ -590,7 +590,10 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft)
format_add(ft, "selection_start_y", "%d", data->sely);
format_add(ft, "selection_end_x", "%d", data->endselx);
format_add(ft, "selection_end_y", "%d", data->endsely);
}
format_add(ft, "selection_active", "%d",
data->cursordrag != CURSORDRAG_NONE);
} else
format_add(ft, "selection_active", "%d", 0);
s = format_grid_word(data->screen.grid, data->cx, data->cy);
if (s != NULL) {
@ -1521,14 +1524,26 @@ window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
struct session *s = cs->s;
struct window_copy_mode_data *data = wme->data;
const char *ws;
u_int px, py, xx;
data->lineflag = LINE_SEL_LEFT_RIGHT;
data->rectflag = 0;
px = data->cx;
py = screen_hsize(data->backing) + data->cy - data->oy;
xx = window_copy_find_length(wme, py);
ws = options_get_string(s->options, "word-separators");
window_copy_cursor_previous_word(wme, ws, 0);
window_copy_start_selection(wme);
window_copy_cursor_next_word_end(wme, ws);
if (px >= xx || !window_copy_in_set(wme, px + 1, py, ws))
window_copy_cursor_next_word_end(wme, ws);
else {
window_copy_update_cursor(wme, px, data->cy);
if (window_copy_update_selection(wme, 1))
window_copy_redraw_lines(wme, data->cy, 1);
}
return (WINDOW_COPY_CMD_REDRAW);
}

View File

@ -548,31 +548,38 @@ window_get_active_at(struct window *w, u_int x, u_int y)
struct window_pane *
window_find_string(struct window *w, const char *s)
{
u_int x, y;
u_int x, y, top = 0, bottom = w->sy - 1;
int status;
x = w->sx / 2;
y = w->sy / 2;
status = options_get_number(w->options, "pane-border-status");
if (status == PANE_STATUS_TOP)
top++;
else if (status == PANE_STATUS_BOTTOM)
bottom--;
if (strcasecmp(s, "top") == 0)
y = 0;
y = top;
else if (strcasecmp(s, "bottom") == 0)
y = w->sy - 1;
y = bottom;
else if (strcasecmp(s, "left") == 0)
x = 0;
else if (strcasecmp(s, "right") == 0)
x = w->sx - 1;
else if (strcasecmp(s, "top-left") == 0) {
x = 0;
y = 0;
y = top;
} else if (strcasecmp(s, "top-right") == 0) {
x = w->sx - 1;
y = 0;
y = top;
} else if (strcasecmp(s, "bottom-left") == 0) {
x = 0;
y = w->sy - 1;
y = bottom;
} else if (strcasecmp(s, "bottom-right") == 0) {
x = w->sx - 1;
y = w->sy - 1;
y = bottom;
} else
return (NULL);