From f0284454079a23962dab96dc692bec39d346f0d6 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 27 Dec 2023 20:13:35 +0000 Subject: [PATCH 1/5] Correctly handle window ops with no pane, GitHub issue 3747. --- input.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/input.c b/input.c index 70a0f5da..b833b50e 100644 --- a/input.c +++ b/input.c @@ -1846,10 +1846,13 @@ input_csi_dispatch_winops(struct input_ctx *ictx) struct screen_write_ctx *sctx = &ictx->ctx; struct screen *s = sctx->s; struct window_pane *wp = ictx->wp; - struct window *w = wp->window; + struct window *w = NULL; u_int x = screen_size_x(s), y = screen_size_y(s); int n, m; + if (wp != NULL) + w = wp->window; + m = 0; while ((n = input_get(ictx, m, 0, -1)) != -1) { switch (n) { @@ -1878,13 +1881,22 @@ input_csi_dispatch_winops(struct input_ctx *ictx) return; break; case 14: - input_reply(ictx, "\033[4;%u;%ut", y * w->ypixel, x * w->xpixel); + if (w == NULL) + break; + input_reply(ictx, "\033[4;%u;%ut", y * w->ypixel, + x * w->xpixel); break; case 15: - input_reply(ictx, "\033[5;%u;%ut", y * w->ypixel, x * w->xpixel); + if (w == NULL) + break; + input_reply(ictx, "\033[5;%u;%ut", y * w->ypixel, + x * w->xpixel); break; case 16: - input_reply(ictx, "\033[6;%u;%ut", w->ypixel, w->xpixel); + if (w == NULL) + break; + input_reply(ictx, "\033[6;%u;%ut", w->ypixel, + w->xpixel); break; case 18: input_reply(ictx, "\033[8;%u;%ut", y, x); @@ -1914,8 +1926,8 @@ input_csi_dispatch_winops(struct input_ctx *ictx) if (wp == NULL) break; notify_pane("pane-title-changed", wp); - server_redraw_window_borders(wp->window); - server_status_window(wp->window); + server_redraw_window_borders(w); + server_status_window(w); break; } break; From 73a2b1208839ea32319616969616ef01b5511c9c Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 27 Dec 2023 20:17:13 +0000 Subject: [PATCH 2/5] Always initialize screen mode, GitHub issue 3750 from Ding Fei. --- screen.c | 1 + 1 file changed, 1 insertion(+) diff --git a/screen.c b/screen.c index 3e86809c..267a50b9 100644 --- a/screen.c +++ b/screen.c @@ -83,6 +83,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) s->cstyle = SCREEN_CURSOR_DEFAULT; s->default_cstyle = SCREEN_CURSOR_DEFAULT; + s->mode = MODE_CURSOR; s->default_mode = 0; s->ccolour = -1; s->default_ccolour = -1; From 008ecd45927681c6172ca1561eef1c6f4e7f57be Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 27 Dec 2023 20:20:50 +0000 Subject: [PATCH 3/5] groff apparently generates broken output for some common characters in mdoc, so escaped versions have to be used instead. From Alexis Hildebrandt in GitHub issue 3762. --- tmux.1 | 90 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/tmux.1 b/tmux.1 index 7bcd4d1a..78214518 100644 --- a/tmux.1 +++ b/tmux.1 @@ -140,7 +140,7 @@ By default, loads the system configuration file from .Pa /etc/tmux.conf , if present, then looks for a user configuration file at -.Pa ~/.tmux.conf . +.Pa \[ti]/.tmux.conf . .Pp The configuration file is a set of .Nm @@ -287,7 +287,7 @@ Rename the current session. Split the current pane into two, left and right. .It & Kill the current window. -.It ' +.It \[aq] Prompt for a window index to select. .It \&( Switch the attached client to the previous session. @@ -359,7 +359,7 @@ Toggle zoom state of the current pane. Swap the current pane with the previous pane. .It } Swap the current pane with the next pane. -.It ~ +.It \[ti] Show previous messages from .Nm , if any. @@ -405,7 +405,7 @@ the command prompt. For example, the same .Ic set-option command run from the shell prompt, from -.Pa ~/.tmux.conf +.Pa \[ti]/.tmux.conf and bound to a key may look like: .Bd -literal -offset indent $ tmux set-option -g status-style bg=cyan @@ -458,7 +458,7 @@ To execute commands, each client has a .Ql command queue . A global command queue not attached to any client is used on startup for configuration files like -.Pa ~/.tmux.conf . +.Pa \[ti]/.tmux.conf . Parsed commands added to the queue are executed in order. Some commands, like .Ic if-shell @@ -530,7 +530,7 @@ $ tmux neww \\; splitw .Pp Or: .Bd -literal -offset indent -$ tmux neww ';' splitw +$ tmux neww \[aq];\[aq] splitw .Ed .Pp Or from the tmux command prompt: @@ -548,7 +548,7 @@ $ tmux neww\e; splitw .Pp Or: .Bd -literal -offset indent -$ tmux 'neww;' splitw +$ tmux \[aq]neww;\[aq] splitw .Ed .Pp As in these examples, when running tmux from the shell extra care must be taken @@ -560,7 +560,7 @@ should be escaped according to the shell conventions. For .Xr sh 1 this typically means quoted (such as -.Ql neww ';' splitw ) +.Ql neww \[aq];\[aq] splitw ) or escaped (such as .Ql neww \e\e\e\e; splitw ) . .It @@ -570,14 +570,14 @@ a second time for .Nm ; for example: .Bd -literal -offset indent -$ tmux neww 'foo\e\e;' bar +$ tmux neww \[aq]foo\e\e;\[aq] bar $ tmux neww foo\e\e\e\e; bar .Ed .It Semicolons that are not individual tokens or trailing another token should only be escaped once according to shell conventions; for example: .Bd -literal -offset indent -$ tmux neww 'foo-;-bar' +$ tmux neww \[aq]foo-;-bar\[aq] $ tmux neww foo-\e\e;-bar .Ed .El @@ -590,8 +590,8 @@ line (the \e and the newline are completely removed). This is called line continuation and applies both inside and outside quoted strings and in comments, but not inside braces. .Pp -Command arguments may be specified as strings surrounded by single (') quotes, -double quotes (") or braces ({}). +Command arguments may be specified as strings surrounded by single (\[aq]) quotes, +double quotes (\[dq]) or braces ({}). .\" " This is required when the argument contains any special character. Single and double quoted strings cannot span multiple lines except with line @@ -606,7 +606,7 @@ global environment (see the .Sx GLOBAL AND SESSION ENVIRONMENT section). .It -A leading ~ or ~user is expanded to the home directory of the current or +A leading \[ti] or \[ti]user is expanded to the home directory of the current or specified user. .It \euXXXX or \euXXXXXXXX is replaced by the Unicode codepoint corresponding to @@ -638,10 +638,10 @@ These two examples produce an identical command - note that no escaping is needed when using {}: .Bd -literal -offset indent if-shell true { - display -p 'brace-dollar-foo: }$foo' + display -p \[aq]brace-dollar-foo: }$foo\[aq] } -if-shell true "display -p 'brace-dollar-foo: }\e$foo'" +if-shell true "display -p \[aq]brace-dollar-foo: }\e$foo\[aq]" .Ed .Pp Braces may be enclosed inside braces, for example: @@ -892,7 +892,7 @@ section) or .Ql {marked} (alternative form -.Ql ~ ) +.Ql \[ti] ) to specify the marked pane (see .Ic select-pane .Fl m ) . @@ -932,12 +932,12 @@ arguments are commands. This may be a single argument passed to the shell, for example: .Bd -literal -offset indent -new-window 'vi ~/.tmux.conf' +new-window \[aq]vi \[ti]/.tmux.conf\[aq] .Ed .Pp Will run: .Bd -literal -offset indent -/bin/sh -c 'vi ~/.tmux.conf' +/bin/sh -c \[aq]vi \[ti]/.tmux.conf\[aq] .Ed .Pp Additionally, the @@ -954,7 +954,7 @@ to be given as multiple arguments and executed directly (without This can avoid issues with shell quoting. For example: .Bd -literal -offset indent -$ tmux new-window vi ~/.tmux.conf +$ tmux new-window vi \[ti]/.tmux.conf .Ed .Pp Will run @@ -989,7 +989,7 @@ set-option -wt:0 monitor-activity on new-window ; split-window -d -bind-key R source-file ~/.tmux.conf \e; \e +bind-key R source-file \[ti]/.tmux.conf \e; \e display-message "source-file done" .Ed .Pp @@ -1000,7 +1000,7 @@ $ tmux kill-window -t :1 $ tmux new-window \e; split-window -d -$ tmux new-session -d 'vi ~/.tmux.conf' \e; split-window -d \e; attach +$ tmux new-session -d \[aq]vi \[ti]/.tmux.conf\[aq] \e; split-window -d \e; attach .Ed .Sh CLIENTS AND SESSIONS The @@ -1581,7 +1581,7 @@ Note that as by default the .Nm server will exit with no sessions, this is only useful if a session is created in -.Pa ~/.tmux.conf , +.Pa \[ti]/.tmux.conf , .Ic exit-empty is turned off, or another command is run as part of the same command sequence. For example: @@ -2171,7 +2171,7 @@ For example: $ tmux list-windows 0: ksh [159x48] layout: bb62,159x48,0,0{79x48,0,0,79x48,80,0} -$ tmux select-layout 'bb62,159x48,0,0{79x48,0,0,79x48,80,0}' +$ tmux select-layout \[aq]bb62,159x48,0,0{79x48,0,0,79x48,80,0}\[aq] .Ed .Pp .Nm @@ -2311,7 +2311,7 @@ is replaced by the client name in and the result executed as a command. If .Ar template -is not given, "detach-client -t '%%'" is used. +is not given, "detach-client -t \[aq]%%\[aq]" is used. .Pp .Fl O specifies the initial sort field: one of @@ -2396,7 +2396,7 @@ are replaced by the target in and the result executed as a command. If .Ar template -is not given, "switch-client -t '%%'" is used. +is not given, "switch-client -t \[aq]%%\[aq]" is used. .Pp .Fl O specifies the initial sort field: one of @@ -2508,7 +2508,7 @@ to be executed as a command with substituted by the pane ID. The default .Ar template -is "select-pane -t '%%'". +is "select-pane -t \[aq]%%\[aq]". With .Fl b , other commands are not blocked from running until the indicator is closed. @@ -2870,7 +2870,7 @@ The option only opens a new pipe if no previous pipe exists, allowing a pipe to be toggled with a single key, for example: .Bd -literal -offset indent -bind-key C-p pipe-pane -o 'cat >>~/output.#I-#P' +bind-key C-p pipe-pane -o \[aq]cat >>\[ti]/output.#I-#P\[aq] .Ed .Tg prevl .It Xo Ic previous-layout @@ -3174,7 +3174,7 @@ zooms if the window is not zoomed, or keeps it zoomed if already zoomed. .Pp An empty .Ar shell-command -('') will create a pane with no command running in it. +(\[aq]\[aq]) will create a pane with no command running in it. Output can be sent to such a pane with the .Ic display-message command. @@ -3301,11 +3301,11 @@ and Note that to bind the .Ql \&" or -.Ql ' +.Ql \[aq] keys, quotation marks are necessary, for example: .Bd -literal -offset indent -bind-key '"' split-window -bind-key "'" new-window +bind-key \[aq]"\[aq] split-window +bind-key "\[aq]" new-window .Ed .Pp A command bound to the @@ -3701,7 +3701,7 @@ it is replaced with .Ar value . For example, after: .Pp -.Dl set -s command-alias[100] zoom='resize-pane -Z' +.Dl set -s command-alias[100] zoom=\[aq]resize-pane -Z\[aq] .Pp Using: .Pp @@ -3939,7 +3939,7 @@ and so on. .Pp For example: .Bd -literal -offset indent -set -s user-keys[0] "\ee[5;30012~" +set -s user-keys[0] "\ee[5;30012\[ti]" bind User0 resize-pane -L 3 .Ed .El @@ -4838,8 +4838,8 @@ or .Fl H . The following two commands are equivalent: .Bd -literal -offset indent. -set-hook -g pane-mode-changed[42] 'set -g status-left-style bg=red' -set-option -g pane-mode-changed[42] 'set -g status-left-style bg=red' +set-hook -g pane-mode-changed[42] \[aq]set -g status-left-style bg=red\[aq] +set-option -g pane-mode-changed[42] \[aq]set -g status-left-style bg=red\[aq] .Ed .Pp Setting a hook without specifying an array index clears the hook and sets the @@ -5778,7 +5778,7 @@ An escape sequence (if the .Ic allow-rename option is turned on): .Bd -literal -offset indent -$ printf '\e033kWINDOW_NAME\e033\e\e' +$ printf \[aq]\e033kWINDOW_NAME\e033\e\e\[aq] .Ed .It Automatic renaming, which sets the name to the active command in the window's @@ -5791,7 +5791,7 @@ option. When a pane is first created, its title is the hostname. A pane's title can be set via the title setting escape sequence, for example: .Bd -literal -offset indent -$ printf '\e033]2;My Title\e033\e\e' +$ printf \[aq]\e033]2;My Title\e033\e\e\[aq] .Ed .Pp It can also be modified with the @@ -5916,7 +5916,7 @@ The flag is one of the following symbols appended to the window name: .It Li "-" Ta "Marks the last window (previously selected)." .It Li "#" Ta "Window activity is monitored and activity has been detected." .It Li "\&!" Ta "Window bells are monitored and a bell has occurred in the window." -.It Li "~" Ta "The window has been silent for the monitor-silence interval." +.It Li "\[ti]" Ta "The window has been silent for the monitor-silence interval." .It Li "M" Ta "The window contains the marked pane." .It Li "Z" Ta "The window's active pane is zoomed." .El @@ -6451,7 +6451,7 @@ is replaced by the buffer name in and the result executed as a command. If .Ar template -is not given, "paste-buffer -b '%%'" is used. +is not given, "paste-buffer -b \[aq]%%\[aq]" is used. .Pp .Fl O specifies the initial sort field: one of @@ -6750,7 +6750,7 @@ If set, a sequence such as this may be used to change the cursor colour from inside .Nm : .Bd -literal -offset indent -$ printf '\e033]12;red\e033\e\e' +$ printf \[aq]\e033]12;red\e033\e\e\[aq] .Ed .Pp The colour is an @@ -6806,7 +6806,7 @@ Set or reset the cursor style. If set, a sequence such as this may be used to change the cursor to an underline: .Bd -literal -offset indent -$ printf '\e033[4 q' +$ printf \[aq]\e033[4 q\[aq] .Ed .Pp If @@ -7125,7 +7125,7 @@ options. .El .Sh FILES .Bl -tag -width "/etc/tmux.confXXX" -compact -.It Pa ~/.tmux.conf +.It Pa \[ti]/.tmux.conf Default .Nm configuration file. @@ -7191,7 +7191,7 @@ to exit from it. Commands to be run when the .Nm server is started may be placed in the -.Pa ~/.tmux.conf +.Pa \[ti]/.tmux.conf configuration file. Common examples include: .Pp @@ -7218,8 +7218,8 @@ set-option -g lock-after-time 1800 Creating new key bindings: .Bd -literal -offset indent bind-key b set-option status -bind-key / command-prompt "split-window 'exec man %%'" -bind-key S command-prompt "new-window -n %1 'ssh %1'" +bind-key / command-prompt "split-window \[aq]exec man %%\[aq]" +bind-key S command-prompt "new-window -n %1 \[aq]ssh %1\[aq]" .Ed .Sh SEE ALSO .Xr pty 4 From f7bf7e9671d89ac8b249ea52b7660ead9f700b03 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 27 Dec 2023 20:23:59 +0000 Subject: [PATCH 4/5] Remove flags from the prefix before comparing with the received key so that modifier keys with flags work correctly, GitHub issue 3764. --- server-client.c | 8 +++++--- tmux.1 | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/server-client.c b/server-client.c index 644d69e2..fa8bddfa 100644 --- a/server-client.c +++ b/server-client.c @@ -1867,7 +1867,7 @@ server_client_key_callback(struct cmdq_item *item, void *data) struct key_binding *bd; int xtimeout, flags; struct cmd_find_state fs; - key_code key0; + key_code key0, prefix, prefix2; /* Check the client is good to accept input. */ if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) @@ -1939,9 +1939,11 @@ table_changed: * The prefix always takes precedence and forces a switch to the prefix * table, unless we are already there. */ + prefix = (key_code)options_get_number(s->options, "prefix"); + prefix2 = (key_code)options_get_number(s->options, "prefix2"); key0 = (key & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS)); - if ((key0 == (key_code)options_get_number(s->options, "prefix") || - key0 == (key_code)options_get_number(s->options, "prefix2")) && + if ((key0 == (prefix & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS)) || + key0 == (prefix2 & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS))) && strcmp(table->name, "prefix") != 0) { server_client_set_key_table(c, "prefix"); server_status_client(c); diff --git a/tmux.1 b/tmux.1 index 78214518..9ffc90d3 100644 --- a/tmux.1 +++ b/tmux.1 @@ -590,8 +590,8 @@ line (the \e and the newline are completely removed). This is called line continuation and applies both inside and outside quoted strings and in comments, but not inside braces. .Pp -Command arguments may be specified as strings surrounded by single (\[aq]) quotes, -double quotes (\[dq]) or braces ({}). +Command arguments may be specified as strings surrounded by single (\[aq]) +quotes, double quotes (\[dq]) or braces ({}). .\" " This is required when the argument contains any special character. Single and double quoted strings cannot span multiple lines except with line From 40a20bc8ae800e9249037867c863111fcbfa2733 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 27 Dec 2023 20:42:01 +0000 Subject: [PATCH 5/5] Only wrap pattern in *s if using a regular expression. --- cmd-find-window.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/cmd-find-window.c b/cmd-find-window.c index cb9afacb..56099837 100644 --- a/cmd-find-window.c +++ b/cmd-find-window.c @@ -48,6 +48,7 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item) struct cmd_find_state *target = cmdq_get_target(item); struct window_pane *wp = target->wp; const char *s = args_string(args, 0), *suffix = ""; + const char *star = "*"; struct args_value *filter; int C, N, T; @@ -55,6 +56,8 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item) N = args_has(args, 'N'); T = args_has(args, 'T'); + if (args_has(args, 'r')) + star = ""; if (args_has(args, 'r') && args_has(args, 'i')) suffix = "/ri"; else if (args_has(args, 'r')) @@ -71,34 +74,34 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item) if (C && N && T) { xasprintf(&filter->string, "#{||:" - "#{C%s:%s},#{||:#{m%s:*%s*,#{window_name}}," - "#{m%s:*%s*,#{pane_title}}}}", - suffix, s, suffix, s, suffix, s); + "#{C%s:%s},#{||:#{m%s:%s%s%s,#{window_name}}," + "#{m%s:%s%s%s,#{pane_title}}}}", + suffix, s, suffix, star, s, star, suffix, star, s, star); } else if (C && N) { xasprintf(&filter->string, - "#{||:#{C%s:%s},#{m%s:*%s*,#{window_name}}}", - suffix, s, suffix, s); + "#{||:#{C%s:%s},#{m%s:%s%s%s,#{window_name}}}", + suffix, s, suffix, star, s, star); } else if (C && T) { xasprintf(&filter->string, - "#{||:#{C%s:%s},#{m%s:*%s*,#{pane_title}}}", - suffix, s, suffix, s); + "#{||:#{C%s:%s},#{m%s:%s%s%s,#{pane_title}}}", + suffix, s, suffix, star, s, star); } else if (N && T) { xasprintf(&filter->string, - "#{||:#{m%s:*%s*,#{window_name}}," - "#{m%s:*%s*,#{pane_title}}}", - suffix, s, suffix, s); + "#{||:#{m%s:%s%s%s,#{window_name}}," + "#{m%s:%s%s%s,#{pane_title}}}", + suffix, star, s, star, suffix, star, s, star); } else if (C) { xasprintf(&filter->string, "#{C%s:%s}", suffix, s); } else if (N) { xasprintf(&filter->string, - "#{m%s:*%s*,#{window_name}}", - suffix, s); + "#{m%s:%s%s%s,#{window_name}}", + suffix, star, s, star); } else { xasprintf(&filter->string, - "#{m%s:*%s*,#{pane_title}}", - suffix, s); + "#{m%s:%s%s%s,#{pane_title}}", + suffix, star, s, star); } new_args = args_create();