summaryrefslogtreecommitdiffstats
path: root/cmd-command-prompt.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2009-08-19 10:39:50 +0000
committerNicholas Marriott <nicm@openbsd.org>2009-08-19 10:39:50 +0000
commit3f4418d84dd8865f1bba410fc796acb53277abbf (patch)
tree8e77d873046cb99f6d4cbd9a8a1528a5d6f575c3 /cmd-command-prompt.c
parent036de0c5e44ba374707e86b313e4f848488ebdea (diff)
Extend command-prompt with a -p option which is a comma-separated list of one
or more prompts to present in order. The responses to the prompt are replaced in the template string: %% are replaced in order, so the first prompt replaces the first %%, the second replaces the second, and so on. In addition, %1 up to %9 are replaced with the responses to the first the ninth prompts The default template is "%1" so the response to the first prompt is processed as a command. Note that this changes the behaviour for %% so if there is only one prompt, only the first %% will be replaced. Templates such as "neww -n '%%' 'ssh %%'" should be changed to "neww -n '%1' 'ssh %1'". From Tiago Cunha.
Diffstat (limited to 'cmd-command-prompt.c')
-rw-r--r--cmd-command-prompt.c270
1 files changed, 196 insertions, 74 deletions
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index dac334b2..e4954ddd 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -27,56 +27,112 @@
* Prompt for command in client.
*/
-void cmd_command_prompt_init(struct cmd *, int);
-int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
+void cmd_command_prompt_init(struct cmd *, int);
+int cmd_command_prompt_parse(struct cmd *, int, char **, char **);
+int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
+void cmd_command_prompt_free(struct cmd *);
+size_t cmd_command_prompt_print(struct cmd *, char *, size_t);
-int cmd_command_prompt_callback(void *, const char *);
-void cmd_command_prompt_free(void *);
+int cmd_command_prompt_callback(void *, const char *);
+void cmd_command_prompt_cfree(void *);
+char *cmd_command_prompt_replace(char *, const char *, int);
const struct cmd_entry cmd_command_prompt_entry = {
"command-prompt", NULL,
- CMD_TARGET_CLIENT_USAGE " [template]",
- CMD_ARG01, 0,
+ CMD_TARGET_CLIENT_USAGE " [-p prompts] [template]",
+ 0, 0,
cmd_command_prompt_init,
- cmd_target_parse,
+ cmd_command_prompt_parse,
cmd_command_prompt_exec,
- cmd_target_free,
- cmd_target_print
+ cmd_command_prompt_free,
+ cmd_command_prompt_print
};
struct cmd_command_prompt_data {
+ char *prompts;
+ char *target;
+ char *template;
+};
+
+struct cmd_command_prompt_cdata {
struct client *c;
+ char *next_prompt;
+ char *prompts;
char *template;
+ int idx;
};
void
cmd_command_prompt_init(struct cmd *self, int key)
{
- struct cmd_target_data *data;
+ struct cmd_command_prompt_data *data;
- cmd_target_init(self, key);
- data = self->data;
+ self->data = data = xmalloc(sizeof *data);
+ data->prompts = NULL;
+ data->target = NULL;
+ data->template = NULL;
switch (key) {
case ',':
- data->arg = xstrdup("rename-window '%%'");
+ data->template = xstrdup("rename-window '%%'");
break;
case '.':
- data->arg = xstrdup("move-window -t '%%'");
+ data->template = xstrdup("move-window -t '%%'");
break;
case 'f':
- data->arg = xstrdup("find-window '%%'");
+ data->template = xstrdup("find-window '%%'");
break;
}
}
int
+cmd_command_prompt_parse(struct cmd *self, int argc, char **argv, char **cause)
+{
+ struct cmd_command_prompt_data *data;
+ int opt;
+
+ self->entry->init(self, 0);
+ data = self->data;
+
+ while ((opt = getopt(argc, argv, "p:t:")) != -1) {
+ switch (opt) {
+ case 'p':
+ if (data->prompts == NULL)
+ data->prompts = xstrdup(optarg);
+ break;
+ case 't':
+ if (data->target == NULL)
+ data->target = xstrdup(optarg);
+ break;
+ default:
+ goto usage;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc != 0 && argc != 1)
+ goto usage;
+
+ if (argc == 1)
+ data->template = xstrdup(argv[0]);
+
+ return (0);
+
+usage:
+ xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
+
+ self->entry->free(self);
+ return (-1);
+}
+
+int
cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
{
- struct cmd_target_data *data = self->data;
- struct cmd_command_prompt_data *cdata;
+ struct cmd_command_prompt_data *data = self->data;
+ struct cmd_command_prompt_cdata *cdata;
struct client *c;
- char *hdr, *ptr;
+ char *prompt, *ptr;
+ size_t n;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
@@ -86,76 +142,100 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
cdata = xmalloc(sizeof *cdata);
cdata->c = c;
- if (data->arg != NULL) {
- cdata->template = xstrdup(data->arg);
- if ((ptr = strchr(data->arg, ' ')) == NULL)
- ptr = strchr(data->arg, '\0');
- xasprintf(&hdr, "(%.*s) ", (int) (ptr - data->arg), data->arg);
- } else {
- cdata->template = NULL;
- hdr = xstrdup(":");
- }
- status_prompt_set(c, hdr,
- cmd_command_prompt_callback, cmd_command_prompt_free, cdata, 0);
- xfree(hdr);
+ cdata->idx = 1;
+ cdata->next_prompt = NULL;
+ cdata->prompts = NULL;
+ cdata->template = NULL;
+
+ if (data->template != NULL)
+ cdata->template = xstrdup(data->template);
+ else
+ cdata->template = xstrdup("%1");
+ if (data->prompts != NULL)
+ cdata->prompts = xstrdup(data->prompts);
+ else if (data->template != NULL) {
+ n = strcspn(data->template, " ,");
+ xasprintf(&cdata->prompts, "(%.*s) ", (int) n, data->template);
+ } else
+ cdata->prompts = xstrdup(":");
+
+ cdata->next_prompt = cdata->prompts;
+ ptr = strsep(&cdata->next_prompt, ",");
+ if (data->prompts == NULL)
+ prompt = xstrdup(ptr);
+ else
+ xasprintf(&prompt, "%s ", ptr);
+ status_prompt_set(c, prompt, cmd_command_prompt_callback,
+ cmd_command_prompt_cfree, cdata, 0);
+ xfree(prompt);
return (0);
}
+void
+cmd_command_prompt_free(struct cmd *self)
+{
+ struct cmd_command_prompt_data *data = self->data;
+
+ if (data->prompts != NULL)
+ xfree(data->prompts);
+ if (data->target != NULL)
+ xfree(data->target);
+ if (data->template != NULL)
+ xfree(data->template);
+ xfree(data);
+}
+
+size_t
+cmd_command_prompt_print(struct cmd *self, char *buf, size_t len)
+{
+ struct cmd_command_prompt_data *data = self->data;
+ size_t off = 0;
+
+ off += xsnprintf(buf, len, "%s", self->entry->name);
+ if (data == NULL)
+ return (off);
+ if (off < len && data->prompts != NULL)
+ off += cmd_prarg(buf + off, len - off, " -p ", data->prompts);
+ if (off < len && data->target != NULL)
+ off += cmd_prarg(buf + off, len - off, " -t ", data->target);
+ if (off < len && data->template != NULL)
+ off += cmd_prarg(buf + off, len - off, " ", data->template);
+ return (off);
+}
+
int
cmd_command_prompt_callback(void *data, const char *s)
{
- struct cmd_command_prompt_data *cdata = data;
+ struct cmd_command_prompt_cdata *cdata = data;
struct client *c = cdata->c;
struct cmd_list *cmdlist;
- struct cmd_ctx ctx;
- char *cause, *ptr, *buf, ch;
- size_t len, slen;
+ struct cmd_ctx ctx;
+ char *cause, *newtempl, *prompt, *ptr;
- if (s == NULL || *s == '\0')
+ if (s == NULL)
return (0);
- slen = strlen(s);
- len = 0;
- buf = NULL;
- if (cdata->template != NULL) {
- ptr = cdata->template;
- while (*ptr != '\0') {
- switch (ch = *ptr++) {
- case '%':
- if (*ptr != '%')
- break;
- ptr++;
-
- buf = xrealloc(buf, 1, len + slen + 1);
- memcpy(buf + len, s, slen);
- len += slen;
- break;
- default:
- buf = xrealloc(buf, 1, len + 2);
- buf[len++] = ch;
- break;
- }
- }
+ newtempl = cmd_command_prompt_replace(cdata->template, s, cdata->idx);
+ xfree(cdata->template);
+ cdata->template = newtempl;
- if (buf == NULL)
- return (0);
- buf[len] = '\0';
- s = buf;
+ if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
+ xasprintf(&prompt, "%s ", ptr);
+ status_prompt_update(c, prompt);
+ xfree(prompt);
+ cdata->idx++;
+ return (1);
}
- if (cmd_string_parse(s, &cmdlist, &cause) != 0) {
- if (cause == NULL)
- return (0);
- *cause = toupper((u_char) *cause);
- status_message_set(c, "%s", cause);
- xfree(cause);
- cmdlist = NULL;
- }
- if (buf != NULL)
- xfree(buf);
- if (cmdlist == NULL)
+ if (cmd_string_parse(newtempl, &cmdlist, &cause) != 0) {
+ if (cause != NULL) {
+ *cause = toupper((u_char) *cause);
+ status_message_set(c, "%s", cause);
+ xfree(cause);
+ }
return (0);
+ }
ctx.msgdata = NULL;
ctx.cursession = c->session;
@@ -176,11 +256,53 @@ cmd_command_prompt_callback(void *data, const char *s)
}
void
-cmd_command_prompt_free(void *data)
+cmd_command_prompt_cfree(void *data)
{
- struct cmd_command_prompt_data *cdata = data;
+ struct cmd_command_prompt_cdata *cdata = data;
+ if (cdata->prompts != NULL)
+ xfree(cdata->prompts);
if (cdata->template != NULL)
xfree(cdata->template);
xfree(cdata);
}
+
+char *
+cmd_command_prompt_replace(char *template, const char *s, int idx)
+{
+ char ch;
+ char *buf, *ptr;
+ int replaced;
+ size_t len;
+
+ if (strstr(template, "%") == NULL)
+ return (xstrdup(template));
+
+ buf = xmalloc(1);
+ *buf = '\0';
+ len = 0;
+ replaced = 0;
+
+ ptr = template;
+ while (*ptr != '\0') {
+ switch (ch = *ptr++) {
+ case '%':
+ if (*ptr < '1' || *ptr > '9' || *ptr - '0' != idx) {
+ if (*ptr != '%' || replaced)
+ break;
+ replaced = 1;
+ }
+ ptr++;
+
+ len += strlen(s);
+ buf = xrealloc(buf, 1, len + 1);
+ strlcat(buf, s, len + 1);
+ continue;
+ }
+ buf = xrealloc(buf, 1, len + 2);
+ buf[len++] = ch;
+ buf[len] = '\0';
+ }
+
+ return (buf);
+}