Annotation of src/usr.bin/tmux/cmd-command-prompt.c, Revision 1.9
1.9 ! nicm 1: /* $OpenBSD: cmd-command-prompt.c,v 1.8 2009/08/19 10:39:50 nicm Exp $ */
1.1 nicm 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:
1.8 nicm 30: void cmd_command_prompt_init(struct cmd *, int);
31: int cmd_command_prompt_parse(struct cmd *, int, char **, char **);
32: int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
33: void cmd_command_prompt_free(struct cmd *);
34: size_t cmd_command_prompt_print(struct cmd *, char *, size_t);
35:
36: int cmd_command_prompt_callback(void *, const char *);
37: void cmd_command_prompt_cfree(void *);
38: char *cmd_command_prompt_replace(char *, const char *, int);
1.1 nicm 39:
40: const struct cmd_entry cmd_command_prompt_entry = {
41: "command-prompt", NULL,
1.8 nicm 42: CMD_TARGET_CLIENT_USAGE " [-p prompts] [template]",
43: 0, 0,
1.1 nicm 44: cmd_command_prompt_init,
1.8 nicm 45: cmd_command_prompt_parse,
1.1 nicm 46: cmd_command_prompt_exec,
1.8 nicm 47: cmd_command_prompt_free,
48: cmd_command_prompt_print
1.1 nicm 49: };
50:
51: struct cmd_command_prompt_data {
1.8 nicm 52: char *prompts;
53: char *target;
54: char *template;
55: };
56:
57: struct cmd_command_prompt_cdata {
1.1 nicm 58: struct client *c;
1.8 nicm 59: char *next_prompt;
60: char *prompts;
1.1 nicm 61: char *template;
1.8 nicm 62: int idx;
1.1 nicm 63: };
64:
65: void
66: cmd_command_prompt_init(struct cmd *self, int key)
67: {
1.8 nicm 68: struct cmd_command_prompt_data *data;
1.1 nicm 69:
1.8 nicm 70: self->data = data = xmalloc(sizeof *data);
71: data->prompts = NULL;
72: data->target = NULL;
73: data->template = NULL;
1.1 nicm 74:
75: switch (key) {
76: case ',':
1.8 nicm 77: data->template = xstrdup("rename-window '%%'");
1.1 nicm 78: break;
79: case '.':
1.8 nicm 80: data->template = xstrdup("move-window -t '%%'");
1.1 nicm 81: break;
82: case 'f':
1.8 nicm 83: data->template = xstrdup("find-window '%%'");
1.1 nicm 84: break;
85: }
86: }
87:
88: int
1.8 nicm 89: cmd_command_prompt_parse(struct cmd *self, int argc, char **argv, char **cause)
90: {
91: struct cmd_command_prompt_data *data;
92: int opt;
93:
94: self->entry->init(self, 0);
95: data = self->data;
96:
97: while ((opt = getopt(argc, argv, "p:t:")) != -1) {
98: switch (opt) {
99: case 'p':
100: if (data->prompts == NULL)
101: data->prompts = xstrdup(optarg);
102: break;
103: case 't':
104: if (data->target == NULL)
105: data->target = xstrdup(optarg);
106: break;
107: default:
108: goto usage;
109: }
110: }
111: argc -= optind;
112: argv += optind;
113: if (argc != 0 && argc != 1)
114: goto usage;
115:
116: if (argc == 1)
117: data->template = xstrdup(argv[0]);
118:
119: return (0);
120:
121: usage:
122: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
123:
124: self->entry->free(self);
125: return (-1);
126: }
127:
128: int
1.1 nicm 129: cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
130: {
1.8 nicm 131: struct cmd_command_prompt_data *data = self->data;
132: struct cmd_command_prompt_cdata *cdata;
1.1 nicm 133: struct client *c;
1.8 nicm 134: char *prompt, *ptr;
135: size_t n;
1.1 nicm 136:
137: if ((c = cmd_find_client(ctx, data->target)) == NULL)
138: return (-1);
139:
140: if (c->prompt_string != NULL)
141: return (0);
142:
143: cdata = xmalloc(sizeof *cdata);
144: cdata->c = c;
1.8 nicm 145: cdata->idx = 1;
146: cdata->next_prompt = NULL;
147: cdata->prompts = NULL;
148: cdata->template = NULL;
149:
150: if (data->template != NULL)
151: cdata->template = xstrdup(data->template);
152: else
153: cdata->template = xstrdup("%1");
154: if (data->prompts != NULL)
155: cdata->prompts = xstrdup(data->prompts);
156: else if (data->template != NULL) {
157: n = strcspn(data->template, " ,");
158: xasprintf(&cdata->prompts, "(%.*s) ", (int) n, data->template);
159: } else
160: cdata->prompts = xstrdup(":");
161:
162: cdata->next_prompt = cdata->prompts;
163: ptr = strsep(&cdata->next_prompt, ",");
164: if (data->prompts == NULL)
165: prompt = xstrdup(ptr);
166: else
167: xasprintf(&prompt, "%s ", ptr);
168: status_prompt_set(c, prompt, cmd_command_prompt_callback,
169: cmd_command_prompt_cfree, cdata, 0);
170: xfree(prompt);
1.1 nicm 171:
172: return (0);
173: }
174:
1.8 nicm 175: void
176: cmd_command_prompt_free(struct cmd *self)
177: {
178: struct cmd_command_prompt_data *data = self->data;
179:
180: if (data->prompts != NULL)
181: xfree(data->prompts);
182: if (data->target != NULL)
183: xfree(data->target);
184: if (data->template != NULL)
185: xfree(data->template);
186: xfree(data);
187: }
188:
189: size_t
190: cmd_command_prompt_print(struct cmd *self, char *buf, size_t len)
191: {
192: struct cmd_command_prompt_data *data = self->data;
193: size_t off = 0;
194:
195: off += xsnprintf(buf, len, "%s", self->entry->name);
196: if (data == NULL)
197: return (off);
198: if (off < len && data->prompts != NULL)
199: off += cmd_prarg(buf + off, len - off, " -p ", data->prompts);
200: if (off < len && data->target != NULL)
201: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
202: if (off < len && data->template != NULL)
203: off += cmd_prarg(buf + off, len - off, " ", data->template);
204: return (off);
205: }
206:
1.1 nicm 207: int
208: cmd_command_prompt_callback(void *data, const char *s)
209: {
1.8 nicm 210: struct cmd_command_prompt_cdata *cdata = data;
1.1 nicm 211: struct client *c = cdata->c;
212: struct cmd_list *cmdlist;
1.8 nicm 213: struct cmd_ctx ctx;
214: char *cause, *newtempl, *prompt, *ptr;
1.1 nicm 215:
1.8 nicm 216: if (s == NULL)
1.1 nicm 217: return (0);
218:
1.8 nicm 219: newtempl = cmd_command_prompt_replace(cdata->template, s, cdata->idx);
220: xfree(cdata->template);
221: cdata->template = newtempl;
222:
223: if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
224: xasprintf(&prompt, "%s ", ptr);
225: status_prompt_update(c, prompt);
226: xfree(prompt);
227: cdata->idx++;
228: return (1);
229: }
1.1 nicm 230:
1.8 nicm 231: if (cmd_string_parse(newtempl, &cmdlist, &cause) != 0) {
232: if (cause != NULL) {
233: *cause = toupper((u_char) *cause);
234: status_message_set(c, "%s", cause);
235: xfree(cause);
1.1 nicm 236: }
1.8 nicm 237: return (0);
1.1 nicm 238: }
239:
240: ctx.msgdata = NULL;
241: ctx.curclient = c;
242:
243: ctx.error = key_bindings_error;
244: ctx.print = key_bindings_print;
245: ctx.info = key_bindings_info;
246:
247: ctx.cmdclient = NULL;
248:
249: cmd_list_exec(cmdlist, &ctx);
250: cmd_list_free(cmdlist);
251:
1.4 nicm 252: if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
1.1 nicm 253: return (1);
254: return (0);
1.4 nicm 255: }
256:
257: void
1.8 nicm 258: cmd_command_prompt_cfree(void *data)
1.4 nicm 259: {
1.8 nicm 260: struct cmd_command_prompt_cdata *cdata = data;
1.4 nicm 261:
1.8 nicm 262: if (cdata->prompts != NULL)
263: xfree(cdata->prompts);
1.4 nicm 264: if (cdata->template != NULL)
265: xfree(cdata->template);
266: xfree(cdata);
1.8 nicm 267: }
268:
269: char *
270: cmd_command_prompt_replace(char *template, const char *s, int idx)
271: {
272: char ch;
273: char *buf, *ptr;
274: int replaced;
275: size_t len;
276:
277: if (strstr(template, "%") == NULL)
278: return (xstrdup(template));
279:
280: buf = xmalloc(1);
281: *buf = '\0';
282: len = 0;
283: replaced = 0;
284:
285: ptr = template;
286: while (*ptr != '\0') {
287: switch (ch = *ptr++) {
288: case '%':
289: if (*ptr < '1' || *ptr > '9' || *ptr - '0' != idx) {
290: if (*ptr != '%' || replaced)
291: break;
292: replaced = 1;
293: }
294: ptr++;
295:
296: len += strlen(s);
297: buf = xrealloc(buf, 1, len + 1);
298: strlcat(buf, s, len + 1);
299: continue;
300: }
301: buf = xrealloc(buf, 1, len + 2);
302: buf[len++] = ch;
303: buf[len] = '\0';
304: }
305:
306: return (buf);
1.1 nicm 307: }