xref: /minix3/external/bsd/tmux/dist/cmd-command-prompt.c (revision eda6f5931d42c77e1480347b1fc3eef2f8d33806)
1*eda6f593SDavid van Moolenbroek /* $Id: cmd-command-prompt.c,v 1.1.1.2 2011/08/17 18:40:04 jmmv Exp $ */
2*eda6f593SDavid van Moolenbroek 
3*eda6f593SDavid van Moolenbroek /*
4*eda6f593SDavid van Moolenbroek  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
5*eda6f593SDavid van Moolenbroek  *
6*eda6f593SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
7*eda6f593SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*eda6f593SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*eda6f593SDavid van Moolenbroek  *
10*eda6f593SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*eda6f593SDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*eda6f593SDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*eda6f593SDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*eda6f593SDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15*eda6f593SDavid van Moolenbroek  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16*eda6f593SDavid van Moolenbroek  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*eda6f593SDavid van Moolenbroek  */
18*eda6f593SDavid van Moolenbroek 
19*eda6f593SDavid van Moolenbroek #include <sys/types.h>
20*eda6f593SDavid van Moolenbroek 
21*eda6f593SDavid van Moolenbroek #include <ctype.h>
22*eda6f593SDavid van Moolenbroek #include <string.h>
23*eda6f593SDavid van Moolenbroek #include <time.h>
24*eda6f593SDavid van Moolenbroek 
25*eda6f593SDavid van Moolenbroek #include "tmux.h"
26*eda6f593SDavid van Moolenbroek 
27*eda6f593SDavid van Moolenbroek /*
28*eda6f593SDavid van Moolenbroek  * Prompt for command in client.
29*eda6f593SDavid van Moolenbroek  */
30*eda6f593SDavid van Moolenbroek 
31*eda6f593SDavid van Moolenbroek void	cmd_command_prompt_key_binding(struct cmd *, int);
32*eda6f593SDavid van Moolenbroek int	cmd_command_prompt_check(struct args *);
33*eda6f593SDavid van Moolenbroek int	cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
34*eda6f593SDavid van Moolenbroek 
35*eda6f593SDavid van Moolenbroek int	cmd_command_prompt_callback(void *, const char *);
36*eda6f593SDavid van Moolenbroek void	cmd_command_prompt_free(void *);
37*eda6f593SDavid van Moolenbroek 
38*eda6f593SDavid van Moolenbroek const struct cmd_entry cmd_command_prompt_entry = {
39*eda6f593SDavid van Moolenbroek 	"command-prompt", NULL,
40*eda6f593SDavid van Moolenbroek 	"I:p:t:", 0, 1,
41*eda6f593SDavid van Moolenbroek 	"[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
42*eda6f593SDavid van Moolenbroek 	0,
43*eda6f593SDavid van Moolenbroek 	cmd_command_prompt_key_binding,
44*eda6f593SDavid van Moolenbroek 	NULL,
45*eda6f593SDavid van Moolenbroek 	cmd_command_prompt_exec
46*eda6f593SDavid van Moolenbroek };
47*eda6f593SDavid van Moolenbroek 
48*eda6f593SDavid van Moolenbroek struct cmd_command_prompt_cdata {
49*eda6f593SDavid van Moolenbroek 	struct client	*c;
50*eda6f593SDavid van Moolenbroek 	char		*inputs;
51*eda6f593SDavid van Moolenbroek 	char		*next_input;
52*eda6f593SDavid van Moolenbroek 	char		*next_prompt;
53*eda6f593SDavid van Moolenbroek 	char		*prompts;
54*eda6f593SDavid van Moolenbroek 	char		*template;
55*eda6f593SDavid van Moolenbroek 	int		 idx;
56*eda6f593SDavid van Moolenbroek };
57*eda6f593SDavid van Moolenbroek 
58*eda6f593SDavid van Moolenbroek void
59*eda6f593SDavid van Moolenbroek cmd_command_prompt_key_binding(struct cmd *self, int key)
60*eda6f593SDavid van Moolenbroek {
61*eda6f593SDavid van Moolenbroek 	switch (key) {
62*eda6f593SDavid van Moolenbroek 	case '$':
63*eda6f593SDavid van Moolenbroek 		self->args = args_create(1, "rename-session '%%'");
64*eda6f593SDavid van Moolenbroek 		args_set(self->args, 'I', "#S");
65*eda6f593SDavid van Moolenbroek 		break;
66*eda6f593SDavid van Moolenbroek 	case ',':
67*eda6f593SDavid van Moolenbroek 		self->args = args_create(1, "rename-window '%%'");
68*eda6f593SDavid van Moolenbroek 		args_set(self->args, 'I', "#W");
69*eda6f593SDavid van Moolenbroek 		break;
70*eda6f593SDavid van Moolenbroek 	case '.':
71*eda6f593SDavid van Moolenbroek 		self->args = args_create(1, "move-window -t '%%'");
72*eda6f593SDavid van Moolenbroek 		break;
73*eda6f593SDavid van Moolenbroek 	case 'f':
74*eda6f593SDavid van Moolenbroek 		self->args = args_create(1, "find-window '%%'");
75*eda6f593SDavid van Moolenbroek 		break;
76*eda6f593SDavid van Moolenbroek 	case '\'':
77*eda6f593SDavid van Moolenbroek 		self->args = args_create(1, "select-window -t ':%%'");
78*eda6f593SDavid van Moolenbroek 		args_set(self->args, 'p', "index");
79*eda6f593SDavid van Moolenbroek 		break;
80*eda6f593SDavid van Moolenbroek 	default:
81*eda6f593SDavid van Moolenbroek 		self->args = args_create(0);
82*eda6f593SDavid van Moolenbroek 		break;
83*eda6f593SDavid van Moolenbroek 	}
84*eda6f593SDavid van Moolenbroek }
85*eda6f593SDavid van Moolenbroek 
86*eda6f593SDavid van Moolenbroek int
87*eda6f593SDavid van Moolenbroek cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
88*eda6f593SDavid van Moolenbroek {
89*eda6f593SDavid van Moolenbroek 	struct args			*args = self->args;
90*eda6f593SDavid van Moolenbroek 	const char			*inputs, *prompts;
91*eda6f593SDavid van Moolenbroek 	struct cmd_command_prompt_cdata	*cdata;
92*eda6f593SDavid van Moolenbroek 	struct client			*c;
93*eda6f593SDavid van Moolenbroek 	char				*prompt, *ptr, *input = NULL;
94*eda6f593SDavid van Moolenbroek 	size_t				 n;
95*eda6f593SDavid van Moolenbroek 
96*eda6f593SDavid van Moolenbroek 	if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
97*eda6f593SDavid van Moolenbroek 		return (-1);
98*eda6f593SDavid van Moolenbroek 
99*eda6f593SDavid van Moolenbroek 	if (c->prompt_string != NULL)
100*eda6f593SDavid van Moolenbroek 		return (0);
101*eda6f593SDavid van Moolenbroek 
102*eda6f593SDavid van Moolenbroek 	cdata = xmalloc(sizeof *cdata);
103*eda6f593SDavid van Moolenbroek 	cdata->c = c;
104*eda6f593SDavid van Moolenbroek 	cdata->idx = 1;
105*eda6f593SDavid van Moolenbroek 	cdata->inputs = NULL;
106*eda6f593SDavid van Moolenbroek 	cdata->next_input = NULL;
107*eda6f593SDavid van Moolenbroek 	cdata->next_prompt = NULL;
108*eda6f593SDavid van Moolenbroek 	cdata->prompts = NULL;
109*eda6f593SDavid van Moolenbroek 	cdata->template = NULL;
110*eda6f593SDavid van Moolenbroek 
111*eda6f593SDavid van Moolenbroek 	if (args->argc != 0)
112*eda6f593SDavid van Moolenbroek 		cdata->template = xstrdup(args->argv[0]);
113*eda6f593SDavid van Moolenbroek 	else
114*eda6f593SDavid van Moolenbroek 		cdata->template = xstrdup("%1");
115*eda6f593SDavid van Moolenbroek 
116*eda6f593SDavid van Moolenbroek 	if ((prompts = args_get(args, 'p')) != NULL)
117*eda6f593SDavid van Moolenbroek 		cdata->prompts = xstrdup(prompts);
118*eda6f593SDavid van Moolenbroek 	else if (args->argc != 0) {
119*eda6f593SDavid van Moolenbroek 		n = strcspn(cdata->template, " ,");
120*eda6f593SDavid van Moolenbroek 		xasprintf(&cdata->prompts, "(%.*s) ", (int) n, cdata->template);
121*eda6f593SDavid van Moolenbroek 	} else
122*eda6f593SDavid van Moolenbroek 		cdata->prompts = xstrdup(":");
123*eda6f593SDavid van Moolenbroek 
124*eda6f593SDavid van Moolenbroek 	/* Get first prompt. */
125*eda6f593SDavid van Moolenbroek 	cdata->next_prompt = cdata->prompts;
126*eda6f593SDavid van Moolenbroek 	ptr = strsep(&cdata->next_prompt, ",");
127*eda6f593SDavid van Moolenbroek 	if (prompts == NULL)
128*eda6f593SDavid van Moolenbroek 		prompt = xstrdup(ptr);
129*eda6f593SDavid van Moolenbroek 	else
130*eda6f593SDavid van Moolenbroek 		xasprintf(&prompt, "%s ", ptr);
131*eda6f593SDavid van Moolenbroek 
132*eda6f593SDavid van Moolenbroek 	/* Get initial prompt input. */
133*eda6f593SDavid van Moolenbroek 	if ((inputs = args_get(args, 'I')) != NULL) {
134*eda6f593SDavid van Moolenbroek 		cdata->inputs = xstrdup(inputs);
135*eda6f593SDavid van Moolenbroek 		cdata->next_input = cdata->inputs;
136*eda6f593SDavid van Moolenbroek 		input = strsep(&cdata->next_input, ",");
137*eda6f593SDavid van Moolenbroek 	}
138*eda6f593SDavid van Moolenbroek 
139*eda6f593SDavid van Moolenbroek 	status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
140*eda6f593SDavid van Moolenbroek 	    cmd_command_prompt_free, cdata, 0);
141*eda6f593SDavid van Moolenbroek 	xfree(prompt);
142*eda6f593SDavid van Moolenbroek 
143*eda6f593SDavid van Moolenbroek 	return (0);
144*eda6f593SDavid van Moolenbroek }
145*eda6f593SDavid van Moolenbroek 
146*eda6f593SDavid van Moolenbroek int
147*eda6f593SDavid van Moolenbroek cmd_command_prompt_callback(void *data, const char *s)
148*eda6f593SDavid van Moolenbroek {
149*eda6f593SDavid van Moolenbroek 	struct cmd_command_prompt_cdata	*cdata = data;
150*eda6f593SDavid van Moolenbroek 	struct client			*c = cdata->c;
151*eda6f593SDavid van Moolenbroek 	struct cmd_list			*cmdlist;
152*eda6f593SDavid van Moolenbroek 	struct cmd_ctx			 ctx;
153*eda6f593SDavid van Moolenbroek 	char				*cause, *new_template, *prompt, *ptr;
154*eda6f593SDavid van Moolenbroek 	char				*input = NULL;
155*eda6f593SDavid van Moolenbroek 
156*eda6f593SDavid van Moolenbroek 	if (s == NULL)
157*eda6f593SDavid van Moolenbroek 		return (0);
158*eda6f593SDavid van Moolenbroek 
159*eda6f593SDavid van Moolenbroek 	new_template = cmd_template_replace(cdata->template, s, cdata->idx);
160*eda6f593SDavid van Moolenbroek 	xfree(cdata->template);
161*eda6f593SDavid van Moolenbroek 	cdata->template = new_template;
162*eda6f593SDavid van Moolenbroek 
163*eda6f593SDavid van Moolenbroek 	/*
164*eda6f593SDavid van Moolenbroek 	 * Check if there are more prompts; if so, get its respective input
165*eda6f593SDavid van Moolenbroek 	 * and update the prompt data.
166*eda6f593SDavid van Moolenbroek 	 */
167*eda6f593SDavid van Moolenbroek 	if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
168*eda6f593SDavid van Moolenbroek 		xasprintf(&prompt, "%s ", ptr);
169*eda6f593SDavid van Moolenbroek 		input = strsep(&cdata->next_input, ",");
170*eda6f593SDavid van Moolenbroek 		status_prompt_update(c, prompt, input);
171*eda6f593SDavid van Moolenbroek 
172*eda6f593SDavid van Moolenbroek 		xfree(prompt);
173*eda6f593SDavid van Moolenbroek 		cdata->idx++;
174*eda6f593SDavid van Moolenbroek 		return (1);
175*eda6f593SDavid van Moolenbroek 	}
176*eda6f593SDavid van Moolenbroek 
177*eda6f593SDavid van Moolenbroek 	if (cmd_string_parse(new_template, &cmdlist, &cause) != 0) {
178*eda6f593SDavid van Moolenbroek 		if (cause != NULL) {
179*eda6f593SDavid van Moolenbroek 			*cause = toupper((u_char) *cause);
180*eda6f593SDavid van Moolenbroek 			status_message_set(c, "%s", cause);
181*eda6f593SDavid van Moolenbroek 			xfree(cause);
182*eda6f593SDavid van Moolenbroek 		}
183*eda6f593SDavid van Moolenbroek 		return (0);
184*eda6f593SDavid van Moolenbroek 	}
185*eda6f593SDavid van Moolenbroek 
186*eda6f593SDavid van Moolenbroek 	ctx.msgdata = NULL;
187*eda6f593SDavid van Moolenbroek 	ctx.curclient = c;
188*eda6f593SDavid van Moolenbroek 
189*eda6f593SDavid van Moolenbroek 	ctx.error = key_bindings_error;
190*eda6f593SDavid van Moolenbroek 	ctx.print = key_bindings_print;
191*eda6f593SDavid van Moolenbroek 	ctx.info = key_bindings_info;
192*eda6f593SDavid van Moolenbroek 
193*eda6f593SDavid van Moolenbroek 	ctx.cmdclient = NULL;
194*eda6f593SDavid van Moolenbroek 
195*eda6f593SDavid van Moolenbroek 	cmd_list_exec(cmdlist, &ctx);
196*eda6f593SDavid van Moolenbroek 	cmd_list_free(cmdlist);
197*eda6f593SDavid van Moolenbroek 
198*eda6f593SDavid van Moolenbroek 	if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
199*eda6f593SDavid van Moolenbroek 		return (1);
200*eda6f593SDavid van Moolenbroek 	return (0);
201*eda6f593SDavid van Moolenbroek }
202*eda6f593SDavid van Moolenbroek 
203*eda6f593SDavid van Moolenbroek void
204*eda6f593SDavid van Moolenbroek cmd_command_prompt_free(void *data)
205*eda6f593SDavid van Moolenbroek {
206*eda6f593SDavid van Moolenbroek 	struct cmd_command_prompt_cdata	*cdata = data;
207*eda6f593SDavid van Moolenbroek 
208*eda6f593SDavid van Moolenbroek 	if (cdata->inputs != NULL)
209*eda6f593SDavid van Moolenbroek 		xfree(cdata->inputs);
210*eda6f593SDavid van Moolenbroek 	if (cdata->prompts != NULL)
211*eda6f593SDavid van Moolenbroek 		xfree(cdata->prompts);
212*eda6f593SDavid van Moolenbroek 	if (cdata->template != NULL)
213*eda6f593SDavid van Moolenbroek 		xfree(cdata->template);
214*eda6f593SDavid van Moolenbroek 	xfree(cdata);
215*eda6f593SDavid van Moolenbroek }
216