diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-07-17 15:03:12 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-07-17 15:03:12 +0000 |
commit | ff129840bbc95ad2f504d1fac3afee6547e707f2 (patch) | |
tree | f48c1fe6ed4fcaa70337210ea5dcf4ac69a6f9cd /usr.bin | |
parent | 1f6bbb790b00f2d31c281d739ce0ae4985fc9304 (diff) |
Tidy up new-session and attach-session and change them to work from inside
tmux, switching the current client to the new or requested session.
Written with Josh Elsasser.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/cmd-attach-session.c | 57 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-new-session.c | 123 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 8 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 12 |
4 files changed, 131 insertions, 69 deletions
diff --git a/usr.bin/tmux/cmd-attach-session.c b/usr.bin/tmux/cmd-attach-session.c index fa24d71eba6..5e8a5cbd997 100644 --- a/usr.bin/tmux/cmd-attach-session.c +++ b/usr.bin/tmux/cmd-attach-session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-attach-session.c,v 1.3 2009/07/13 23:11:35 nicm Exp $ */ +/* $OpenBSD: cmd-attach-session.c,v 1.4 2009/07/17 15:03:11 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -44,10 +44,9 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) { struct cmd_target_data *data = self->data; struct session *s; + struct client *c; char *cause; - - if (ctx->curclient != NULL) - return (0); + u_int i; if (ARRAY_LENGTH(&sessions) == 0) { ctx->error(ctx, "no sessions"); @@ -56,24 +55,44 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) if ((s = cmd_find_session(ctx, data->target)) == NULL) return (-1); - if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) { - ctx->error(ctx, "not a terminal"); - return (-1); - } + if (ctx->cmdclient == NULL) { + if (data->chflags & CMD_CHFLAG('d')) { + /* + * Can't use server_write_session in case attaching to + * the same session as currently attached to. + */ + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c == NULL || c->session != s) + continue; + if (c == ctx->curclient) + continue; + server_write_client(c, MSG_DETACH, NULL, 0); + } + } + + ctx->curclient->session = s; + server_redraw_client(ctx->curclient); + } else { + if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) { + ctx->error(ctx, "not a terminal"); + return (-1); + } - if (tty_open(&ctx->cmdclient->tty, &cause) != 0) { - ctx->error(ctx, "terminal open failed: %s", cause); - xfree(cause); - return (-1); - } + if (tty_open(&ctx->cmdclient->tty, &cause) != 0) { + ctx->error(ctx, "terminal open failed: %s", cause); + xfree(cause); + return (-1); + } - if (data->chflags & CMD_CHFLAG('d')) - server_write_session(s, MSG_DETACH, NULL, 0); - ctx->cmdclient->session = s; + if (data->chflags & CMD_CHFLAG('d')) + server_write_session(s, MSG_DETACH, NULL, 0); - server_write_client(ctx->cmdclient, MSG_READY, NULL, 0); + ctx->cmdclient->session = s; + server_write_client(ctx->cmdclient, MSG_READY, NULL, 0); + server_redraw_client(ctx->cmdclient); + } recalculate_sizes(); - server_redraw_client(ctx->cmdclient); - return (1); + return (1); /* 1 means don't tell command client to exit */ } diff --git a/usr.bin/tmux/cmd-new-session.c b/usr.bin/tmux/cmd-new-session.c index 7e20496085c..56a0abba850 100644 --- a/usr.bin/tmux/cmd-new-session.c +++ b/usr.bin/tmux/cmd-new-session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-new-session.c,v 1.3 2009/07/13 23:11:35 nicm Exp $ */ +/* $OpenBSD: cmd-new-session.c,v 1.4 2009/07/17 15:03:11 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -111,65 +111,80 @@ int cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) { struct cmd_new_session_data *data = self->data; - struct client *c = ctx->cmdclient; struct session *s; char *cmd, *cwd, *cause; u_int sx, sy; - if (ctx->curclient != NULL) - return (0); + if (data->newname != NULL && session_find(data->newname) != NULL) { + ctx->error(ctx, "duplicate session: %s", data->newname); + return (-1); + } - if (!data->flag_detached) { - if (c == NULL) { - ctx->error(ctx, "no client to attach to"); + /* + * There are two cases: + * + * 1. If cmdclient is non-NULL, new-session has been called from the + * command-line - cmdclient is to become a new attached, interactive + * client. Unless -d is given, the terminal must be opened and then + * the client sent MSG_READY. + * + * 2. If cmdclient is NULL, new-session has been called from an + * existing client (such as a key binding). + * + * In both cases, a new additional session needs to be created and + * (unless -d) set as the current session for the client. + */ + + /* Open the terminal if necessary. */ + if (!data->flag_detached && ctx->cmdclient != NULL) { + if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) { + ctx->error(ctx, "not a terminal"); return (-1); } - if (!(c->flags & CLIENT_TERMINAL)) { - ctx->error(ctx, "not a terminal"); + + if (tty_open(&ctx->cmdclient->tty, &cause) != 0) { + ctx->error(ctx, "open terminal failed: %s", cause); + xfree(cause); return (-1); } } - if (data->newname != NULL && session_find(data->newname) != NULL) { - ctx->error(ctx, "duplicate session: %s", data->newname); - return (-1); + /* Find new session size and options. */ + if (data->flag_detached) { + sx = 80; + sy = 25; + } else { + if (ctx->cmdclient != NULL) { + sx = ctx->cmdclient->tty.sx; + sy = ctx->cmdclient->tty.sy; + } else { + sx = ctx->curclient->tty.sx; + sy = ctx->curclient->tty.sy; + } } - - cmd = data->cmd; - if (cmd == NULL) - cmd = options_get_string(&global_s_options, "default-command"); - if (c == NULL || c->cwd == NULL) + if (sy > 0 && options_get_number(&global_s_options, "status")) + sy--; + if (sx == 0) + sx = 1; + if (sy == 0) + sy = 1; + if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) + cwd = ctx->cmdclient->cwd; + else cwd = options_get_string(&global_s_options, "default-path"); + if (data->cmd != NULL) + cmd = data->cmd; else - cwd = c->cwd; - - sx = 80; - sy = 25; - if (!data->flag_detached) { - sx = c->tty.sx; - sy = c->tty.sy; - } - - if (options_get_number(&global_s_options, "status")) { - if (sy == 0) - sy = 1; - else - sy--; - } - - if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) { - ctx->error(ctx, "open terminal failed: %s", cause); - xfree(cause); - return (-1); - } - + cmd = options_get_string(&global_s_options, "default-command"); + /* Create the new session. */ s = session_create(data->newname, cmd, cwd, sx, sy, &cause); if (s == NULL) { ctx->error(ctx, "create session failed: %s", cause); xfree(cause); return (-1); } + if (data->winname != NULL) { xfree(s->curw->window->name); s->curw->window->name = xstrdup(data->winname); @@ -177,17 +192,31 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) &s->curw->window->options, "automatic-rename", 0); } - if (data->flag_detached) { - if (c != NULL) - server_write_client(c, MSG_EXIT, NULL, 0); - } else { - c->session = s; - server_write_client(c, MSG_READY, NULL, 0); - server_redraw_client(c); + /* + * If a command client exists, it is either taking this session (and + * needs to get MSG_READY and stay around), or -d is given and it needs + * to exit. + */ + if (ctx->cmdclient != NULL) { + if (!data->flag_detached) + server_write_client(ctx->cmdclient, MSG_READY, NULL, 0); + else + server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); + } + + /* Set the client to the new session. */ + if (!data->flag_detached) { + if (ctx->cmdclient != NULL) { + ctx->cmdclient->session = s; + server_redraw_client(ctx->cmdclient); + } else { + ctx->curclient->session = s; + server_redraw_client(ctx->curclient); + } } recalculate_sizes(); - return (1); + return (1); /* 1 means don't tell command client to exit */ } void diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 384cbdd7f46..c114559387c 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.33 2009/07/17 13:38:03 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.34 2009/07/17 15:03:11 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" @@ -596,7 +596,11 @@ The following commands are available: .Op Fl t Ar target-session .Xc .D1 (alias: Ic attach ) -Create a new client in the current terminal and attach it to a session. +If run from outside +.Nm , +create a new client in the current terminal and attach it to +.Ar target-session . +If used from inside, switch the current client. If .Fl d is specified, any other clients attached to the session are detached. diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index ba67dc05c81..70f423d7cf3 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.34 2009/07/17 07:05:58 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.35 2009/07/17 15:03:11 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -835,8 +835,18 @@ struct client_ctx { struct cmd_ctx { struct client *cmdclient; + /* + * curclient is the client where this command was executed if inside + * tmux. This is NULL if the command came from the command-line. + * + * cmdclient is the client which sent the MSG_COMMAND to the server, if + * any. This is NULL unless the command came from the command-line. + * + * One of curclient or cmdclient is always NULL and the other not. + */ struct client *curclient; struct session *cursession; + struct msg_command_data *msgdata; void (*print)(struct cmd_ctx *, const char *, ...); |