summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2021-08-27 20:01:11 +0100
committerThomas Adam <thomas@xteddy.org>2021-08-27 20:01:11 +0100
commit609baea95e30201919a173ea1de1f750a15a9f8c (patch)
tree68225d4bd3ba7e258cddb8e6b40f0764408a6e32
parentc6375a0d4003d1008bb64e96e9c0c4433e4a5d13 (diff)
parentdaec63e5e6eb3390d53f4bf7f8a327df77e46c95 (diff)
Merge branch 'obsd-master' into master
-rw-r--r--arguments.c115
-rw-r--r--client.c12
-rw-r--r--cmd-bind-key.c8
-rw-r--r--cmd-choose-tree.c18
-rw-r--r--cmd-command-prompt.c25
-rw-r--r--cmd-display-menu.c2
-rw-r--r--cmd-new-session.c5
-rw-r--r--cmd-new-window.c4
-rw-r--r--cmd-parse.y124
-rw-r--r--cmd-refresh-client.c72
-rw-r--r--cmd-resize-window.c4
-rw-r--r--cmd-respawn-pane.c6
-rw-r--r--cmd-respawn-window.c5
-rw-r--r--cmd-split-window.c6
-rw-r--r--cmd.c48
-rw-r--r--key-bindings.c80
-rw-r--r--resize.c93
-rw-r--r--server-client.c30
-rw-r--r--tmux.114
-rw-r--r--tmux.h19
-rw-r--r--window.c2
21 files changed, 498 insertions, 194 deletions
diff --git a/arguments.c b/arguments.c
index 30e8fa0b..5669df92 100644
--- a/arguments.c
+++ b/arguments.c
@@ -166,7 +166,7 @@ args_parse(const struct args_parse *parse, struct args_value *values,
}
argument = *++found;
if (argument != ':') {
- log_debug("%s: add -%c", __func__, flag);
+ log_debug("%s: -%c", __func__, flag);
args_set(args, flag, NULL);
continue;
}
@@ -192,7 +192,7 @@ args_parse(const struct args_parse *parse, struct args_value *values,
args_copy_value(new, &values[i++]);
}
s = args_value_as_string(new);
- log_debug("%s: add -%c = %s", __func__, flag, s);
+ log_debug("%s: -%c = %s", __func__, flag, s);
args_set(args, flag, new);
break;
}
@@ -203,7 +203,8 @@ args_parse(const struct args_parse *parse, struct args_value *values,
value = &values[i];
s = args_value_as_string(value);
- log_debug("%s: %u = %s", __func__, i, s);
+ log_debug("%s: %u = %s (type %d)", __func__, i, s,
+ value->type);
if (parse->cb != NULL) {
type = parse->cb(args, args->count, cause);
@@ -265,6 +266,63 @@ args_parse(const struct args_parse *parse, struct args_value *values,
return (args);
}
+/* Copy and expand a value. */
+static void
+args_copy_copy_value(struct args_value *to, struct args_value *from, int argc,
+ char **argv)
+{
+ char *s, *expanded;
+ int i;
+
+ to->type = from->type;
+ switch (from->type) {
+ case ARGS_NONE:
+ break;
+ case ARGS_STRING:
+ expanded = xstrdup(from->string);
+ for (i = 0; i < argc; i++) {
+ s = cmd_template_replace(expanded, argv[i], i + 1);
+ free(expanded);
+ expanded = s;
+ }
+ to->string = expanded;
+ break;
+ case ARGS_COMMANDS:
+ to->cmdlist = cmd_list_copy(from->cmdlist, argc, argv);
+ break;
+ }
+}
+
+/* Copy an arguments set. */
+struct args *
+args_copy(struct args *args, int argc, char **argv)
+{
+ struct args *new_args;
+ struct args_entry *entry;
+ struct args_value *value, *new_value;
+ u_int i;
+
+ new_args = args_create();
+ RB_FOREACH(entry, args_tree, &args->tree) {
+ if (entry->count == 1) {
+ args_set(new_args, entry->flag, NULL);
+ continue;
+ }
+ TAILQ_FOREACH(value, &entry->values, entry) {
+ new_value = xcalloc(1, sizeof *new_value);
+ args_copy_copy_value(new_value, value, argc, argv);
+ args_set(new_args, entry->flag, new_value);
+ }
+ }
+ new_args->count = args->count;
+ new_args->values = xcalloc(args->count, sizeof *new_args->values);
+ for (i = 0; i < args->count; i++) {
+ new_value = &new_args->values[i];
+ args_copy_copy_value(new_value, &args->values[i], argc, argv);
+ }
+ return (new_args);
+}
+
/* Free a value. */
void
args_free_value(struct args_value *value)
@@ -282,6 +340,16 @@ args_free_value(struct args_value *value)
free(value->cached);
}
+/* Free values. */
+void
+args_free_values(struct args_value *values, u_int count)
+{
+ u_int i;
+
+ for (i = 0; i < count; i++)
+ args_free_value(&values[i]);
+}
+
/* Free an arguments set. */
void
args_free(struct args *args)
@@ -290,10 +358,8 @@ args_free(struct args *args)
struct args_entry *entry1;
struct args_value *value;
struct args_value *value1;
- u_int i;
- for (i = 0; i < args->count; i++)
- args_free_value(&args->values[i]);
+ args_free_values(args->values, args->count);
free(args->values);
RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
@@ -311,7 +377,7 @@ args_free(struct args *args)
/* Convert arguments to vector. */
void
-args_vector(struct args *args, int *argc, char ***argv)
+args_to_vector(struct args *args, int *argc, char ***argv)
{
char *s;
u_int i;
@@ -335,6 +401,21 @@ args_vector(struct args *args, int *argc, char ***argv)
}
}
+/* Convert arguments from vector. */
+struct args_value *
+args_from_vector(int argc, char **argv)
+{
+ struct args_value *values;
+ int i;
+
+ values = xcalloc(argc, sizeof *values);
+ for (i = 0; i < argc; i++) {
+ values[i].type = ARGS_STRING;
+ values[i].string = xstrdup(argv[i]);
+ }
+ return (values);
+}
+
/* Add to string. */
static void printflike(3, 4)
args_print_add(char **buf, size_t *len, const char *fmt, ...)
@@ -424,7 +505,7 @@ args_print(struct args *args)
char *
args_escape(const char *s)
{
- static const char dquoted[] = " #';${}";
+ static const char dquoted[] = " #';${}%";
static const char squoted[] = " \"";
char *escaped, *result;
int flags, quotes = 0;
@@ -538,6 +619,13 @@ args_count(struct args *args)
return (args->count);
}
+/* Get argument values. */
+struct args_value *
+args_values(struct args *args)
+{
+ return (args->values);
+}
+
/* Get argument value. */
struct args_value *
args_value(struct args *args, u_int idx)
@@ -570,8 +658,8 @@ args_make_commands_now(struct cmd *self, struct cmdq_item *item, u_int idx)
cmdq_error(item, "%s", error);
free(error);
}
- else
- cmdlist->references++;
+ else
+ cmdlist->references++;
args_make_commands_free(state);
return (cmdlist);
}
@@ -631,8 +719,11 @@ args_make_commands(struct args_command_state *state, int argc, char **argv,
char *cmd, *new_cmd;
int i;
- if (state->cmdlist != NULL)
- return (state->cmdlist);
+ if (state->cmdlist != NULL) {
+ if (argc == 0)
+ return (state->cmdlist);
+ return (cmd_list_copy(state->cmdlist, argc, argv));
+ }
cmd = xstrdup(state->cmd);
for (i = 0; i < argc; i++) {
diff --git a/client.c b/client.c
index fc0e1dde..8ca08524 100644
--- a/client.c
+++ b/client.c
@@ -243,6 +243,7 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
ssize_t linelen;
char *line = NULL, **caps = NULL, *cause;
u_int ncaps = 0;
+ struct args_value *values;
/* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
signal(SIGCHLD, SIG_IGN);
@@ -258,17 +259,20 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
msg = MSG_COMMAND;
/*
- * It sucks parsing the command string twice (in client and
- * later in server) but it is necessary to get the start server
- * flag.
+ * It's annoying parsing the command string twice (in client
+ * and later in server) but it is necessary to get the start
+ * server flag.
*/
- pr = cmd_parse_from_arguments(argc, argv, NULL);
+ values = args_from_vector(argc, argv);
+ pr = cmd_parse_from_arguments(values, argc, NULL);
if (pr->status == CMD_PARSE_SUCCESS) {
if (cmd_list_any_have(pr->cmdlist, CMD_STARTSERVER))
flags |= CLIENT_STARTSERVER;
cmd_list_free(pr->cmdlist);
} else
free(pr->error);
+ args_free_values(values, argc);
+ free(values);
}
/* Create client process structure (starts logging). */
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index be0ae40e..dab03b01 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -58,8 +58,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
key_code key;
const char *tablename, *note = args_get(args, 'N');
struct cmd_parse_result *pr;
- char **argv;
- int argc, repeat;
+ int repeat;
struct args_value *value;
u_int count = args_count(args);
@@ -92,9 +91,8 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
if (count == 2)
pr = cmd_parse_from_string(args_string(args, 1), NULL);
else {
- args_vector(args, &argc, &argv);
- pr = cmd_parse_from_arguments(argc - 1, argv + 1, NULL);
- cmd_free_argv(argc, argv);
+ pr = cmd_parse_from_arguments(args_values(args) + 1, count - 1,
+ NULL);
}
switch (pr->status) {
case CMD_PARSE_ERROR:
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index 9258f366..7aa1d217 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -24,13 +24,16 @@
* Enter a mode.
*/
-static enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmdq_item *);
+static enum args_parse_type cmd_choose_tree_args_parse(struct args *args,
+ u_int idx, char **cause);
+static enum cmd_retval cmd_choose_tree_exec(struct cmd *,
+ struct cmdq_item *);
const struct cmd_entry cmd_choose_tree_entry = {
.name = "choose-tree",
.alias = NULL,
- .args = { "F:f:GK:NO:rst:wZ", 0, 1, NULL },
+ .args = { "F:f:GK:NO:rst:wZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
@@ -44,7 +47,7 @@ const struct cmd_entry cmd_choose_client_entry = {
.name = "choose-client",
.alias = NULL,
- .args = { "F:f:K:NO:rt:Z", 0, 1, NULL },
+ .args = { "F:f:K:NO:rt:Z", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
@@ -58,7 +61,7 @@ const struct cmd_entry cmd_choose_buffer_entry = {
.name = "choose-buffer",
.alias = NULL,
- .args = { "F:f:K:NO:rt:Z", 0, 1, NULL },
+ .args = { "F:f:K:NO:rt:Z", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
@@ -81,6 +84,13 @@ const struct cmd_entry cmd_customize_mode_entry = {
.exec = cmd_choose_tree_exec
};
+static enum args_parse_type
+cmd_choose_tree_args_parse(__unused struct args *args, __unused u_int idx,
+ __unused char **cause)
+{
+ return (ARGS_PARSE_COMMANDS_OR_STRING);
+}
+
static enum cmd_retval
cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
{
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 737c44c7..820053ec 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -169,11 +169,13 @@ 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;
+ 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;
@@ -181,7 +183,6 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
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);
@@ -189,8 +190,15 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
}
}
- cmdlist = args_make_commands(cdata->state, cdata->argc, cdata->argv,
- &error);
+ 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);
@@ -201,6 +209,7 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
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);
diff --git a/cmd-display-menu.c b/cmd-display-menu.c
index 4c5fb510..1a11bd01 100644
--- a/cmd-display-menu.c
+++ b/cmd-display-menu.c
@@ -407,7 +407,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
shell = _PATH_BSHELL;
cmd_append_argv(&argc, &argv, shell);
} else
- args_vector(args, &argc, &argv);
+ args_to_vector(args, &argc, &argv);
if (args_has(args, 'E') > 1)
flags |= POPUP_CLOSEEXITZERO;
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 93c7e7b4..cb9abfb3 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -42,7 +42,8 @@ const struct cmd_entry cmd_new_session_entry = {
.args = { "Ac:dDe:EF:f:n:Ps:t:x:Xy:", 0, -1, NULL },
.usage = "[-AdDEPX] [-c start-directory] [-e environment] [-F format] "
"[-f flags] [-n window-name] [-s session-name] "
- CMD_TARGET_SESSION_USAGE " [-x width] [-y height] [command]",
+ CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
+ "[shell-command]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
@@ -283,7 +284,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
sc.tc = c;
sc.name = args_get(args, 'n');
- args_vector(args, &sc.argc, &sc.argv);
+ args_to_vector(args, &sc.argc, &sc.argv);
sc.idx = -1;
sc.cwd = args_get(args, 'c');
diff --git a/cmd-new-window.c b/cmd-new-window.c
index e88795c2..e7f0868f 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -40,7 +40,7 @@ const struct cmd_entry cmd_new_window_entry = {
.args = { "abc:de:F:kn:PSt:", 0, -1, NULL },
.usage = "[-abdkPS] [-c start-directory] [-e environment] [-F format] "
- "[-n window-name] " CMD_TARGET_WINDOW_USAGE " [command]",
+ "[-n window-name] " CMD_TARGET_WINDOW_USAGE " [shell-command]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX },
@@ -105,7 +105,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
sc.tc = tc;
sc.name = args_get(args, 'n');
- args_vector(args, &sc.argc, &sc.argv);
+ args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
av = args_first_value(args, 'e');
diff --git a/cmd-parse.y b/cmd-parse.y
index a08c5819..2b5b7e0b 100644
--- a/cmd-parse.y
+++ b/cmd-parse.y
@@ -44,13 +44,15 @@ struct cmd_parse_scope {
enum cmd_parse_argument_type {
CMD_PARSE_STRING,
- CMD_PARSE_COMMANDS
+ CMD_PARSE_COMMANDS,
+ CMD_PARSE_PARSED_COMMANDS
};
struct cmd_parse_argument {
enum cmd_parse_argument_type type;
char *string;
struct cmd_parse_commands *commands;
+ struct cmd_list *cmdlist;
TAILQ_ENTRY(cmd_parse_argument) entry;
};
@@ -608,6 +610,9 @@ cmd_parse_free_argument(struct cmd_parse_argument *arg)
case CMD_PARSE_COMMANDS:
cmd_parse_free_commands(arg->commands);
break;
+ case CMD_PARSE_PARSED_COMMANDS:
+ cmd_list_free(arg->cmdlist);
+ break;
}
free(arg);
}
@@ -723,6 +728,11 @@ cmd_parse_log_commands(struct cmd_parse_commands *cmds, const char *prefix)
cmd_parse_log_commands(arg->commands, s);
free(s);
break;
+ case CMD_PARSE_PARSED_COMMANDS:
+ s = cmd_list_print(arg->cmdlist, 0);
+ log_debug("%s %u:%u: %s", prefix, i, j, s);
+ free(s);
+ break;
}
j++;
}
@@ -818,6 +828,11 @@ cmd_parse_build_command(struct cmd_parse_command *cmd,
values[count].type = ARGS_COMMANDS;
values[count].cmdlist = pr->cmdlist;
break;
+ case CMD_PARSE_PARSED_COMMANDS:
+ values[count].type = ARGS_COMMANDS;
+ values[count].cmdlist = arg->cmdlist;
+ values[count].cmdlist->references++;
+ break;
}
count++;
}
@@ -1023,39 +1038,19 @@ cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi)
return (&pr);
}
-static void
-cmd_parse_add_command(struct cmd_parse_commands *cmds,
- struct cmd_parse_input *pi, int argc, char **argv)
+struct cmd_parse_result *
+cmd_parse_from_arguments(struct args_value *values, u_int count,
+ struct cmd_parse_input *pi)
{
+ static struct cmd_parse_result pr;
+ struct cmd_parse_input input;
+ struct cmd_parse_commands *cmds;
struct cmd_parse_command *cmd;
struct cmd_parse_argument *arg;
- int i;
-
- cmd_log_argv(argc, argv, "%s", __func__);
-
- cmd = xcalloc(1, sizeof *cmd);
- cmd->line = pi->line;
-
- TAILQ_INIT(&cmd->arguments);
- for (i = 0; i < argc; i++) {
- arg = xcalloc(1, sizeof *arg);
- arg->type = CMD_PARSE_STRING;
- arg->string = xstrdup(argv[i]);
- TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
- }
-
- TAILQ_INSERT_TAIL(cmds, cmd, entry);
-}
-
-struct cmd_parse_result *
-cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi)
-{
- static struct cmd_parse_result pr;
- struct cmd_parse_input input;
- struct cmd_parse_commands *cmds;
- char **copy, **new_argv;
- size_t size;
- int i, last, new_argc;
+ u_int i;
+ char *copy;
+ size_t size;
+ int end;
/*
* The commands are already split up into arguments, so just separate
@@ -1066,40 +1061,51 @@ cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi)
memset(&input, 0, sizeof input);
pi = &input;
}
- cmd_log_argv(argc, argv, "%s", __func__);
cmds = cmd_parse_new_commands();
- copy = cmd_copy_argv(argc, argv);
-
- last = 0;
- for (i = 0; i < argc; i++) {
- size = strlen(copy[i]);
- if (size == 0 || copy[i][size - 1] != ';')
- continue;
- copy[i][--size] = '\0';
- if (size > 0 && copy[i][size - 1] == '\\') {
- copy[i][size - 1] = ';';
- continue;
- }
-
- new_argc = i - last;
- new_argv = copy + last;
- if (size != 0)
- new_argc++;
- if (new_argc != 0)
- cmd_parse_add_command(cmds, pi, new_argc, new_argv);
- last = i + 1;
- }
- if (last != argc) {
- new_argv = copy + last;
- new_argc = argc - last;
+ cmd = xcalloc(1, sizeof *cmd);
+ cmd->line = pi->line;
+ TAILQ_INIT(&cmd->arguments);
- if (new_argc != 0)
- cmd_parse_add_command(cmds, pi, new_argc, new_argv);
+ for (i = 0; i < count; i++) {
+ end = 0;
+ if (values[i].type == ARGS_STRING) {
+ copy = xstrdup(values[i].string);
+ size = strlen(copy);
+ if (size != 0 && copy[size - 1] == ';') {
+ copy[--size] = '\0';
+ if (size > 0 && copy[size - 1] == '\\')
+ copy[size - 1] = ';';
+ else
+ end = 1;
+ }
+ if (!end || size != 0) {
+ arg = xcalloc(1, sizeof *arg);
+ arg->type = CMD_PARSE_STRING;
+ arg->string = copy;
+ TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
+ }
+ } else if (values[i].type == ARGS_COMMANDS) {
+ arg = xcalloc(1, sizeof *arg);
+ arg->type = CMD_PARSE_PARSED_COMMANDS;
+ arg->cmdlist = values[i].cmdlist;
+ arg->cmdlist->references++;
+ TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
+ } else
+ fatalx("unknown argument type");
+ if (end) {
+ TAILQ_INSERT_TAIL(cmds, cmd, entry);
+ cmd = xcalloc(1, sizeof *cmd);
+ cmd->line = pi->line;
+ TAILQ_INIT(&cmd->arguments);
+ }
}
+ if (!TAILQ_EMPTY(&cmd->arguments))
+ TAILQ_INSERT_TAIL(cmds, cmd, entry);
+ else
+ free(cmd);
- cmd_free_argv(argc, copy);
cmd_parse_build_commands(cmds, pi, &pr);
cmd_parse_free_commands(cmds);
return (&pr);
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 24a49dcb..821558ae 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -77,6 +77,58 @@ out:
free(copy);
}
+static enum cmd_retval
+cmd_refresh_client_control_client_size(struct cmd *self, struct cmdq_item *item)
+{
+ struct args *args = cmd_get_args(self);
+ struct client *tc = cmdq_get_target_client(item);
+ const char *size = args_get(args, 'C');
+ u_int w, x, y;
+ struct client_window *cw;
+
+ if (sscanf(size, "@%u:%ux%u", &w, &x, &y) == 3) {
+ if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
+ y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
+ cmdq_error(item, "size too small or too big");
+ return (CMD_RETURN_ERROR);
+ }
+ log_debug("%s: client %s window @%u: size %ux%u", __func__,
+ tc->name, w, x, y);
+ cw = server_client_add_client_window(tc, w);
+ cw->sx = x;
+ cw->sy = y;
+ tc->flags |= CLIENT_WINDOWSIZECHANGED;
+ recalculate_sizes_now(1);
+ return (CMD_RETURN_NORMAL);
+ }
+ if (sscanf(size, "@%u:", &w) == 1) {
+ cw = server_client_get_client_window(tc, w);
+ if (cw != NULL) {
+ log_debug("%s: client %s window @%u: no size", __func__,
+ tc->name, w);
+ cw->sx = 0;
+ cw->sy = 0;
+ recalculate_sizes_now(1);
+ }
+ return (CMD_RETURN_NORMAL);
+ }
+
+ if (sscanf(size, "%u,%u", &x, &y) != 2 &&
+ sscanf(size, "%ux%u", &x, &y) != 2) {
+ cmdq_error(item, "bad size argument");
+ return (CMD_RETURN_ERROR);
+ }
+ if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
+ y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
+ cmdq_error(item, "size too small or too big");
+ return (CMD_RETURN_ERROR);
+ }
+ tty_set_size(&tc->tty, x, y, 0, 0);
+ tc->flags |= CLIENT_SIZECHANGED;
+ recalculate_sizes_now(1);
+ return (CMD_RETURN_NORMAL);
+}
+
static void
cmd_refresh_client_update_offset(struct client *tc, const char *value)
{
@@ -117,8 +169,8 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
struct client *tc = cmdq_get_target_client(item);
struct tty *tty = &tc->tty;
struct window *w;
- const char *size, *errstr;
- u_int x, y, adjust;
+ const char *errstr;
+ u_int adjust;
struct args_value *av;
if (args_has(args, 'c') ||
@@ -205,21 +257,7 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'C')) {
if (~tc->flags & CLIENT_CONTROL)
goto not_control_client;
- size = args_get(args, 'C');
- if (sscanf(size, "%u,%u", &x, &y) != 2 &&
- sscanf(size, "%ux%u", &x, &y) != 2) {
- cmdq_error(item, "bad size argument");
- return (CMD_RETURN_ERROR);
- }
- if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
- y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
- cmdq_error(item, "size too small or too big");
- return (CMD_RETURN_ERROR);
- }
- tty_set_size(&tc->tty, x, y, 0, 0);
- tc->flags |= CLIENT_SIZECHANGED;
- recalculate_sizes_now(1);
- return (CMD_RETURN_NORMAL);
+ return (cmd_refresh_client_control_client_size(self, item));
}
if (args_has(args, 'S')) {
diff --git a/cmd-resize-window.c b/cmd-resize-window.c
index 24d73c87..ad739165 100644
--- a/cmd-resize-window.c
+++ b/cmd-resize-window.c
@@ -108,7 +108,9 @@ cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item)
}
options_set_number(w->options, "window-size", WINDOW_SIZE_MANUAL);
- resize_window(w, sx, sy, xpixel, ypixel);
+ w->manual_sx = sx;
+ w->manual_sy = sy;
+ recalculate_size(w, 1);
return (CMD_RETURN_NORMAL);
}
diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c
index 652ef755..6d60002e 100644
--- a/cmd-respawn-pane.c
+++ b/cmd-respawn-pane.c
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_respawn_pane_entry = {
.args = { "c:e:kt:", 0, -1, NULL },
.usage = "[-k] [-c start-directory] [-e environment] "
- CMD_TARGET_PANE_USAGE " [command]",
+ CMD_TARGET_PANE_USAGE " [shell-command]",
.target = { 't', CMD_FIND_PANE, 0 },
@@ -61,10 +61,8 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
sc.wl = wl;
sc.wp0 = wp;
- sc.lc = NULL;
- sc.name = NULL;
- args_vector(args, &sc.argc, &sc.argv);
+ args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
av = args_first_value(args, 'e');
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index 4e6dc2a9..9a1a02c9 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_respawn_window_entry = {
.args = { "c:e:kt:", 0, -1, NULL },
.usage = "[-k] [-c start-directory] [-e environment] "
- CMD_TARGET_WINDOW_USAGE " [command]",
+ CMD_TARGET_WINDOW_USAGE " [shell-command]",
.target = { 't', CMD_FIND_WINDOW, 0 },
@@ -61,8 +61,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
sc.wl = wl;
sc.tc = tc;
- sc.name = NULL;
- args_vector(args, &sc.argc, &sc.argv);
+ args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
av = args_first_value(args, 'e');
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 109c587b..74c8b5ab 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -41,7 +41,8 @@ const struct cmd_entry cmd_split_window_entry = {
.args = { "bc:de:fF:hIl:p:Pt:vZ", 0, -1, NULL },
.usage = "[-bdefhIPvZ] [-c start-directory] [-e environment] "
- "[-F format] [-l size] " CMD_TARGET_PANE_USAGE " [command]",
+ "[-F format] [-l size] " CMD_TARGET_PANE_USAGE
+ "[shell-command]",
.target = { 't', CMD_FIND_PANE, 0 },
@@ -135,8 +136,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
sc.wp0 = wp;
sc.lc = lc;
- sc.name = NULL;
- args_vector(args, &sc.argc, &sc.argv);
+ args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
av = args_first_value(args, 'e');
diff --git a/cmd.c b/cmd.c
index 4b1dbbbf..44952d11 100644
--- a/cmd.c
+++ b/cmd.c
@@ -543,6 +543,23 @@ cmd_free(struct cmd *cmd)
free(cmd);
}
+/* Copy a command. */
+struct cmd *
+cmd_copy(struct cmd *cmd, int argc, char **argv)
+{
+ struct cmd *new_cmd;
+
+ new_cmd = xcalloc(1, sizeof *new_cmd);
+ new_cmd->entry = cmd->entry;
+ new_cmd->args = args_copy(cmd->args, argc, argv);
+
+ if (cmd->file != NULL)
+ new_cmd->file = xstrdup(cmd->file);
+ new_cmd->line = cmd->line;
+
+ return (new_cmd);
+}
+
/* Get a command as a string. */
char *
cmd_print(struct cmd *cmd)
@@ -617,6 +634,37 @@ cmd_list_free(struct cmd_list *cmdlist)
free(cmdlist);
}
+/* Copy a command list, expanding %s in arguments. */
+struct cmd_list *
+cmd_list_copy(struct cmd_list *cmdlist, int argc, char **argv)
+{
+ struct cmd *cmd;
+ struct cmd_list *new_cmdlist;
+ struct cmd *new_cmd;
+ u_int group = cmdlist->group;
+ char *s;
+
+ s = cmd_list_print(cmdlist, 0);
+ log_debug("%s: %s", __func__, s);
+ free(s);
+
+ new_cmdlist = cmd_list_new();
+ TAILQ_FOREACH(cmd, cmdlist->list, qentry) {
+ if (cmd->group != group) {
+ new_cmdlist->group = cmd_list_next_group++;
+ group = cmd->group;
+ }
+ new_cmd = cmd_copy(cmd, argc, argv);
+ cmd_list_append(new_cmdlist, new_cmd);
+ }
+
+ s = cmd_list_print(new_cmdlist, 0);
+ log_debug("%s: %s", __func__, s);
+ free(s);
+
+ return (new_cmdlist);
+}
+
/* Get a command list as a string. */
char *
cmd_list_print(struct cmd_list *cmdlist, int escaped)
diff --git a/key-bindings.c b/key-bindings.c
index 66e1ec9f..9f7e734a 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -29,7 +29,7 @@
" 'Previous' 'p' {switch-client -p}" \
" ''" \
" 'Renumber' 'N' {move-window -r}" \
- " 'Rename' 'n' {command-prompt -I \"#S\" \"rename-session -- '%%'\"}" \
+ " 'Rename' 'n' {command-prompt -I \"#S\" {rename-session -- '%%'}}" \
" ''" \
" 'New Session' 's' {new-session}" \
" 'New Window' 'w' {new-window}"
@@ -41,7 +41,7 @@
" 'Kill' 'X' {kill-window}" \
" 'Respawn' 'R' {respawn-window -k}" \
" '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}" \
- " 'Rename' 'n' {command-prompt -FI \"#W\" \"rename-window -t#{window_id} -- '%%'\"}" \
+ " 'Rename' 'n' {command-prompt -FI \"#W\" {rename-window -t '#{window_id}' -- '%%'}}" \
" ''" \
" 'New After' 'w' {new-window -a}" \
" 'New At End' 'W' {new-window}"
@@ -350,16 +350,16 @@ key_bindings_init(void)
"bind -N 'Break pane to a new window' ! { break-pane }",
"bind -N 'Split window vertically' '\"' { split-window }",
"bind -N 'List all paste buffers' '#' { list-buffers }",
- "bind -N 'Rename current session' '$' { command-prompt -I'#S' \"rename-session -- '%%'\" }",
+ "bind -N 'Rename current session' '$' { command-prompt -I'#S' { rename-session -- '%%' } }",
"bind -N 'Split window horizontally' % { split-window -h }",
"bind -N 'Kill current window' & { confirm-before -p\"kill-window #W? (y/n)\" kill-window }",
- "bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex \"select-window -t ':%%'\" }",
+ "bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex { select-window -t ':%%' } }",
"bind -N 'Switch to previous client' ( { switch-client -p }",
"bind -N 'Switch to next client' ) { switch-client -n }",
- "bind -N 'Rename current window' , { command-prompt -I'#W' \"rename-window -- '%%'\" }",
+ "bind -N 'Rename current window' , { command-prompt -I'#W' { rename-window -- '%%' } }",
"bind -N 'Delete the most recent paste buffer' - { delete-buffer }",
- "bind -N 'Move the current window' . { command-prompt -T target \"move-window -t '%%'\" }",
- "bind -N 'Describe key binding' '/' { command-prompt -kpkey 'list-keys -1N \"%%%\"' }",
+ "bind -N 'Move the current window' . { command-prompt -T target { move-window -t '%%' } }",
+ "bind -N 'Describe key binding' '/' { command-prompt -kpkey { list-keys -1N '%%' } }",
"bind -N 'Select window 0' 0 { select-window -t:=0 }",
"bind -N 'Select window 1' 1 { select-window -t:=1 }",
"bind -N 'Select window 2' 2 { select-window -t:=2 }",
@@ -382,7 +382,7 @@ key_bindings_init(void)
"bind -N 'Paste the most recent paste buffer' ] { paste-buffer -p }",
"bind -N 'Create a new window' c { new-window }",
"bind -N 'Detach the current client' d { detach-client }",
- "bind -N 'Search for a pane' f { command-prompt \"find-window -Z -- '%%'\" }",
+ "bind -N 'Search for a pane' f { command-prompt { find-window -Z -- '%%' } }",
"bind -N 'Display window information' i { display-message }",
"bind -N 'Select the previously current window' l { last-window }",
"bind -N 'Toggle the marked pane' m { select-p