summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2024-02-13 10:01:10 +0000
committerThomas Adam <thomas@xteddy.org>2024-02-13 10:01:10 +0000
commit0960862950476a5a519905487d731a8b843d07c2 (patch)
tree72b24ad259c3e0c78f1cf166b35b60e718240eab
parent44ad25b3673cf9fddc92ed122e51cd9beb50d4f7 (diff)
parent40b97b1715182b0ab0274b0c402b34e2cba98f04 (diff)
Merge branch 'obsd-master'
-rw-r--r--cmd-paste-buffer.c5
-rw-r--r--cmd-pipe-pane.c2
-rw-r--r--options-table.c8
-rw-r--r--proc.c2
-rw-r--r--server-fn.c22
-rw-r--r--tmux.116
-rw-r--r--tmux.h1
-rw-r--r--window.c6
8 files changed, 52 insertions, 10 deletions
diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c
index 36326e18..269e92f7 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -54,6 +54,11 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
size_t seplen, bufsize;
int bracket = args_has(args, 'p');
+ if (window_pane_exited(wp)) {
+ cmdq_error(item, "target pane has exited");
+ return (CMD_RETURN_ERROR);
+ }
+
bufname = NULL;
if (args_has(args, 'b'))
bufname = args_get(args, 'b');
diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c
index 0fa656ce..268b51bf 100644
--- a/cmd-pipe-pane.c
+++ b/cmd-pipe-pane.c
@@ -68,7 +68,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
sigset_t set, oldset;
/* Do nothing if pane is dead. */
- if (wp->fd == -1 || (wp->flags & PANE_EXITED)) {
+ if (window_pane_exited(wp)) {
cmdq_error(item, "target pane has exited");
return (CMD_RETURN_ERROR);
}
diff --git a/options-table.c b/options-table.c
index 89200b95..f030f2db 100644
--- a/options-table.c
+++ b/options-table.c
@@ -84,6 +84,9 @@ static const char *options_table_window_size_list[] = {
static const char *options_table_remain_on_exit_list[] = {
"off", "on", "failed", NULL
};
+static const char *options_table_destroy_unattached_list[] = {
+ "off", "on", "keep-last", "keep-group", NULL
+};
static const char *options_table_detach_on_destroy_list[] = {
"off", "on", "no-detached", "previous", "next", NULL
};
@@ -483,11 +486,12 @@ const struct options_table_entry options_table[] = {
},
{ .name = "destroy-unattached",
- .type = OPTIONS_TABLE_FLAG,
+ .type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_SESSION,
+ .choices = options_table_destroy_unattached_list,
.default_num = 0,
.text = "Whether to destroy sessions when they have no attached "
- "clients."
+ "clients, or keep the last session whether in the group."
},
{ .name = "detach-on-destroy",
diff --git a/proc.c b/proc.c
index 68ab9604..7c4805f2 100644
--- a/proc.c
+++ b/proc.c
@@ -93,7 +93,7 @@ proc_event_cb(__unused int fd, short events, void *arg)
log_debug("peer %p message %d", peer, imsg.hdr.type);
if (peer_check_version(peer, &imsg) != 0) {
- int fd = imsg_get_fd(&imsg);
+ fd = imsg_get_fd(&imsg);
if (fd != -1)
close(fd);
imsg_free(&imsg);
diff --git a/server-fn.c b/server-fn.c
index 50f5a8d9..2f649329 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -455,7 +455,8 @@ server_destroy_session(struct session *s)
void
server_check_unattached(void)
{
- struct session *s;
+ struct session *s;
+ struct session_group *sg;
/*
* If any sessions are no longer attached and have destroy-unattached
@@ -464,8 +465,23 @@ server_check_unattached(void)
RB_FOREACH(s, sessions, &sessions) {
if (s->attached != 0)
continue;
- if (options_get_number (s->options, "destroy-unattached"))
- session_destroy(s, 1, __func__);
+ switch (options_get_number(s->options, "destroy-unattached")) {
+ case 0: /* off */
+ continue;
+ case 1: /* on */
+ break;
+ case 2: /* keep-last */
+ sg = session_group_contains(s);
+ if (sg == NULL || session_group_count(sg) <= 1)
+ continue;
+ break;
+ case 3: /* keep-group */
+ sg = session_group_contains(s);
+ if (sg != NULL && session_group_count(sg) == 1)
+ continue;
+ break;
+ }
+ session_destroy(s, 1, __func__);
}
}
diff --git a/tmux.1 b/tmux.1
index 10f73176..9c028352 100644
--- a/tmux.1
+++ b/tmux.1
@@ -4026,10 +4026,20 @@ The value is the width and height separated by an
character.
The default is 80x24.
.It Xo Ic destroy-unattached
-.Op Ic on | off
+.Op Ic off | on | keep-last | keep-group
.Xc
-If enabled and the session is no longer attached to any clients, it is
-destroyed.
+If
+.Ic on ,
+destroy the session after the last client has detached.
+If
+.Ic off
+(the default), leave the session orphaned.
+If
+.Ic keep-last ,
+destroy the session only if it is in a group and has other sessions in that group.
+If
+.Ic keep-group ,
+destroy the session unless it is in a group and is the only session in that group.
.It Xo Ic detach-on-destroy
.Op Ic off | on | no-detached | previous | next
.Xc
diff --git a/tmux.h b/tmux.h
index 53f73b20..a50adbfa 100644
--- a/tmux.h
+++ b/tmux.h
@@ -3096,6 +3096,7 @@ int window_pane_key(struct window_pane *, struct client *,
struct session *, struct winlink *, key_code,
struct mouse_event *);
int window_pane_visible(struct window_pane *);
+int window_pane_exited(struct window_pane *);
u_int window_pane_search(struct window_pane *, const char *, int,
int);
const char *window_printable_flags(struct winlink *, int);
diff --git a/window.c b/window.c
index 81d0f809..77ce41d8 100644
--- a/window.c
+++ b/window.c
@@ -1214,6 +1214,12 @@ window_pane_visible(struct window_pane *wp)
return (wp == wp->window->active);
}
+int
+window_pane_exited(struct window_pane *wp)
+{
+ return (wp->fd == -1 || (wp->flags & PANE_EXITED));
+}
+
u_int
window_pane_search(struct window_pane *wp, const char *term, int regex,
int ignore)