1 /* $Id: cmd-confirm-before.c,v 1.1.1.2 2011/08/17 18:40:04 jmmv Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> 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 <ctype.h> 20 #include <string.h> 21 22 #include "tmux.h" 23 24 /* 25 * Asks for confirmation before executing a command. 26 */ 27 28 void cmd_confirm_before_key_binding(struct cmd *, int); 29 int cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *); 30 31 int cmd_confirm_before_callback(void *, const char *); 32 void cmd_confirm_before_free(void *); 33 34 const struct cmd_entry cmd_confirm_before_entry = { 35 "confirm-before", "confirm", 36 "p:t:", 1, 1, 37 "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command", 38 0, 39 cmd_confirm_before_key_binding, 40 NULL, 41 cmd_confirm_before_exec 42 }; 43 44 struct cmd_confirm_before_data { 45 struct client *c; 46 char *cmd; 47 }; 48 49 void 50 cmd_confirm_before_key_binding(struct cmd *self, int key) 51 { 52 switch (key) { 53 case '&': 54 self->args = args_create(1, "kill-window"); 55 args_set(self->args, 'p', "kill-window #W? (y/n)"); 56 break; 57 case 'x': 58 self->args = args_create(1, "kill-pane"); 59 args_set(self->args, 'p', "kill-pane #P? (y/n)"); 60 break; 61 default: 62 self->args = args_create(0); 63 break; 64 } 65 } 66 67 int 68 cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx) 69 { 70 struct args *args = self->args; 71 struct cmd_confirm_before_data *cdata; 72 struct client *c; 73 char *cmd, *copy, *new_prompt, *ptr; 74 const char *prompt; 75 76 if (ctx->curclient == NULL) { 77 ctx->error(ctx, "must be run interactively"); 78 return (-1); 79 } 80 81 if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL) 82 return (-1); 83 84 if ((prompt = args_get(args, 'p')) != NULL) 85 xasprintf(&new_prompt, "%s ", prompt); 86 else { 87 ptr = copy = xstrdup(args->argv[0]); 88 cmd = strsep(&ptr, " \t"); 89 xasprintf(&new_prompt, "Confirm '%s'? (y/n) ", cmd); 90 xfree(copy); 91 } 92 93 cdata = xmalloc(sizeof *cdata); 94 cdata->cmd = xstrdup(args->argv[0]); 95 cdata->c = c; 96 status_prompt_set(cdata->c, new_prompt, NULL, 97 cmd_confirm_before_callback, cmd_confirm_before_free, cdata, 98 PROMPT_SINGLE); 99 100 xfree(new_prompt); 101 return (1); 102 } 103 104 int 105 cmd_confirm_before_callback(void *data, const char *s) 106 { 107 struct cmd_confirm_before_data *cdata = data; 108 struct client *c = cdata->c; 109 struct cmd_list *cmdlist; 110 struct cmd_ctx ctx; 111 char *cause; 112 113 if (s == NULL || *s == '\0') 114 return (0); 115 if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') 116 return (0); 117 118 if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) { 119 if (cause != NULL) { 120 *cause = toupper((u_char) *cause); 121 status_message_set(c, "%s", cause); 122 xfree(cause); 123 } 124 return (0); 125 } 126 127 ctx.msgdata = NULL; 128 ctx.curclient = c; 129 130 ctx.error = key_bindings_error; 131 ctx.print = key_bindings_print; 132 ctx.info = key_bindings_info; 133 134 ctx.cmdclient = NULL; 135 136 cmd_list_exec(cmdlist, &ctx); 137 cmd_list_free(cmdlist); 138 139 return (0); 140 } 141 142 void 143 cmd_confirm_before_free(void *data) 144 { 145 struct cmd_confirm_before_data *cdata = data; 146 147 if (cdata->cmd != NULL) 148 xfree(cdata->cmd); 149 xfree(cdata); 150 } 151