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