summaryrefslogtreecommitdiffstats
path: root/cmd-command-prompt.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--cmd-command-prompt.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
new file mode 100644
index 0000000..4455856
--- /dev/null
+++ b/cmd-command-prompt.c
@@ -0,0 +1,238 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "tmux.h"
+
+/*
+ * Prompt for command in client.
+ */
+
+static enum args_parse_type cmd_command_prompt_args_parse(struct args *,
+ u_int, char **);
+static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
+ struct cmdq_item *);
+
+static int cmd_command_prompt_callback(struct client *, void *,
+ const char *, int);
+static void cmd_command_prompt_free(void *);
+
+const struct cmd_entry cmd_command_prompt_entry = {
+ .name = "command-prompt",
+ .alias = NULL,
+
+ .args = { "1bFkiI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
+ .usage = "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
+ " [-T type] [template]",
+
+ .flags = CMD_CLIENT_TFLAG,
+ .exec = cmd_command_prompt_exec
+};
+
+struct cmd_command_prompt_prompt {
+ char *input;
+ char *prompt;
+};
+
+struct cmd_command_prompt_cdata {
+ struct cmdq_item *item;
+ struct args_command_state *state;
+
+ int flags;
+ enum prompt_type prompt_type;
+
+ struct cmd_command_prompt_prompt *prompts;
+ u_int count;
+ u_int current;
+
+ int argc;
+ char **argv;
+};
+
+static enum args_parse_type
+cmd_command_prompt_args_parse(__unused struct args *args, __unused u_int idx,
+ __unused char **cause)
+{
+ return (ARGS_PARSE_COMMANDS_OR_STRING);
+}
+
+static enum cmd_retval
+cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
+{
+ struct args *args = cmd_get_args(self);
+ struct client *tc = cmdq_get_target_client(item);
+ struct cmd_find_state *target = cmdq_get_target(item);
+ const char *type, *s, *input;
+ struct cmd_command_prompt_cdata *cdata;
+ char *tmp, *prompts, *prompt, *next_prompt;
+ char *inputs = NULL, *next_input;
+ u_int count = args_count(args);
+ int wait = !args_has(args, 'b'), space = 1;
+
+ if (tc->prompt_string != NULL)
+ return (CMD_RETURN_NORMAL);
+ if (args_has(args, 'i'))
+ wait = 0;
+
+ cdata = xcalloc(1, sizeof *cdata);
+ if (wait)
+ cdata->item = item;
+ cdata->state = args_make_commands_prepare(self, item, 0, "%1", wait,
+ args_has(args, 'F'));
+
+ if ((s = args_get(args, 'p')) == NULL) {
+ if (count != 0) {
+ tmp = args_make_commands_get_command(cdata->state);
+ xasprintf(&prompts, "(%s)", tmp);
+ free(tmp);
+ } else {
+ prompts = xstrdup(":");
+ space = 0;
+ }
+ next_prompt = prompts;
+ } else
+ next_prompt = prompts = xstrdup(s);
+ if ((s = args_get(args, 'I')) != NULL)
+ next_input = inputs = xstrdup(s);
+ else
+ next_input = NULL;
+ while ((prompt = strsep(&next_prompt, ",")) != NULL) {
+ cdata->prompts = xreallocarray(cdata->prompts, cdata->count + 1,
+ sizeof *cdata->prompts);
+ if (!space)
+ tmp = xstrdup(prompt);
+ else
+ xasprintf(&tmp, "%s ", prompt);
+ cdata->prompts[cdata->count].prompt = tmp;
+
+ if (next_input != NULL) {
+ input = strsep(&next_input, ",");
+ if (input == NULL)
+ input = "";
+ } else
+ input = "";
+ cdata->prompts[cdata->count].input = xstrdup(input);
+
+ cdata->count++;
+ }
+ free(inputs);
+ free(prompts);
+
+ if ((type = args_get(args, 'T')) != NULL) {
+ cdata->prompt_type = status_prompt_type(type);
+ if (cdata->prompt_type == PROMPT_TYPE_INVALID) {
+ cmdq_error(item, "unknown type: %s", type);
+ return (CMD_RETURN_ERROR);
+ }
+ } else
+ cdata->prompt_type = PROMPT_TYPE_COMMAND;
+
+ if (args_has(args, '1'))
+ cdata->flags |= PROMPT_SINGLE;
+ else if (args_has(args, 'N'))
+ cdata->flags |= PROMPT_NUMERIC;
+ else if (args_has(args, 'i'))
+ cdata->flags |= PROMPT_INCREMENTAL;
+ else if (args_has(args, 'k'))
+ cdata->flags |= PROMPT_KEY;
+ status_prompt_set(tc, target, cdata->prompts[0].prompt,
+ cdata->prompts[0].input, cmd_command_prompt_callback,
+ cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
+
+ if (!wait)
+ return (CMD_RETURN_NORMAL);
+ return (CMD_RETURN_WAIT);
+}
+
+static int
+cmd_command_prompt_callback(struct client *c, void *data, const char *s,
+ int done)
+{
+ struct cmd_command_prompt_cdata *cdata = data;
+ char *error;
+ struct cmdq_item *item = cdata->item, *new_item;
+ struct cmd_list *cmdlist;
+ struct cmd_command_prompt_prompt *prompt;
+ int argc = 0;
+ char **argv = NULL;
+
+ if (s == NULL)
+ goto out;
+ if (done) {
+ if (cdata->flags & PROMPT_INCREMENTAL)
+ goto out;
+
+ cmd_append_argv(&cdata->argc, &cdata->argv, s);
+ if (++cdata->current != cdata->count) {
+ prompt = &cdata->prompts[cdata->current];
+ status_prompt_update(c, prompt->prompt, prompt->input);
+ return (1);
+ }
+ }
+
+ argc = cdata->argc;
+ argv = cmd_copy_argv(cdata->argc, cdata->argv);
+ cmd_append_argv(&argc, &argv, s);
+ if (done) {
+ cdata->argc = argc;
+ cdata->argv = cmd_copy_argv(argc, argv);
+ }
+
+ cmdlist = args_make_commands(cdata->state, argc, argv, &error);
+ if (cmdlist == NULL) {
+ cmdq_append(c, cmdq_get_error(error));
+ free(error);
+ } else if (item == NULL) {
+ new_item = cmdq_get_command(cmdlist, NULL);
+ cmdq_append(c, new_item);
+ } else {
+ new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
+ cmdq_insert_after(item, new_item);
+ }
+ cmd_free_argv(argc, argv);
+
+ if (c->prompt_inputcb != cmd_command_prompt_callback)
+ return (1);
+
+out:
+ if (item != NULL)
+ cmdq_continue(item);
+ return (0);
+}
+
+static void
+cmd_command_prompt_free(void *data)
+{
+ struct cmd_command_prompt_cdata *cdata = data;
+ u_int i;
+
+ for (i = 0; i < cdata->count; i++) {
+ free(cdata->prompts[i].prompt);
+ free(cdata->prompts[i].input);
+ }
+ free(cdata->prompts);
+ cmd_free_argv(cdata->argc, cdata->argv);
+ args_make_commands_free(cdata->state);
+ free(cdata);
+}