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