Add a clear-on-attach option which when turned off scrolls away the

existing terminal state instead of entering the alternate screen. This
is useful in environments where tmux is started as a login shell but it
is important that any pre-tmux messages are still visible. GitHub issue
5508 from Josef Řídký.
This commit is contained in:
nicm
2026-08-25 08:37:08 +00:00
committed by tmux update bot
parent 6f4c9b32af
commit 4157b64754
5 changed files with 48 additions and 11 deletions

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: options-table.c,v 1.242 2026/07/27 08:03:01 nicm Exp $ */ /* $OpenBSD: options-table.c,v 1.243 2026/08/25 08:37:08 nicm Exp $ */
/* /*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -306,6 +306,16 @@ const struct options_table_entry options_table[] = {
"When this is reached, the oldest buffer is deleted." "When this is reached, the oldest buffer is deleted."
}, },
{ .name = "clear-on-attach",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_SERVER,
.default_num = 1,
.text = "Whether to use the alternate screen and clear it when "
"a client is attached. When disabled, tmux does not "
"enter the alternate screen on attach so terminal "
"content before tmux remains in scrollback."
},
{ .name = "command-alias", { .name = "command-alias",
.type = OPTIONS_TABLE_STRING, .type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER, .scope = OPTIONS_TABLE_SERVER,

13
tmux.1
View File

@@ -1,4 +1,4 @@
.\" $OpenBSD: tmux.1,v 1.1158 2026/08/20 09:19:24 nicm Exp $ .\" $OpenBSD: tmux.1,v 1.1159 2026/08/25 08:37:08 nicm Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\" .\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: August 20 2026 $ .Dd $Mdocdate: August 25 2026 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@@ -4752,6 +4752,15 @@ for backspace.
Set the number of buffers; as new buffers are added to the top of the stack, Set the number of buffers; as new buffers are added to the top of the stack,
old ones are removed from the bottom if necessary to maintain this maximum old ones are removed from the bottom if necessary to maintain this maximum
length. length.
.It Xo Ic clear\-on\-attach
.Op Ic on | off
.Xc
When enabled (the default), the client terminal switches to the alternate
screen and clears it when a client is attached.
When disabled,
.Nm
does not enter the alternate screen; instead the existing terminal content is
scrolled into the scrollback buffer so it remains accessible.
.It Xo Ic command\-alias[] .It Xo Ic command\-alias[]
.Ar name=value .Ar name=value
.Xc .Xc

3
tmux.h
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1430 2026/08/24 21:17:19 nicm Exp $ */ /* $OpenBSD: tmux.h,v 1.1431 2026/08/25 08:37:08 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -474,6 +474,7 @@ enum tty_code_code {
TTYC_ICH1, TTYC_ICH1,
TTYC_IL, TTYC_IL,
TTYC_IL1, TTYC_IL1,
TTYC_IND,
TTYC_INDN, TTYC_INDN,
TTYC_INVIS, TTYC_INVIS,
TTYC_KCBT, TTYC_KCBT,

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tty-term.c,v 1.108 2026/08/17 14:47:41 nicm Exp $ */ /* $OpenBSD: tty-term.c,v 1.109 2026/08/25 08:37:08 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -108,6 +108,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
[TTYC_ICH] = { TTYCODE_STRING, "ich" }, [TTYC_ICH] = { TTYCODE_STRING, "ich" },
[TTYC_IL1] = { TTYCODE_STRING, "il1" }, [TTYC_IL1] = { TTYCODE_STRING, "il1" },
[TTYC_IL] = { TTYCODE_STRING, "il" }, [TTYC_IL] = { TTYCODE_STRING, "il" },
[TTYC_IND] = { TTYCODE_STRING, "ind" },
[TTYC_INDN] = { TTYCODE_STRING, "indn" }, [TTYC_INDN] = { TTYCODE_STRING, "indn" },
[TTYC_INVIS] = { TTYCODE_STRING, "invis" }, [TTYC_INVIS] = { TTYCODE_STRING, "invis" },
[TTYC_KCBT] = { TTYCODE_STRING, "kcbt" }, [TTYC_KCBT] = { TTYCODE_STRING, "kcbt" },

28
tty.c
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tty.c,v 1.479 2026/08/18 09:01:20 nicm Exp $ */ /* $OpenBSD: tty.c,v 1.480 2026/08/25 08:37:08 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -333,6 +333,7 @@ tty_start_tty(struct tty *tty)
{ {
struct client *c = tty->client; struct client *c = tty->client;
struct termios tio; struct termios tio;
u_int i;
setblocking(c->fd, 0); setblocking(c->fd, 0);
event_add(&tty->event_in, NULL); event_add(&tty->event_in, NULL);
@@ -348,10 +349,21 @@ tty_start_tty(struct tty *tty)
if (tcsetattr(c->fd, TCSANOW, &tio) == 0) if (tcsetattr(c->fd, TCSANOW, &tio) == 0)
tcflush(c->fd, TCOFLUSH); tcflush(c->fd, TCOFLUSH);
tty_putcode(tty, TTYC_SMCUP); if (options_get_number(global_options, "clear-on-attach")) {
tty_putcode(tty, TTYC_SMCUP);
tty_putcode(tty, TTYC_CLEAR);
} else {
tty_putcode_ii(tty, TTYC_CSR, 0, tty->sy - 1);
tty_putcode_ii(tty, TTYC_CUP, 0, tty->sy - 1);
if (tty_term_has(tty->term, TTYC_INDN))
tty_putcode_i(tty, TTYC_INDN, tty->sy + 1);
else if (tty_term_has(tty->term, TTYC_IND)) {
for (i = 0; i < tty->sy + 1; i++)
tty_putcode(tty, TTYC_IND);
} else
tty_putcode(tty, TTYC_CLEAR);
}
tty_putcode(tty, TTYC_SMKX); tty_putcode(tty, TTYC_SMKX);
tty_putcode(tty, TTYC_CLEAR);
if (tty_acs_needed(tty)) { if (tty_acs_needed(tty)) {
log_debug("%s: using capabilities for ACS", c->name); log_debug("%s: using capabilities for ACS", c->name);
@@ -467,7 +479,8 @@ tty_stop_tty(struct tty *tty)
tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS));
tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0)); tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0));
tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX));
tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); if (options_get_number(global_options, "clear-on-attach"))
tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR));
if (tty->cstyle != SCREEN_CURSOR_DEFAULT) { if (tty->cstyle != SCREEN_CURSOR_DEFAULT) {
if (tty_term_has(tty->term, TTYC_SE)) if (tty_term_has(tty->term, TTYC_SE))
tty_raw(tty, tty_term_string(tty->term, TTYC_SE)); tty_raw(tty, tty_term_string(tty->term, TTYC_SE));
@@ -492,7 +505,10 @@ tty_stop_tty(struct tty *tty)
if (tty_use_margin(tty)) if (tty_use_margin(tty))
tty_raw(tty, tty_term_string(tty->term, TTYC_DSMG)); tty_raw(tty, tty_term_string(tty->term, TTYC_DSMG));
tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); if (options_get_number(global_options, "clear-on-attach"))
tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP));
else
tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR));
if (tty->term->flags & TERM_VT100LIKE) if (tty->term->flags & TERM_VT100LIKE)
tty_raw(tty, "\033[?2031l"); tty_raw(tty, "\033[?2031l");