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