1/* $Id: cmd-choose-session.c,v 1.1.1.2 2011/08/17 18:40:04 jmmv Exp $ */
2
3/*
4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <ctype.h>
22
23#include "tmux.h"
24
25/*
26 * Enter choice mode to choose a session.
27 */
28
29int	cmd_choose_session_exec(struct cmd *, struct cmd_ctx *);
30
31void	cmd_choose_session_callback(void *, int);
32void	cmd_choose_session_free(void *);
33
34const struct cmd_entry cmd_choose_session_entry = {
35	"choose-session", NULL,
36	"t:", 0, 1,
37	CMD_TARGET_WINDOW_USAGE " [template]",
38	0,
39	NULL,
40	NULL,
41	cmd_choose_session_exec
42};
43
44struct cmd_choose_session_data {
45	struct client	*client;
46	char   		*template;
47};
48
49int
50cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
51{
52	struct args			*args = self->args;
53	struct cmd_choose_session_data	*cdata;
54	struct winlink			*wl;
55	struct session			*s;
56	struct session_group		*sg;
57	u_int			 	 idx, sgidx, cur;
58	char				 tmp[64];
59
60	if (ctx->curclient == NULL) {
61		ctx->error(ctx, "must be run interactively");
62		return (-1);
63	}
64
65	if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
66		return (-1);
67
68	if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
69		return (0);
70
71	cur = idx = 0;
72	RB_FOREACH(s, sessions, &sessions) {
73		if (s == ctx->curclient->session)
74			cur = idx;
75		idx++;
76
77		sg = session_group_find(s);
78		if (sg == NULL)
79			*tmp = '\0';
80		else {
81			sgidx = session_group_index(sg);
82			xsnprintf(tmp, sizeof tmp, " (group %u)", sgidx);
83		}
84
85		window_choose_add(wl->window->active, s->idx,
86		    "%s: %u windows [%ux%u]%s%s", s->name,
87		    winlink_count(&s->windows), s->sx, s->sy,
88		    tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
89	}
90
91	cdata = xmalloc(sizeof *cdata);
92	if (args->argc != 0)
93		cdata->template = xstrdup(args->argv[0]);
94	else
95		cdata->template = xstrdup("switch-client -t '%%'");
96	cdata->client = ctx->curclient;
97	cdata->client->references++;
98
99	window_choose_ready(wl->window->active,
100	    cur, cmd_choose_session_callback, cmd_choose_session_free, cdata);
101
102	return (0);
103}
104
105void
106cmd_choose_session_callback(void *data, int idx)
107{
108	struct cmd_choose_session_data	*cdata = data;
109	struct session			*s;
110	struct cmd_list			*cmdlist;
111	struct cmd_ctx			 ctx;
112	char				*template, *cause;
113
114	if (idx == -1)
115		return;
116	if (cdata->client->flags & CLIENT_DEAD)
117		return;
118
119	s = session_find_by_index(idx);
120	if (s == NULL)
121		return;
122	template = cmd_template_replace(cdata->template, s->name, 1);
123
124	if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
125		if (cause != NULL) {
126			*cause = toupper((u_char) *cause);
127			status_message_set(cdata->client, "%s", cause);
128			xfree(cause);
129		}
130		xfree(template);
131		return;
132	}
133	xfree(template);
134
135	ctx.msgdata = NULL;
136	ctx.curclient = cdata->client;
137
138	ctx.error = key_bindings_error;
139	ctx.print = key_bindings_print;
140	ctx.info = key_bindings_info;
141
142	ctx.cmdclient = NULL;
143
144	cmd_list_exec(cmdlist, &ctx);
145	cmd_list_free(cmdlist);
146}
147
148void
149cmd_choose_session_free(void *data)
150{
151	struct cmd_choose_session_data	*cdata = data;
152
153	cdata->client->references--;
154	xfree(cdata->template);
155	xfree(cdata);
156}
157