Home | History | Annotate | Line # | Download | only in dist
cmd-command-prompt.c revision 1.1.1.3
      1 /* $Id: cmd-command-prompt.c,v 1.1.1.3 2014/07/24 14:22:53 christos Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2008 Nicholas Marriott <nicm (at) 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 <stdlib.h>
     23 #include <string.h>
     24 #include <time.h>
     25 
     26 #include "tmux.h"
     27 
     28 /*
     29  * Prompt for command in client.
     30  */
     31 
     32 void	cmd_command_prompt_key_binding(struct cmd *, int);
     33 enum cmd_retval	cmd_command_prompt_exec(struct cmd *, struct cmd_q *);
     34 
     35 int	cmd_command_prompt_callback(void *, const char *);
     36 void	cmd_command_prompt_free(void *);
     37 
     38 const struct cmd_entry cmd_command_prompt_entry = {
     39 	"command-prompt", NULL,
     40 	"I:p:t:", 0, 1,
     41 	"[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
     42 	0,
     43 	cmd_command_prompt_key_binding,
     44 	cmd_command_prompt_exec
     45 };
     46 
     47 struct cmd_command_prompt_cdata {
     48 	struct client	*c;
     49 	char		*inputs;
     50 	char		*next_input;
     51 	char		*next_prompt;
     52 	char		*prompts;
     53 	char		*template;
     54 	int		 idx;
     55 };
     56 
     57 void
     58 cmd_command_prompt_key_binding(struct cmd *self, int key)
     59 {
     60 	switch (key) {
     61 	case '$':
     62 		self->args = args_create(1, "rename-session '%%'");
     63 		args_set(self->args, 'I', "#S");
     64 		break;
     65 	case ',':
     66 		self->args = args_create(1, "rename-window '%%'");
     67 		args_set(self->args, 'I', "#W");
     68 		break;
     69 	case '.':
     70 		self->args = args_create(1, "move-window -t '%%'");
     71 		break;
     72 	case 'f':
     73 		self->args = args_create(1, "find-window '%%'");
     74 		break;
     75 	case '\'':
     76 		self->args = args_create(1, "select-window -t ':%%'");
     77 		args_set(self->args, 'p', "index");
     78 		break;
     79 	default:
     80 		self->args = args_create(0);
     81 		break;
     82 	}
     83 }
     84 
     85 enum cmd_retval
     86 cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
     87 {
     88 	struct args			*args = self->args;
     89 	const char			*inputs, *prompts;
     90 	struct cmd_command_prompt_cdata	*cdata;
     91 	struct client			*c;
     92 	char				*prompt, *ptr, *input = NULL;
     93 	size_t				 n;
     94 
     95 	if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
     96 		return (CMD_RETURN_ERROR);
     97 
     98 	if (c->prompt_string != NULL)
     99 		return (CMD_RETURN_NORMAL);
    100 
    101 	cdata = xmalloc(sizeof *cdata);
    102 	cdata->c = c;
    103 	cdata->idx = 1;
    104 	cdata->inputs = NULL;
    105 	cdata->next_input = NULL;
    106 	cdata->next_prompt = NULL;
    107 	cdata->prompts = NULL;
    108 	cdata->template = NULL;
    109 
    110 	if (args->argc != 0)
    111 		cdata->template = xstrdup(args->argv[0]);
    112 	else
    113 		cdata->template = xstrdup("%1");
    114 
    115 	if ((prompts = args_get(args, 'p')) != NULL)
    116 		cdata->prompts = xstrdup(prompts);
    117 	else if (args->argc != 0) {
    118 		n = strcspn(cdata->template, " ,");
    119 		xasprintf(&cdata->prompts, "(%.*s) ", (int) n, cdata->template);
    120 	} else
    121 		cdata->prompts = xstrdup(":");
    122 
    123 	/* Get first prompt. */
    124 	cdata->next_prompt = cdata->prompts;
    125 	ptr = strsep(&cdata->next_prompt, ",");
    126 	if (prompts == NULL)
    127 		prompt = xstrdup(ptr);
    128 	else
    129 		xasprintf(&prompt, "%s ", ptr);
    130 
    131 	/* Get initial prompt input. */
    132 	if ((inputs = args_get(args, 'I')) != NULL) {
    133 		cdata->inputs = xstrdup(inputs);
    134 		cdata->next_input = cdata->inputs;
    135 		input = strsep(&cdata->next_input, ",");
    136 	}
    137 
    138 	status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
    139 	    cmd_command_prompt_free, cdata, 0);
    140 	free(prompt);
    141 
    142 	return (CMD_RETURN_NORMAL);
    143 }
    144 
    145 int
    146 cmd_command_prompt_callback(void *data, const char *s)
    147 {
    148 	struct cmd_command_prompt_cdata	*cdata = data;
    149 	struct client			*c = cdata->c;
    150 	struct cmd_list			*cmdlist;
    151 	char				*cause, *new_template, *prompt, *ptr;
    152 	char				*input = NULL;
    153 
    154 	if (s == NULL)
    155 		return (0);
    156 
    157 	new_template = cmd_template_replace(cdata->template, s, cdata->idx);
    158 	free(cdata->template);
    159 	cdata->template = new_template;
    160 
    161 	/*
    162 	 * Check if there are more prompts; if so, get its respective input
    163 	 * and update the prompt data.
    164 	 */
    165 	if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
    166 		xasprintf(&prompt, "%s ", ptr);
    167 		input = strsep(&cdata->next_input, ",");
    168 		status_prompt_update(c, prompt, input);
    169 
    170 		free(prompt);
    171 		cdata->idx++;
    172 		return (1);
    173 	}
    174 
    175 	if (cmd_string_parse(new_template, &cmdlist, NULL, 0, &cause) != 0) {
    176 		if (cause != NULL) {
    177 			*cause = toupper((u_char) *cause);
    178 			status_message_set(c, "%s", cause);
    179 			free(cause);
    180 		}
    181 		return (0);
    182 	}
    183 
    184 	cmdq_run(c->cmdq, cmdlist);
    185 	cmd_list_free(cmdlist);
    186 
    187 	if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
    188 		return (1);
    189 	return (0);
    190 }
    191 
    192 void
    193 cmd_command_prompt_free(void *data)
    194 {
    195 	struct cmd_command_prompt_cdata	*cdata = data;
    196 
    197 	free(cdata->inputs);
    198 	free(cdata->prompts);
    199 	free(cdata->template);
    200 	free(cdata);
    201 }
    202