mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
418ab1a553
15
client.c
15
client.c
@ -251,16 +251,13 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
|
||||
* flag.
|
||||
*/
|
||||
cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause);
|
||||
if (cmdlist == NULL) {
|
||||
fprintf(stderr, "%s\n", cause);
|
||||
return (1);
|
||||
if (cmdlist != NULL) {
|
||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||
if (cmd->entry->flags & CMD_STARTSERVER)
|
||||
cmdflags |= CMD_STARTSERVER;
|
||||
}
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
cmdflags &= ~CMD_STARTSERVER;
|
||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||
if (cmd->entry->flags & CMD_STARTSERVER)
|
||||
cmdflags |= CMD_STARTSERVER;
|
||||
}
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
/* Create client process structure (starts logging). */
|
||||
|
@ -54,7 +54,6 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
||||
struct client *c = item->client, *c_loop;
|
||||
struct winlink *wl = item->state.tflag.wl;
|
||||
struct window_pane *wp = item->state.tflag.wp;
|
||||
const char *update;
|
||||
char *cause, *cwd;
|
||||
struct format_tree *ft;
|
||||
|
||||
@ -95,12 +94,8 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
||||
server_client_detach(c_loop, MSG_DETACH);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Eflag) {
|
||||
update = options_get_string(s->options,
|
||||
"update-environment");
|
||||
environ_update(update, c->environ, s->environ);
|
||||
}
|
||||
if (!Eflag)
|
||||
environ_update(s->options, c->environ, s->environ);
|
||||
|
||||
c->session = s;
|
||||
server_client_set_key_table(c, NULL);
|
||||
@ -116,7 +111,6 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
if (rflag)
|
||||
c->flags |= CLIENT_READONLY;
|
||||
|
||||
@ -127,12 +121,8 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
||||
server_client_detach(c_loop, MSG_DETACH);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Eflag) {
|
||||
update = options_get_string(s->options,
|
||||
"update-environment");
|
||||
environ_update(update, c->environ, s->environ);
|
||||
}
|
||||
if (!Eflag)
|
||||
environ_update(s->options, c->environ, s->environ);
|
||||
|
||||
c->session = s;
|
||||
server_client_set_key_table(c, NULL);
|
||||
|
@ -73,7 +73,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct window *w;
|
||||
struct environ *env;
|
||||
struct termios tio, *tiop;
|
||||
const char *newname, *target, *update, *errstr, *template;
|
||||
const char *newname, *target, *errstr, *template;
|
||||
const char *path, *cmd, *cwd, *to_free = NULL;
|
||||
char **argv, *cause, *cp;
|
||||
int detached, already_attached, idx, argc;
|
||||
@ -234,11 +234,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
/* Construct the environment. */
|
||||
env = environ_create();
|
||||
if (c != NULL && !args_has(args, 'E')) {
|
||||
update = options_get_string(global_s_options,
|
||||
"update-environment");
|
||||
environ_update(update, c->environ, env);
|
||||
}
|
||||
if (c != NULL && !args_has(args, 'E'))
|
||||
environ_update(global_s_options, c->environ, env);
|
||||
|
||||
/* Create the new session. */
|
||||
idx = -1 - options_get_number(global_s_options, "base-index");
|
||||
|
@ -68,6 +68,7 @@ static enum cmd_retval
|
||||
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
int append = args_has(args, 'a');
|
||||
struct cmd_find_state *fs = &item->state.tflag;
|
||||
struct session *s = fs->s;
|
||||
struct winlink *wl = fs->wl;
|
||||
@ -160,17 +161,6 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cmdq_error(item, "not an array: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
} else if (*name != '@' && options_array_size(parent, NULL) != -1) {
|
||||
if (value == NULL) {
|
||||
cmdq_error(item, "empty value");
|
||||
return (-1);
|
||||
}
|
||||
if (o == NULL)
|
||||
o = options_empty(oo, options_table_entry(parent));
|
||||
if (!args_has(args, 'a'))
|
||||
options_array_clear(o);
|
||||
options_array_assign(o, value);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
/* With -o, check this option is not already set. */
|
||||
@ -204,16 +194,26 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||
options_remove(o);
|
||||
} else
|
||||
options_array_set(o, idx, NULL, 0);
|
||||
} else if (*name == '@')
|
||||
options_set_string(oo, name, args_has(args, 'a'), "%s", value);
|
||||
else if (idx == -1) {
|
||||
} else if (*name == '@') {
|
||||
if (value == NULL) {
|
||||
cmdq_error(item, "empty value");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
options_set_string(oo, name, append, "%s", value);
|
||||
} else if (idx == -1 && options_array_size(parent, NULL) == -1) {
|
||||
error = cmd_set_option_set(self, item, oo, parent, value);
|
||||
if (error != 0)
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else {
|
||||
if (value == NULL) {
|
||||
cmdq_error(item, "empty value");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (o == NULL)
|
||||
o = options_empty(oo, options_table_entry(parent));
|
||||
if (options_array_set(o, idx, value, 1) != 0) {
|
||||
if (idx == -1)
|
||||
options_array_assign(o, value);
|
||||
else if (options_array_set(o, idx, value, append) != 0) {
|
||||
cmdq_error(item, "invalid index: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
@ -44,17 +44,6 @@ const struct cmd_entry cmd_show_messages_entry = {
|
||||
.exec = cmd_show_messages_exec
|
||||
};
|
||||
|
||||
const struct cmd_entry cmd_server_info_entry = {
|
||||
.name = "server-info",
|
||||
.alias = "info",
|
||||
|
||||
.args = { "", 0, 0 },
|
||||
.usage = "",
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
.exec = cmd_show_messages_exec
|
||||
};
|
||||
|
||||
static int cmd_show_messages_terminals(struct cmdq_item *, int);
|
||||
static int cmd_show_messages_jobs(struct cmdq_item *, int);
|
||||
|
||||
@ -108,11 +97,11 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
|
||||
int done, blank;
|
||||
|
||||
done = blank = 0;
|
||||
if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
|
||||
if (args_has(args, 'T')) {
|
||||
blank = cmd_show_messages_terminals(item, blank);
|
||||
done = 1;
|
||||
}
|
||||
if (args_has(args, 'J') || self->entry == &cmd_server_info_entry) {
|
||||
if (args_has(args, 'J')) {
|
||||
cmd_show_messages_jobs(item, blank);
|
||||
done = 1;
|
||||
}
|
||||
|
94
cmd-string.c
94
cmd-string.c
@ -54,17 +54,15 @@ cmd_string_ungetc(size_t *p)
|
||||
(*p)--;
|
||||
}
|
||||
|
||||
struct cmd_list *
|
||||
cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
|
||||
int
|
||||
cmd_string_split(const char *s, int *rargc, char ***rargv)
|
||||
{
|
||||
size_t p = 0;
|
||||
int ch, i, argc = 0;
|
||||
char **argv = NULL, *buf = NULL, *t;
|
||||
const char *whitespace, *equals;
|
||||
size_t len = 0;
|
||||
struct cmd_list *cmdlist = NULL;
|
||||
size_t p = 0;
|
||||
int ch, argc = 0, append = 0;
|
||||
char **argv = NULL, *buf = NULL, *t;
|
||||
const char *whitespace, *equals;
|
||||
size_t len = 0;
|
||||
|
||||
*cause = NULL;
|
||||
for (;;) {
|
||||
ch = cmd_string_getc(s, &p);
|
||||
switch (ch) {
|
||||
@ -115,43 +113,67 @@ cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
|
||||
argc--;
|
||||
memmove(argv, argv + 1, argc * (sizeof *argv));
|
||||
}
|
||||
if (argc == 0)
|
||||
goto out;
|
||||
|
||||
cmdlist = cmd_list_parse(argc, argv, file, line, cause);
|
||||
goto out;
|
||||
goto done;
|
||||
case '~':
|
||||
if (buf == NULL) {
|
||||
t = cmd_string_expand_tilde(s, &p);
|
||||
if (t == NULL)
|
||||
goto error;
|
||||
cmd_string_copy(&buf, t, &len);
|
||||
if (buf != NULL) {
|
||||
append = 1;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if (len >= SIZE_MAX - 2)
|
||||
t = cmd_string_expand_tilde(s, &p);
|
||||
if (t == NULL)
|
||||
goto error;
|
||||
|
||||
buf = xrealloc(buf, len + 1);
|
||||
buf[len++] = ch;
|
||||
cmd_string_copy(&buf, t, &len);
|
||||
break;
|
||||
default:
|
||||
append = 1;
|
||||
break;
|
||||
}
|
||||
if (append) {
|
||||
if (len >= SIZE_MAX - 2)
|
||||
goto error;
|
||||
buf = xrealloc(buf, len + 1);
|
||||
buf[len++] = ch;
|
||||
}
|
||||
append = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
*rargc = argc;
|
||||
*rargv = argv;
|
||||
|
||||
free(buf);
|
||||
return (0);
|
||||
|
||||
error:
|
||||
if (argv != NULL)
|
||||
cmd_free_argv(argc, argv);
|
||||
free(buf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
struct cmd_list *
|
||||
cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
|
||||
{
|
||||
struct cmd_list *cmdlist = NULL;
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
*cause = NULL;
|
||||
if (cmd_string_split(s, &argc, &argv) != 0)
|
||||
goto error;
|
||||
if (argc != 0) {
|
||||
cmdlist = cmd_list_parse(argc, argv, file, line, cause);
|
||||
if (cmdlist == NULL) {
|
||||
cmd_free_argv(argc, argv);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
cmd_free_argv(argc, argv);
|
||||
return (cmdlist);
|
||||
|
||||
error:
|
||||
xasprintf(cause, "invalid or unknown command: %s", s);
|
||||
|
||||
out:
|
||||
free(buf);
|
||||
|
||||
if (argv != NULL) {
|
||||
for (i = 0; i < argc; i++)
|
||||
free(argv[i]);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
return (cmdlist);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -53,7 +53,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct client *c = state->c;
|
||||
struct session *s = item->state.tflag.s;
|
||||
struct window_pane *wp;
|
||||
const char *tablename, *update;
|
||||
const char *tablename;
|
||||
struct key_table *table;
|
||||
|
||||
if (args_has(args, 'r'))
|
||||
@ -102,10 +102,8 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
}
|
||||
|
||||
if (!args_has(args, 'E')) {
|
||||
update = options_get_string(s->options, "update-environment");
|
||||
environ_update(update, c->environ, s->environ);
|
||||
}
|
||||
if (!args_has(args, 'E'))
|
||||
environ_update(s->options, c->environ, s->environ);
|
||||
|
||||
if (c->session != NULL && c->session != s)
|
||||
c->last_session = c->session;
|
||||
|
70
cmd.c
70
cmd.c
@ -92,7 +92,6 @@ extern const struct cmd_entry cmd_select_pane_entry;
|
||||
extern const struct cmd_entry cmd_select_window_entry;
|
||||
extern const struct cmd_entry cmd_send_keys_entry;
|
||||
extern const struct cmd_entry cmd_send_prefix_entry;
|
||||
extern const struct cmd_entry cmd_server_info_entry;
|
||||
extern const struct cmd_entry cmd_set_buffer_entry;
|
||||
extern const struct cmd_entry cmd_set_environment_entry;
|
||||
extern const struct cmd_entry cmd_set_hook_entry;
|
||||
@ -181,7 +180,6 @@ const struct cmd_entry *cmd_table[] = {
|
||||
&cmd_select_window_entry,
|
||||
&cmd_send_keys_entry,
|
||||
&cmd_send_prefix_entry,
|
||||
&cmd_server_info_entry,
|
||||
&cmd_set_buffer_entry,
|
||||
&cmd_set_environment_entry,
|
||||
&cmd_set_hook_entry,
|
||||
@ -307,21 +305,74 @@ cmd_stringify_argv(int argc, char **argv)
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_try_alias(int *argc, char ***argv)
|
||||
{
|
||||
struct options_entry *o;
|
||||
int old_argc = *argc, new_argc;
|
||||
char **old_argv = *argv, **new_argv;
|
||||
u_int size, idx;
|
||||
int i;
|
||||
size_t wanted;
|
||||
const char *s, *cp = NULL;
|
||||
|
||||
o = options_get_only(global_options, "command-alias");
|
||||
if (o == NULL || options_array_size(o, &size) == -1 || size == 0)
|
||||
return (-1);
|
||||
|
||||
wanted = strlen(old_argv[0]);
|
||||
for (idx = 0; idx < size; idx++) {
|
||||
s = options_array_get(o, idx);
|
||||
if (s == NULL)
|
||||
continue;
|
||||
|
||||
cp = strchr(s, '=');
|
||||
if (cp == NULL || (size_t)(cp - s) != wanted)
|
||||
continue;
|
||||
if (strncmp(old_argv[0], s, wanted) == 0)
|
||||
break;
|
||||
}
|
||||
if (idx == size)
|
||||
return (-1);
|
||||
|
||||
if (cmd_string_split(cp + 1, &new_argc, &new_argv) != 0)
|
||||
return (-1);
|
||||
|
||||
*argc = new_argc + old_argc - 1;
|
||||
*argv = xcalloc((*argc) + 1, sizeof **argv);
|
||||
|
||||
for (i = 0; i < new_argc; i++)
|
||||
(*argv)[i] = xstrdup(new_argv[i]);
|
||||
for (i = 1; i < old_argc; i++)
|
||||
(*argv)[new_argc + i - 1] = xstrdup(old_argv[i]);
|
||||
|
||||
log_debug("alias: %s=%s", old_argv[0], cp + 1);
|
||||
for (i = 0; i < *argc; i++)
|
||||
log_debug("alias: argv[%d] = %s", i, (*argv)[i]);
|
||||
|
||||
cmd_free_argv(new_argc, new_argv);
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct cmd *
|
||||
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
||||
{
|
||||
const char *name;
|
||||
const struct cmd_entry **entryp, *entry;
|
||||
struct cmd *cmd;
|
||||
struct args *args;
|
||||
char s[BUFSIZ];
|
||||
int ambiguous = 0;
|
||||
int ambiguous, allocated = 0;
|
||||
|
||||
*cause = NULL;
|
||||
if (argc == 0) {
|
||||
xasprintf(cause, "no command");
|
||||
return (NULL);
|
||||
}
|
||||
name = argv[0];
|
||||
|
||||
retry:
|
||||
ambiguous = 0;
|
||||
entry = NULL;
|
||||
for (entryp = cmd_table; *entryp != NULL; entryp++) {
|
||||
if ((*entryp)->alias != NULL &&
|
||||
@ -341,10 +392,17 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
||||
if (strcmp(entry->name, argv[0]) == 0)
|
||||
break;
|
||||
}
|
||||
if ((ambiguous || entry == NULL) &&
|
||||
server_proc != NULL &&
|
||||
!allocated &&
|
||||
cmd_try_alias(&argc, &argv) == 0) {
|
||||
allocated = 1;
|
||||
goto retry;
|
||||
}
|
||||
if (ambiguous)
|
||||
goto ambiguous;
|
||||
if (entry == NULL) {
|
||||
xasprintf(cause, "unknown command: %s", argv[0]);
|
||||
xasprintf(cause, "unknown command: %s", name);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -364,6 +422,8 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
||||
cmd->file = xstrdup(file);
|
||||
cmd->line = line;
|
||||
|
||||
if (allocated)
|
||||
cmd_free_argv(argc, argv);
|
||||
return (cmd);
|
||||
|
||||
ambiguous:
|
||||
@ -377,7 +437,7 @@ ambiguous:
|
||||
break;
|
||||
}
|
||||
s[strlen(s) - 2] = '\0';
|
||||
xasprintf(cause, "ambiguous command: %s, could be: %s", argv[0], s);
|
||||
xasprintf(cause, "ambiguous command: %s, could be: %s", name, s);
|
||||
return (NULL);
|
||||
|
||||
usage:
|
||||
|
28
environ.c
28
environ.c
@ -169,25 +169,27 @@ environ_unset(struct environ *env, const char *name)
|
||||
free(envent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a space-separated list of variables from a destination into a source
|
||||
* environment.
|
||||
*/
|
||||
/* Copy variables from a destination into a source * environment. */
|
||||
void
|
||||
environ_update(const char *vars, struct environ *srcenv,
|
||||
struct environ *dstenv)
|
||||
environ_update(struct options *oo, struct environ *src, struct environ *dst)
|
||||
{
|
||||
struct environ_entry *envent;
|
||||
char *copyvars, *var, *next;
|
||||
struct options_entry *o;
|
||||
u_int size, idx;
|
||||
const char *value;
|
||||
|
||||
copyvars = next = xstrdup(vars);
|
||||
while ((var = strsep(&next, " ")) != NULL) {
|
||||
if ((envent = environ_find(srcenv, var)) == NULL)
|
||||
environ_clear(dstenv, var);
|
||||
o = options_get(oo, "update-environment");
|
||||
if (o == NULL || options_array_size(o, &size) == -1)
|
||||
return;
|
||||
for (idx = 0; idx < size; idx++) {
|
||||
value = options_array_get(o, idx);
|
||||
if (value == NULL)
|
||||
continue;
|
||||
if ((envent = environ_find(src, value)) == NULL)
|
||||
environ_clear(dst, value);
|
||||
else
|
||||
environ_set(dstenv, envent->name, "%s", envent->value);
|
||||
environ_set(dst, envent->name, "%s", envent->value);
|
||||
}
|
||||
free(copyvars);
|
||||
}
|
||||
|
||||
/* Push environment into the real environment - use after fork(). */
|
||||
|
@ -383,7 +383,7 @@ key_bindings_init(void)
|
||||
for (i = 0; i < nitems(defaults); i++) {
|
||||
cmdlist = cmd_string_parse(defaults[i], "<default>", i, &cause);
|
||||
if (cmdlist == NULL)
|
||||
fatalx("bad default key");
|
||||
fatalx("bad default key: %s", defaults[i]);
|
||||
cmdq_append(NULL, cmdq_get_command(cmdlist, NULL, NULL, 0));
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
@ -64,6 +64,16 @@ const struct options_table_entry options_table[] = {
|
||||
.default_num = 20
|
||||
},
|
||||
|
||||
{ .name = "command-alias",
|
||||
.type = OPTIONS_TABLE_ARRAY,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.default_str = "split-pane=split-window,"
|
||||
"splitp=split-window,"
|
||||
"server-info=show-messages -JT,"
|
||||
"info=show-messages -JT",
|
||||
.separator = ","
|
||||
},
|
||||
|
||||
{ .name = "default-terminal",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
@ -111,11 +121,12 @@ const struct options_table_entry options_table[] = {
|
||||
},
|
||||
|
||||
{ .name = "terminal-overrides",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.type = OPTIONS_TABLE_ARRAY,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.default_str = "xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
|
||||
":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007"
|
||||
":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT"
|
||||
":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT",
|
||||
.separator = ","
|
||||
},
|
||||
|
||||
{ .name = "assume-paste-time",
|
||||
@ -470,11 +481,10 @@ const struct options_table_entry options_table[] = {
|
||||
},
|
||||
|
||||
{ .name = "update-environment",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.type = OPTIONS_TABLE_ARRAY,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
.default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
|
||||
"SSH_CONNECTION WINDOWID XAUTHORITY"
|
||||
|
||||
},
|
||||
|
||||
{ .name = "visual-activity",
|
||||
|
2
pty.c
2
pty.c
@ -53,7 +53,7 @@ pty_fork(int ptmfd, int *fd, char *name, size_t namelen, struct winsize *ws)
|
||||
struct ptmget ptm;
|
||||
pid_t pid;
|
||||
|
||||
if ((ioctl(ptmfd, PTMGET, &ptm) == -1))
|
||||
if (ioctl(ptmfd, PTMGET, &ptm) == -1)
|
||||
return (-1);
|
||||
|
||||
strlcpy(name, ptm.sn, namelen);
|
||||
|
66
tmux.1
66
tmux.1
@ -2414,6 +2414,30 @@ Available server options are:
|
||||
Set the number of buffers; as new buffers are added to the top of the stack,
|
||||
old ones are removed from the bottom if necessary to maintain this maximum
|
||||
length.
|
||||
.It Xo Ic command-alias[]
|
||||
.Ar name=value
|
||||
.Xc
|
||||
This is an array of custom aliases for commands.
|
||||
If an unknown command matches
|
||||
.Ar name ,
|
||||
it is replaced with
|
||||
.Ar value .
|
||||
For example, after:
|
||||
.Pp
|
||||
.Dl set -s command-alias[2] zoom='resize-pane -Z'
|
||||
.Pp
|
||||
Using:
|
||||
.Pp
|
||||
.Dl zoom -t:.1
|
||||
.Pp
|
||||
Is equivalent to:
|
||||
.Pp
|
||||
.Dl resize-pane -Z -t:.1
|
||||
.Pp
|
||||
Note that aliases are expanded when a command is parsed rather than when it is
|
||||
executed, so binding an alias with
|
||||
.Ic bind-key
|
||||
will bind the expanded form.
|
||||
.It Ic default-terminal Ar terminal
|
||||
Set the default terminal for new windows created in this session - the
|
||||
default value of the
|
||||
@ -2475,12 +2499,12 @@ disallowedWindowOps: 20,21,SetXprop
|
||||
Or changing this property from the
|
||||
.Xr xterm 1
|
||||
interactive menu when required.
|
||||
.It Ic terminal-overrides Ar string
|
||||
Contains a list of entries which override terminal descriptions read using
|
||||
.Xr terminfo 5 .
|
||||
.Ar string
|
||||
is a comma-separated list of items each a colon-separated string made up of a
|
||||
terminal type pattern (matched using
|
||||
.It Ic terminal-overrides[] Ar string
|
||||
Allow terminal descriptions read using
|
||||
.Xr terminfo 5
|
||||
to be overriden.
|
||||
Each entry is a colon-separated string made up of a terminal type pattern
|
||||
(matched using
|
||||
.Xr fnmatch 3 )
|
||||
and a set of
|
||||
.Em name=value
|
||||
@ -2491,26 +2515,14 @@ For example, to set the
|
||||
.Xr terminfo 5
|
||||
entry to
|
||||
.Ql \ee[H\ee[2J
|
||||
for all terminal types and the
|
||||
.Ql dch1
|
||||
entry to
|
||||
.Ql \ee[P
|
||||
for the
|
||||
.Ql rxvt
|
||||
terminal type, the option could be set to the string:
|
||||
.Bd -literal -offset indent
|
||||
"*:clear=\ee[H\ee[2J,rxvt:dch1=\ee[P"
|
||||
.Ed
|
||||
for all terminal types matching
|
||||
.Ql rxvt* :
|
||||
.Pp
|
||||
.Dl "rxvt*:clear=\ee[H\ee[2J"
|
||||
.Pp
|
||||
The terminal entry value is passed through
|
||||
.Xr strunvis 3
|
||||
before interpretation.
|
||||
The default value forcibly corrects the
|
||||
.Ql colors
|
||||
entry for terminals which support 256 colours:
|
||||
.Bd -literal -offset indent
|
||||
"*256col*:colors=256,xterm*:XT"
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
Available session options are:
|
||||
@ -2861,19 +2873,15 @@ For how to specify
|
||||
see the
|
||||
.Ic message-command-style
|
||||
option.
|
||||
.It Ic update-environment Ar variables
|
||||
Set a space-separated string containing a list of environment variables to be
|
||||
copied into the session environment when a new session is created or an
|
||||
existing session is attached.
|
||||
.It Ic update-environment[] Ar variable
|
||||
Set list of environment variables to be copied into the session environment
|
||||
when a new session is created or an existing session is attached.
|
||||
Any variables that do not exist in the source environment are set to be
|
||||
removed from the session environment (as if
|
||||
.Fl r
|
||||
was given to the
|
||||
.Ic set-environment
|
||||
command).
|
||||
The default is
|
||||
"DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION WINDOWID
|
||||
XAUTHORITY".
|
||||
.It Xo Ic visual-activity
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
|
3
tmux.h
3
tmux.h
@ -1671,7 +1671,7 @@ void printflike(3, 4) environ_set(struct environ *, const char *, const char *,
|
||||
void environ_clear(struct environ *, const char *);
|
||||
void environ_put(struct environ *, const char *);
|
||||
void environ_unset(struct environ *, const char *);
|
||||
void environ_update(const char *, struct environ *, struct environ *);
|
||||
void environ_update(struct options *, struct environ *, struct environ *);
|
||||
void environ_push(struct environ *);
|
||||
void environ_log(struct environ *, const char *);
|
||||
|
||||
@ -1830,6 +1830,7 @@ void printflike(2, 3) cmdq_print(struct cmdq_item *, const char *, ...);
|
||||
void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...);
|
||||
|
||||
/* cmd-string.c */
|
||||
int cmd_string_split(const char *, int *, char ***);
|
||||
struct cmd_list *cmd_string_parse(const char *, const char *, u_int, char **);
|
||||
|
||||
/* cmd-wait-for.c */
|
||||
|
151
tty-term.c
151
tty-term.c
@ -297,86 +297,82 @@ tty_term_strip(const char *s)
|
||||
}
|
||||
|
||||
static void
|
||||
tty_term_override(struct tty_term *term, const char *overrides)
|
||||
tty_term_override(struct tty_term *term, const char *override)
|
||||
{
|
||||
const struct tty_term_code_entry *ent;
|
||||
struct tty_code *code;
|
||||
char *termnext, *termstr;
|
||||
char *entnext, *entstr;
|
||||
char *s, *ptr, *val;
|
||||
char *next, *s, *copy, *cp, *value;
|
||||
const char *errstr;
|
||||
u_int i;
|
||||
int n, removeflag;
|
||||
int n, remove;
|
||||
|
||||
s = xstrdup(overrides);
|
||||
copy = next = xstrdup(override);
|
||||
|
||||
termnext = s;
|
||||
while ((termstr = strsep(&termnext, ",")) != NULL) {
|
||||
entnext = termstr;
|
||||
|
||||
entstr = strsep(&entnext, ":");
|
||||
if (entstr == NULL || entnext == NULL)
|
||||
continue;
|
||||
if (fnmatch(entstr, term->name, 0) != 0)
|
||||
continue;
|
||||
while ((entstr = strsep(&entnext, ":")) != NULL) {
|
||||
if (*entstr == '\0')
|
||||
continue;
|
||||
|
||||
val = NULL;
|
||||
removeflag = 0;
|
||||
if ((ptr = strchr(entstr, '=')) != NULL) {
|
||||
*ptr++ = '\0';
|
||||
val = xstrdup(ptr);
|
||||
if (strunvis(val, ptr) == -1) {
|
||||
free(val);
|
||||
val = xstrdup(ptr);
|
||||
}
|
||||
} else if (entstr[strlen(entstr) - 1] == '@') {
|
||||
entstr[strlen(entstr) - 1] = '\0';
|
||||
removeflag = 1;
|
||||
} else
|
||||
val = xstrdup("");
|
||||
|
||||
log_debug("%s override: %s %s",
|
||||
term->name, entstr, removeflag ? "@" : val);
|
||||
for (i = 0; i < tty_term_ncodes(); i++) {
|
||||
ent = &tty_term_codes[i];
|
||||
if (strcmp(entstr, ent->name) != 0)
|
||||
continue;
|
||||
code = &term->codes[i];
|
||||
|
||||
if (removeflag) {
|
||||
code->type = TTYCODE_NONE;
|
||||
continue;
|
||||
}
|
||||
switch (ent->type) {
|
||||
case TTYCODE_NONE:
|
||||
break;
|
||||
case TTYCODE_STRING:
|
||||
if (code->type == TTYCODE_STRING)
|
||||
free(code->value.string);
|
||||
code->value.string = xstrdup(val);
|
||||
code->type = ent->type;
|
||||
break;
|
||||
case TTYCODE_NUMBER:
|
||||
n = strtonum(val, 0, INT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
break;
|
||||
code->value.number = n;
|
||||
code->type = ent->type;
|
||||
break;
|
||||
case TTYCODE_FLAG:
|
||||
code->value.flag = 1;
|
||||
code->type = ent->type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(val);
|
||||
}
|
||||
s = strsep(&next, ":");
|
||||
if (s == NULL || next == NULL || fnmatch(s, term->name, 0) != 0) {
|
||||
free(copy);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((s = strsep(&next, ":")) != NULL) {
|
||||
if (*s == '\0')
|
||||
continue;
|
||||
value = NULL;
|
||||
|
||||
remove = 0;
|
||||
if ((cp = strchr(s, '=')) != NULL) {
|
||||
*cp++ = '\0';
|
||||
value = xstrdup(cp);
|
||||
if (strunvis(value, cp) == -1) {
|
||||
free(value);
|
||||
value = xstrdup(cp);
|
||||
}
|
||||
} else if (s[strlen(s) - 1] == '@') {
|
||||
s[strlen(s) - 1] = '\0';
|
||||
remove = 1;
|
||||
} else
|
||||
value = xstrdup("");
|
||||
|
||||
if (remove)
|
||||
log_debug("%s override: %s@", term->name, s);
|
||||
else
|
||||
log_debug("%s override: %s=%s", term->name, s, value);
|
||||
|
||||
for (i = 0; i < tty_term_ncodes(); i++) {
|
||||
ent = &tty_term_codes[i];
|
||||
if (strcmp(s, ent->name) != 0)
|
||||
continue;
|
||||
code = &term->codes[i];
|
||||
|
||||
if (remove) {
|
||||
code->type = TTYCODE_NONE;
|
||||
continue;
|
||||
}
|
||||
switch (ent->type) {
|
||||
case TTYCODE_NONE:
|
||||
break;
|
||||
case TTYCODE_STRING:
|
||||
if (code->type == TTYCODE_STRING)
|
||||
free(code->value.string);
|
||||
code->value.string = xstrdup(value);
|
||||
code->type = ent->type;
|
||||
break;
|
||||
case TTYCODE_NUMBER:
|
||||
n = strtonum(value, 0, INT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
break;
|
||||
code->value.number = n;
|
||||
code->type = ent->type;
|
||||
break;
|
||||
case TTYCODE_FLAG:
|
||||
code->value.flag = 1;
|
||||
code->type = ent->type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(value);
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
|
||||
@ -386,7 +382,8 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
struct tty_term *term;
|
||||
const struct tty_term_code_entry *ent;
|
||||
struct tty_code *code;
|
||||
u_int i;
|
||||
struct options_entry *o;
|
||||
u_int size, i;
|
||||
int n, error;
|
||||
const char *s, *acs;
|
||||
|
||||
@ -460,8 +457,14 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
}
|
||||
|
||||
/* Apply terminal overrides. */
|
||||
s = options_get_string(global_options, "terminal-overrides");
|
||||
tty_term_override(term, s);
|
||||
o = options_get_only(global_options, "terminal-overrides");
|
||||
if (options_array_size(o, &size) != -1) {
|
||||
for (i = 0; i < size; i++) {
|
||||
s = options_array_get(o, i);
|
||||
if (s != NULL)
|
||||
tty_term_override(term, s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete curses data. */
|
||||
#if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \
|
||||
|
Loading…
Reference in New Issue
Block a user