From 6e0452459640b892e8fc2ea7435f5e847cc33967 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 16 Nov 2007 21:31:03 +0000 Subject: [PATCH] switch-client command. --- CHANGES | 9 ++- GNUmakefile | 5 +- Makefile | 5 +- TODO | 3 + cmd-switch-client.c | 133 ++++++++++++++++++++++++++++++++++++++++++++ cmd.c | 3 +- server-msg.c | 16 +++--- tmux.h | 3 +- 8 files changed, 163 insertions(+), 14 deletions(-) create mode 100644 cmd-switch-client.c diff --git a/CHANGES b/CHANGES index ae1b9a30..5738c752 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,12 @@ 16 November 2007 +* (nicm) switch-client command to switch client between different sessions. This + is pretty cool: + + $ tmux bind q switch 0 + $ tmux bind w switch 1 + + To switch between sessions 0 and 1 with a key :-). * (nicm) Accept "-c client-tty" on command line to allow client manipulation commands, and change detach-/refresh-session to detach-/refresh-client (this loses the -a behaviour, but at some point -session versions may return, and @@ -214,4 +221,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.69 2007-11-16 21:12:31 nicm Exp $ +$Id: CHANGES,v 1.70 2007-11-16 21:31:03 nicm Exp $ diff --git a/GNUmakefile b/GNUmakefile index 186eef67..2378fd34 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,4 +1,4 @@ -# $Id: GNUmakefile,v 1.4 2007-11-16 21:12:31 nicm Exp $ +# $Id: GNUmakefile,v 1.5 2007-11-16 21:31:03 nicm Exp $ .PHONY: clean @@ -21,7 +21,8 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-list-windows.c cmd-attach-session.c cmd-send-prefix.c \ cmd-refresh-client.c cmd-kill-window.c cmd-list-clients.c \ cmd-has-session.c cmd-link-window.c cmd-unlink-window.c \ - cmd-swap-window.c cmd-rename-session.c + cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \ + cmd-switch-client.c CC?= gcc INCDIRS+= -I. -I- diff --git a/Makefile b/Makefile index 5ca34443..430fc86f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.40 2007-11-16 21:12:31 nicm Exp $ +# $Id: Makefile,v 1.41 2007-11-16 21:31:03 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean @@ -25,7 +25,8 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-list-windows.c cmd-attach-session.c cmd-send-prefix.c \ cmd-refresh-client.c cmd-kill-window.c cmd-list-clients.c \ cmd-has-session.c cmd-link-window.c cmd-unlink-window.c \ - cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c + cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \ + cmd-switch-client.c CC?= cc INCDIRS+= -I. -I- -I/usr/local/include diff --git a/TODO b/TODO index 49b0441b..0bf42b5f 100644 --- a/TODO +++ b/TODO @@ -63,6 +63,9 @@ - function groups, bind-key ^W { select-window 0; send-key ^W } etc - more(1) style handling for in-client output - allow fnmatch for -c, so that you can, eg, detach all clients +- session specification is all over the place. some things use -s before cmd, + some -s after, some no -s, there are various uses of -n. the differences are + sort of logical, but confusing. needs rethought -- For 0.1 -------------------------------------------------------------------- - diff --git a/cmd-switch-client.c b/cmd-switch-client.c new file mode 100644 index 00000000..2d3788b7 --- /dev/null +++ b/cmd-switch-client.c @@ -0,0 +1,133 @@ +/* $Id: cmd-switch-client.c,v 1.1 2007-11-16 21:31:03 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +#include "tmux.h" + +/* + * Switch client to a different session. + */ + +int cmd_switch_client_parse(void **, int, char **, char **); +void cmd_switch_client_exec(void *, struct cmd_ctx *); +void cmd_switch_client_send(void *, struct buffer *); +void cmd_switch_client_recv(void **, struct buffer *); +void cmd_switch_client_free(void *); + +struct cmd_switch_client_data { + char *name; +}; + +const struct cmd_entry cmd_switch_client_entry = { + "switch-client", "switchc", "session-name", + CMD_NOSESSION, + cmd_switch_client_parse, + cmd_switch_client_exec, + cmd_switch_client_send, + cmd_switch_client_recv, + cmd_switch_client_free +}; + +int +cmd_switch_client_parse(void **ptr, int argc, char **argv, char **cause) +{ + struct cmd_switch_client_data *data; + int opt; + + *ptr = data = xmalloc(sizeof *data); + data->name = NULL; + + while ((opt = getopt(argc, argv, "")) != EOF) { + switch (opt) { + default: + goto usage; + } + } + argc -= optind; + argv += optind; + if (argc != 1) + goto usage; + + data->name = xstrdup(argv[0]); + + return (0); + +usage: + usage(cause, "%s %s", + cmd_switch_client_entry.name, cmd_switch_client_entry.usage); + + cmd_switch_client_free(data); + return (-1); +} + +void +cmd_switch_client_exec(void *ptr, struct cmd_ctx *ctx) +{ + struct cmd_switch_client_data *data = ptr; + struct session *s; + + if (data == NULL) + return; + + if ((s = session_find(data->name)) == NULL) { + ctx->error(ctx, "session not found: %s", data->name); + return; + } + + ctx->client->session = s; + + recalculate_sizes(); + server_redraw_client(ctx->client); + + if (ctx->cmdclient != NULL) + server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); +} + +void +cmd_switch_client_send(void *ptr, struct buffer *b) +{ + struct cmd_switch_client_data *data = ptr; + + buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->name); +} + +void +cmd_switch_client_recv(void **ptr, struct buffer *b) +{ + struct cmd_switch_client_data *data; + + *ptr = data = xmalloc(sizeof *data); + buffer_read(b, data, sizeof *data); + data->name = cmd_recv_string(b); +} + +void +cmd_switch_client_free(void *ptr) +{ + struct cmd_switch_client_data *data = ptr; + + if (data->name != NULL) + xfree(data->name); + xfree(data); +} diff --git a/cmd.c b/cmd.c index 084f6bf8..0be6aebb 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.28 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd.c,v 1.29 2007-11-16 21:31:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -47,6 +47,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_send_prefix_entry, &cmd_set_option_entry, &cmd_swap_window_entry, + &cmd_switch_client_entry, &cmd_unbind_key_entry, &cmd_unlink_window_entry, NULL diff --git a/server-msg.c b/server-msg.c index 7c132d7a..3af04de8 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,4 @@ -/* $Id: server-msg.c,v 1.31 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: server-msg.c,v 1.32 2007-11-16 21:31:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -111,6 +111,8 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) char *name, *client, *cause; u_int i; + /* XXX I hate this function. Split it? */ + if (hdr->size < sizeof data) fatalx("bad MSG_COMMAND size"); buffer_read(c->in, &data, sizeof data); @@ -141,8 +143,8 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) } } else { if (client == NULL) { - server_msg_fn_command_error(&ctx, "%s: must " - "specify a client: %s", cmd->entry->name, client); + server_msg_fn_command_error(&ctx, + "%s: must specify a client: %s", cmd->entry->name); goto out; } for (i = 0; i < ARRAY_LENGTH(&clients); i++) { @@ -158,15 +160,15 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) } } - ctx.session = server_extract_session(&data, name, &cause); + ctx.session = NULL; if (cmd->entry->flags & CMD_NOSESSION) { - if (ctx.session != NULL) { + if (name != NULL) { server_msg_fn_command_error(&ctx, "%s: cannot specify a session", cmd->entry->name); goto out; - } else - xfree(cause); + } } else { + ctx.session = server_extract_session(&data, name, &cause); if (ctx.session == NULL) { server_msg_fn_command_error( &ctx, "%s: %s", cmd->entry->name, cause); diff --git a/tmux.h b/tmux.h index fac858a3..289fa582 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.80 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: tmux.h,v 1.81 2007-11-16 21:31:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -593,6 +593,7 @@ extern const struct cmd_entry cmd_select_window_entry; extern const struct cmd_entry cmd_send_prefix_entry; extern const struct cmd_entry cmd_set_option_entry; extern const struct cmd_entry cmd_swap_window_entry; +extern const struct cmd_entry cmd_switch_client_entry; extern const struct cmd_entry cmd_unbind_key_entry; extern const struct cmd_entry cmd_unlink_window_entry; void cmd_select_window_default(void **, int);