Add detach-on-destroy previous and next, mostly from Alexis Hildebrandt.

This commit is contained in:
nicm 2023-09-01 13:48:54 +00:00
parent 71d453f169
commit c1e6e54e6e
4 changed files with 44 additions and 34 deletions

View File

@ -86,7 +86,7 @@ static const char *options_table_remain_on_exit_list[] = {
"off", "on", "failed", NULL "off", "on", "failed", NULL
}; };
static const char *options_table_detach_on_destroy_list[] = { static const char *options_table_detach_on_destroy_list[] = {
"off", "on", "no-detached", NULL "off", "on", "no-detached", "previous", "next", NULL
}; };
static const char *options_table_extended_keys_list[] = { static const char *options_table_extended_keys_list[] = {
"off", "on", "always", NULL "off", "on", "always", NULL

View File

@ -29,7 +29,6 @@
#include "tmux.h" #include "tmux.h"
static struct session *server_next_session(struct session *);
static void server_destroy_session_group(struct session *); static void server_destroy_session_group(struct session *);
void void
@ -209,7 +208,7 @@ server_kill_window(struct window *w, int renumber)
if (session_detach(s, wl)) { if (session_detach(s, wl)) {
server_destroy_session_group(s); server_destroy_session_group(s);
break; break;
} else }
server_redraw_session_group(s); server_redraw_session_group(s);
} }
@ -384,9 +383,10 @@ server_destroy_session_group(struct session *s)
struct session_group *sg; struct session_group *sg;
struct session *s1; struct session *s1;
if ((sg = session_group_contains(s)) == NULL) if ((sg = session_group_contains(s)) == NULL) {
server_destroy_session(s); server_destroy_session(s);
else { session_destroy(s, 1, __func__);
} else {
TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) { TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {
server_destroy_session(s); server_destroy_session(s);
session_destroy(s, 1, __func__); session_destroy(s, 1, __func__);
@ -395,52 +395,55 @@ server_destroy_session_group(struct session *s)
} }
static struct session * static struct session *
server_next_session(struct session *s) server_find_session(struct session *s,
int (*f)(struct session *, struct session *))
{ {
struct session *s_loop, *s_out = NULL; struct session *s_loop, *s_out = NULL;
RB_FOREACH(s_loop, sessions, &sessions) { RB_FOREACH(s_loop, sessions, &sessions) {
if (s_loop == s) if (s_loop != s && (s_out == NULL || f(s_loop, s_out)))
continue;
if (s_out == NULL ||
timercmp(&s_loop->activity_time, &s_out->activity_time, <))
s_out = s_loop; s_out = s_loop;
} }
return (s_out); return (s_out);
} }
static struct session * static int
server_next_detached_session(struct session *s) server_newer_session(struct session *s_loop, struct session *s_out)
{ {
struct session *s_loop, *s_out = NULL; return (timercmp(&s_loop->activity_time, &s_out->activity_time, <));
}
RB_FOREACH(s_loop, sessions, &sessions) { static int
if (s_loop == s || s_loop->attached) server_newer_detached_session(struct session *s_loop, struct session *s_out)
continue; {
if (s_out == NULL || if (s_loop->attached)
timercmp(&s_loop->activity_time, &s_out->activity_time, <)) return (0);
s_out = s_loop; return (server_newer_session(s_loop, s_out));
}
return (s_out);
} }
void void
server_destroy_session(struct session *s) server_destroy_session(struct session *s)
{ {
struct client *c; struct client *c;
struct session *s_new; struct session *s_new = NULL;
int detach_on_destroy; int detach_on_destroy;
detach_on_destroy = options_get_number(s->options, "detach-on-destroy"); detach_on_destroy = options_get_number(s->options, "detach-on-destroy");
if (detach_on_destroy == 0) if (detach_on_destroy == 0)
s_new = server_next_session(s); s_new = server_find_session(s, server_newer_session);
else if (detach_on_destroy == 2) else if (detach_on_destroy == 2)
s_new = server_next_detached_session(s); s_new = server_find_session(s, server_newer_detached_session);
else else if (detach_on_destroy == 3)
s_new = session_previous_session(s);
else if (detach_on_destroy == 4)
s_new = session_next_session(s);
if (s_new == s)
s_new = NULL; s_new = NULL;
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s) if (c->session != s)
continue; continue;
c->session = NULL;
c->last_session = NULL;
server_client_set_session(c, s_new); server_client_set_session(c, s_new);
if (s_new == NULL) if (s_new == NULL)
c->flags |= CLIENT_EXIT; c->flags |= CLIENT_EXIT;

View File

@ -367,10 +367,8 @@ session_detach(struct session *s, struct winlink *wl)
session_group_synchronize_from(s); session_group_synchronize_from(s);
if (RB_EMPTY(&s->windows)) { if (RB_EMPTY(&s->windows))
session_destroy(s, 1, __func__);
return (1); return (1);
}
return (0); return (0);
} }

15
tmux.1
View File

@ -4039,16 +4039,25 @@ The default is 80x24.
If enabled and the session is no longer attached to any clients, it is If enabled and the session is no longer attached to any clients, it is
destroyed. destroyed.
.It Xo Ic detach-on-destroy .It Xo Ic detach-on-destroy
.Op Ic off | on | no-detached .Op Ic off | on | no-detached | previous | next
.Xc .Xc
If on (the default), the client is detached when the session it is attached to If
.Ic on
(the default), the client is detached when the session it is attached to
is destroyed. is destroyed.
If off, the client is switched to the most recently active of the remaining If
.Ic off ,
the client is switched to the most recently active of the remaining
sessions. sessions.
If If
.Ic no-detached , .Ic no-detached ,
the client is detached only if there are no detached sessions; if detached the client is detached only if there are no detached sessions; if detached
sessions exist, the client is switched to the most recently active. sessions exist, the client is switched to the most recently active.
If
.Ic previous
or
.Ic next ,
the client is switched to the previous or next session in alphabetical order.
.It Ic display-panes-active-colour Ar colour .It Ic display-panes-active-colour Ar colour
Set the colour used by the Set the colour used by the
.Ic display-panes .Ic display-panes