xref: /openbsd-src/usr.bin/tmux/cmd-command-prompt.c (revision f475c9a8023e1649f1acc2955f6e5f14a07fdf12)
1 /* $OpenBSD: cmd-command-prompt.c,v 1.5 2009/07/20 07:31:10 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2008 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 #include <string.h>
23 
24 #include "tmux.h"
25 
26 /*
27  * Prompt for command in client.
28  */
29 
30 void	cmd_command_prompt_init(struct cmd *, int);
31 int	cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
32 
33 int	cmd_command_prompt_callback(void *, const char *);
34 void	cmd_command_prompt_free(void *);
35 
36 const struct cmd_entry cmd_command_prompt_entry = {
37 	"command-prompt", NULL,
38 	CMD_TARGET_CLIENT_USAGE " [template]",
39 	CMD_ARG01, 0,
40 	cmd_command_prompt_init,
41 	cmd_target_parse,
42 	cmd_command_prompt_exec,
43 	cmd_target_send,
44 	cmd_target_recv,
45 	cmd_target_free,
46 	cmd_target_print
47 };
48 
49 struct cmd_command_prompt_data {
50 	struct client	*c;
51 	char		*template;
52 };
53 
54 void
55 cmd_command_prompt_init(struct cmd *self, int key)
56 {
57 	struct cmd_target_data	*data;
58 
59 	cmd_target_init(self, key);
60 	data = self->data;
61 
62 	switch (key) {
63 	case ',':
64 		data->arg = xstrdup("rename-window '%%'");
65 		break;
66 	case '.':
67 		data->arg = xstrdup("move-window -t '%%'");
68 		break;
69 	case 'f':
70 		data->arg = xstrdup("find-window '%%'");
71 		break;
72 	}
73 }
74 
75 int
76 cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
77 {
78 	struct cmd_target_data		*data = self->data;
79 	struct cmd_command_prompt_data	*cdata;
80 	struct client			*c;
81 	char				*hdr, *ptr;
82 
83 	if ((c = cmd_find_client(ctx, data->target)) == NULL)
84 		return (-1);
85 
86 	if (c->prompt_string != NULL)
87 		return (0);
88 
89 	cdata = xmalloc(sizeof *cdata);
90 	cdata->c = c;
91 	if (data->arg != NULL) {
92 		cdata->template = xstrdup(data->arg);
93 		if ((ptr = strchr(data->arg, ' ')) == NULL)
94 			ptr = strchr(data->arg, '\0');
95 		xasprintf(&hdr, "(%.*s) ", (int) (ptr - data->arg), data->arg);
96 	} else {
97 		cdata->template = NULL;
98 		hdr = xstrdup(":");
99 	}
100 	status_prompt_set(c, hdr,
101 	    cmd_command_prompt_callback, cmd_command_prompt_free, cdata, 0);
102 	xfree(hdr);
103 
104 	return (0);
105 }
106 
107 int
108 cmd_command_prompt_callback(void *data, const char *s)
109 {
110 	struct cmd_command_prompt_data	*cdata = data;
111 	struct client			*c = cdata->c;
112 	struct cmd_list			*cmdlist;
113 	struct cmd_ctx	 		 ctx;
114 	char				*cause, *ptr, *buf, ch;
115 	size_t				 len, slen;
116 
117 	if (s == NULL)
118 		return (0);
119 	slen = strlen(s);
120 
121 	len = 0;
122 	buf = NULL;
123 	if (cdata->template != NULL) {
124 		ptr = cdata->template;
125 		while (*ptr != '\0') {
126 			switch (ch = *ptr++) {
127 			case '%':
128 				if (*ptr != '%')
129 					break;
130 				ptr++;
131 
132 				buf = xrealloc(buf, 1, len + slen + 1);
133 				memcpy(buf + len, s, slen);
134 				len += slen;
135 				break;
136 			default:
137 				buf = xrealloc(buf, 1, len + 2);
138 				buf[len++] = ch;
139 				break;
140 			}
141 		}
142 
143 		if (buf == NULL)
144 			return (0);
145 		buf[len] = '\0';
146 		s = buf;
147 	}
148 
149 	if (cmd_string_parse(s, &cmdlist, &cause) != 0) {
150 		if (cause == NULL)
151 			return (0);
152 		*cause = toupper((u_char) *cause);
153 		status_message_set(c, "%s", cause);
154 		xfree(cause);
155 		cmdlist = NULL;
156 	}
157 	if (buf != NULL)
158 		xfree(buf);
159 	if (cmdlist == NULL)
160 		return (0);
161 
162 	ctx.msgdata = NULL;
163 	ctx.cursession = c->session;
164 	ctx.curclient = c;
165 
166 	ctx.error = key_bindings_error;
167 	ctx.print = key_bindings_print;
168 	ctx.info = key_bindings_info;
169 
170 	ctx.cmdclient = NULL;
171 
172 	cmd_list_exec(cmdlist, &ctx);
173 	cmd_list_free(cmdlist);
174 
175 	if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
176 		return (1);
177 	return (0);
178 }
179 
180 void
181 cmd_command_prompt_free(void *data)
182 {
183 	struct cmd_command_prompt_data	*cdata = data;
184 
185 	if (cdata->template != NULL)
186 		xfree(cdata->template);
187 	xfree(cdata);
188 }
189