mirror of
https://github.com/tmux/tmux.git
synced 2025-09-06 11:28:24 +00:00
Merge branch 'obsd-master'
This commit is contained in:
@@ -44,8 +44,8 @@ const struct cmd_entry cmd_run_shell_entry = {
|
||||
.name = "run-shell",
|
||||
.alias = "run",
|
||||
|
||||
.args = { "bd:Ct:c:", 0, 1, cmd_run_shell_args_parse },
|
||||
.usage = "[-bC] [-c start-directory] [-d delay] " CMD_TARGET_PANE_USAGE
|
||||
.args = { "bd:Ct:Es:c:", 0, 1, cmd_run_shell_args_parse },
|
||||
.usage = "[-bCE] [-c start-directory] [-d delay] " CMD_TARGET_PANE_USAGE
|
||||
" [shell-command]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||
@@ -158,6 +158,9 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
else
|
||||
cdata->cwd = xstrdup(server_client_get_cwd(c, s));
|
||||
|
||||
if (args_has(args, 'E'))
|
||||
cdata->flags |= JOB_SHOWSTDERR;
|
||||
|
||||
cdata->s = s;
|
||||
if (s != NULL)
|
||||
session_add_ref(s, __func__);
|
||||
|
49
format.c
49
format.c
@@ -106,6 +106,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
|
||||
#define FORMAT_CLIENTS 0x40000
|
||||
#define FORMAT_NOT 0x80000
|
||||
#define FORMAT_NOT_NOT 0x100000
|
||||
#define FORMAT_REPEAT 0x200000
|
||||
|
||||
/* Limit on recursion. */
|
||||
#define FORMAT_LOOP_LIMIT 100
|
||||
@@ -205,7 +206,7 @@ static const char *format_upper[] = {
|
||||
"window_name", /* W */
|
||||
NULL, /* X */
|
||||
NULL, /* Y */
|
||||
NULL /* Z */
|
||||
NULL /* Z */
|
||||
};
|
||||
|
||||
/* Single-character lowercase aliases. */
|
||||
@@ -865,7 +866,7 @@ format_cb_history_bytes(struct format_tree *ft)
|
||||
struct window_pane *wp = ft->wp;
|
||||
struct grid *gd;
|
||||
struct grid_line *gl;
|
||||
size_t size = 0;
|
||||
size_t size = 0;
|
||||
u_int i;
|
||||
char *value;
|
||||
|
||||
@@ -1623,11 +1624,11 @@ format_cb_cursor_shape(struct format_tree *ft)
|
||||
switch (ft->wp->screen->cstyle) {
|
||||
case SCREEN_CURSOR_BLOCK:
|
||||
return (xstrdup("block"));
|
||||
case SCREEN_CURSOR_UNDERLINE:
|
||||
case SCREEN_CURSOR_UNDERLINE:
|
||||
return (xstrdup("underline"));
|
||||
case SCREEN_CURSOR_BAR:
|
||||
case SCREEN_CURSOR_BAR:
|
||||
return (xstrdup("bar"));
|
||||
default:
|
||||
default:
|
||||
return (xstrdup("default"));
|
||||
}
|
||||
}
|
||||
@@ -3672,7 +3673,7 @@ format_quote_style(const char *s)
|
||||
char *
|
||||
format_pretty_time(time_t t, int seconds)
|
||||
{
|
||||
struct tm now_tm, tm;
|
||||
struct tm now_tm, tm;
|
||||
time_t now, age;
|
||||
char s[9];
|
||||
|
||||
@@ -3850,7 +3851,7 @@ format_unescape(const char *s)
|
||||
*s == '#' &&
|
||||
strchr(",#{}:", s[1]) != NULL) {
|
||||
*cp++ = *++s;
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
if (*s == '}')
|
||||
brackets--;
|
||||
@@ -3992,10 +3993,10 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
||||
|
||||
/*
|
||||
* Modifiers are a ; separated list of the forms:
|
||||
* l,m,C,a,b,c,d,n,t,w,q,E,T,S,W,P,<,>
|
||||
* l,m,C,a,b,c,d,n,t,w,q,E,T,S,W,P,R,<,>
|
||||
* =a
|
||||
* =/a
|
||||
* =/a/
|
||||
* =/a/
|
||||
* s/a/b/
|
||||
* s/a/b
|
||||
* ||,&&,!=,==,<=,>=
|
||||
@@ -4031,7 +4032,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
||||
}
|
||||
|
||||
/* Now try single character with arguments. */
|
||||
if (strchr("mCNst=peq", cp[0]) == NULL)
|
||||
if (strchr("mCNst=pReq", cp[0]) == NULL)
|
||||
break;
|
||||
c = cp[0];
|
||||
|
||||
@@ -4586,7 +4587,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
struct format_modifier *list, *cmp = NULL, *search = NULL;
|
||||
struct format_modifier **sub = NULL, *mexp = NULL, *fm;
|
||||
struct format_modifier *bool_op_n = NULL;
|
||||
u_int i, count, nsub = 0;
|
||||
u_int i, count, nsub = 0, nrep;
|
||||
struct format_expand_state next;
|
||||
|
||||
/* Make a copy of the key. */
|
||||
@@ -4708,6 +4709,9 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
case 'L':
|
||||
modifiers |= FORMAT_CLIENTS;
|
||||
break;
|
||||
case 'R':
|
||||
modifiers |= FORMAT_REPEAT;
|
||||
break;
|
||||
}
|
||||
} else if (fm->size == 2) {
|
||||
if (strcmp(fm->modifier, "||") == 0 ||
|
||||
@@ -4790,7 +4794,26 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
value = format_search(search, wp, new);
|
||||
}
|
||||
free(new);
|
||||
} else if (modifiers & FORMAT_NOT) {
|
||||
} else if (modifiers & FORMAT_REPEAT) {
|
||||
/* Repeat multiple times. */
|
||||
if (format_choose(es, copy, &left, &right, 1) != 0) {
|
||||
format_log(es, "repeat syntax error: %s", copy);
|
||||
goto fail;
|
||||
}
|
||||
nrep = strtonum(right, 1, 10000, &errstr);
|
||||
if (errstr != NULL)
|
||||
value = xstrdup("");
|
||||
else {
|
||||
value = xstrdup("");
|
||||
for (i = 0; i < nrep; i++) {
|
||||
xasprintf(&new, "%s%s", value, left);
|
||||
free(value);
|
||||
value = new;
|
||||
}
|
||||
}
|
||||
free(right);
|
||||
free(left);
|
||||
} else if (modifiers & FORMAT_NOT) {
|
||||
value = format_bool_op_1(es, copy, 1);
|
||||
} else if (modifiers & FORMAT_NOT_NOT) {
|
||||
value = format_bool_op_1(es, copy, 0);
|
||||
@@ -5050,7 +5073,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
||||
char *buf, *out, *name;
|
||||
const char *ptr, *s, *style_end = NULL;
|
||||
size_t off, len, n, outlen;
|
||||
int ch, brackets;
|
||||
int ch, brackets;
|
||||
char expanded[8192];
|
||||
|
||||
if (fmt == NULL || *fmt == '\0')
|
||||
|
27
job.c
27
job.c
@@ -77,7 +77,7 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e,
|
||||
struct job *job;
|
||||
struct environ *env;
|
||||
pid_t pid;
|
||||
int nullfd, out[2], master;
|
||||
int nullfd, out[2], master, do_close = 1;
|
||||
const char *home, *shell;
|
||||
sigset_t set, oldset;
|
||||
struct winsize ws;
|
||||
@@ -150,19 +150,26 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e,
|
||||
if (~flags & JOB_PTY) {
|
||||
if (dup2(out[1], STDIN_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
do_close = do_close && out[1] != STDIN_FILENO;
|
||||
if (dup2(out[1], STDOUT_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (out[1] != STDIN_FILENO && out[1] != STDOUT_FILENO)
|
||||
do_close = do_close && out[1] != STDOUT_FILENO;
|
||||
if (flags & JOB_SHOWSTDERR) {
|
||||
if (dup2(out[1], STDERR_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
do_close = do_close && out[1] != STDERR_FILENO;
|
||||
} else {
|
||||
nullfd = open(_PATH_DEVNULL, O_RDWR);
|
||||
if (nullfd == -1)
|
||||
fatal("open failed");
|
||||
if (dup2(nullfd, STDERR_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (nullfd != STDERR_FILENO)
|
||||
close(nullfd);
|
||||
}
|
||||
if (do_close)
|
||||
close(out[1]);
|
||||
close(out[0]);
|
||||
|
||||
nullfd = open(_PATH_DEVNULL, O_RDWR);
|
||||
if (nullfd == -1)
|
||||
fatal("open failed");
|
||||
if (dup2(nullfd, STDERR_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
if (nullfd != STDERR_FILENO)
|
||||
close(nullfd);
|
||||
}
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
|
||||
|
47
status.c
47
status.c
@@ -631,17 +631,18 @@ status_prompt_set(struct client *c, struct cmd_find_state *fs,
|
||||
|
||||
if (input == NULL)
|
||||
input = "";
|
||||
if (flags & PROMPT_NOFORMAT)
|
||||
tmp = xstrdup(input);
|
||||
else
|
||||
tmp = format_expand_time(ft, input);
|
||||
|
||||
status_message_clear(c);
|
||||
status_prompt_clear(c);
|
||||
status_push_screen(c);
|
||||
|
||||
c->prompt_string = format_expand_time(ft, msg);
|
||||
c->prompt_formats = ft;
|
||||
c->prompt_string = xstrdup (msg);
|
||||
|
||||
if (flags & PROMPT_NOFORMAT)
|
||||
tmp = xstrdup(input);
|
||||
else
|
||||
tmp = format_expand_time(ft, input);
|
||||
if (flags & PROMPT_INCREMENTAL) {
|
||||
c->prompt_last = xstrdup(tmp);
|
||||
c->prompt_buffer = utf8_fromcstr("");
|
||||
@@ -650,6 +651,7 @@ status_prompt_set(struct client *c, struct cmd_find_state *fs,
|
||||
c->prompt_buffer = utf8_fromcstr(tmp);
|
||||
}
|
||||
c->prompt_index = utf8_strlen(c->prompt_buffer);
|
||||
free(tmp);
|
||||
|
||||
c->prompt_inputcb = inputcb;
|
||||
c->prompt_freecb = freecb;
|
||||
@@ -668,9 +670,6 @@ status_prompt_set(struct client *c, struct cmd_find_state *fs,
|
||||
if (flags & PROMPT_INCREMENTAL)
|
||||
c->prompt_inputcb(c, c->prompt_data, "=", 0);
|
||||
|
||||
free(tmp);
|
||||
format_free(ft);
|
||||
|
||||
if ((flags & PROMPT_SINGLE) && (flags & PROMPT_ACCEPT))
|
||||
cmdq_append(c, cmdq_get_callback(status_prompt_accept, c));
|
||||
}
|
||||
@@ -688,6 +687,9 @@ status_prompt_clear(struct client *c)
|
||||
free(c->prompt_last);
|
||||
c->prompt_last = NULL;
|
||||
|
||||
format_free(c->prompt_formats);
|
||||
c->prompt_formats = NULL;
|
||||
|
||||
free(c->prompt_string);
|
||||
c->prompt_string = NULL;
|
||||
|
||||
@@ -707,27 +709,20 @@ status_prompt_clear(struct client *c)
|
||||
void
|
||||
status_prompt_update(struct client *c, const char *msg, const char *input)
|
||||
{
|
||||
struct format_tree *ft;
|
||||
char *tmp;
|
||||
|
||||
ft = format_create(c, NULL, FORMAT_NONE, 0);
|
||||
format_defaults(ft, c, NULL, NULL, NULL);
|
||||
|
||||
tmp = format_expand_time(ft, input);
|
||||
char *tmp;
|
||||
|
||||
free(c->prompt_string);
|
||||
c->prompt_string = format_expand_time(ft, msg);
|
||||
c->prompt_string = xstrdup(msg);
|
||||
|
||||
free(c->prompt_buffer);
|
||||
tmp = format_expand_time(c->prompt_formats, input);
|
||||
c->prompt_buffer = utf8_fromcstr(tmp);
|
||||
c->prompt_index = utf8_strlen(c->prompt_buffer);
|
||||
free(tmp);
|
||||
|
||||
memset(c->prompt_hindex, 0, sizeof c->prompt_hindex);
|
||||
|
||||
c->flags |= CLIENT_REDRAWSTATUS;
|
||||
|
||||
free(tmp);
|
||||
format_free(ft);
|
||||
}
|
||||
|
||||
/* Redraw character. Return 1 if can continue redrawing, 0 otherwise. */
|
||||
@@ -790,7 +785,8 @@ status_prompt_redraw(struct client *c)
|
||||
u_int i, lines, offset, left, start, width, n;
|
||||
u_int pcursor, pwidth, promptline;
|
||||
struct grid_cell gc;
|
||||
struct format_tree *ft;
|
||||
struct format_tree *ft = c->prompt_formats;
|
||||
char *prompt, *tmp;
|
||||
|
||||
if (c->tty.sx == 0 || c->tty.sy == 0)
|
||||
return (0);
|
||||
@@ -811,14 +807,17 @@ status_prompt_redraw(struct client *c)
|
||||
if (promptline > lines - 1)
|
||||
promptline = lines - 1;
|
||||
|
||||
ft = format_create_defaults(NULL, c, NULL, NULL, NULL);
|
||||
if (c->prompt_mode == PROMPT_COMMAND)
|
||||
style_apply(&gc, s->options, "message-command-style", ft);
|
||||
else
|
||||
style_apply(&gc, s->options, "message-style", ft);
|
||||
format_free(ft);
|
||||
|
||||
start = format_width(c->prompt_string);
|
||||
tmp = utf8_tocstr(c->prompt_buffer);
|
||||
format_add(c->prompt_formats, "prompt-input", "%s", tmp);
|
||||
prompt = format_expand_time(c->prompt_formats, c->prompt_string);
|
||||
free (tmp);
|
||||
|
||||
start = format_width(prompt);
|
||||
if (start > c->tty.sx)
|
||||
start = c->tty.sx;
|
||||
|
||||
@@ -828,7 +827,7 @@ status_prompt_redraw(struct client *c)
|
||||
for (offset = 0; offset < c->tty.sx; offset++)
|
||||
screen_write_putc(&ctx, &gc, ' ');
|
||||
screen_write_cursormove(&ctx, 0, promptline, 0);
|
||||
format_draw(&ctx, &gc, start, c->prompt_string, NULL, 0);
|
||||
format_draw(&ctx, &gc, start, prompt, NULL, 0);
|
||||
screen_write_cursormove(&ctx, start, promptline, 0);
|
||||
|
||||
left = c->tty.sx - start;
|
||||
|
10
tmux.1
10
tmux.1
@@ -5835,6 +5835,12 @@ expands to the length of the variable and
|
||||
.Ql w
|
||||
to its width when displayed, for example
|
||||
.Ql #{n:window_name} .
|
||||
.Ql R
|
||||
repeats the first argument by a number of times given by the second argument,
|
||||
so
|
||||
.Ql #{R:a,3}
|
||||
will result in
|
||||
.Ql aaa .
|
||||
.Pp
|
||||
Prefixing a time variable with
|
||||
.Ql t:\&
|
||||
@@ -7283,7 +7289,7 @@ Lock each client individually by running the command specified by the
|
||||
option.
|
||||
.Tg run
|
||||
.It Xo Ic run-shell
|
||||
.Op Fl bC
|
||||
.Op Fl bCE
|
||||
.Op Fl c Ar start-directory
|
||||
.Op Fl d Ar delay
|
||||
.Op Fl t Ar target-pane
|
||||
@@ -7311,6 +7317,8 @@ the command is run in the background.
|
||||
waits for
|
||||
.Ar delay
|
||||
seconds before starting the command.
|
||||
.Fl E
|
||||
redirects the command's stderr to stdout instead of ignoring it.
|
||||
If
|
||||
.Fl c
|
||||
is given, the current working directory is set to
|
||||
|
2
tmux.h
2
tmux.h
@@ -2024,6 +2024,7 @@ struct client {
|
||||
struct event message_timer;
|
||||
|
||||
char *prompt_string;
|
||||
struct format_tree *prompt_formats;
|
||||
struct utf8_data *prompt_buffer;
|
||||
char *prompt_last;
|
||||
size_t prompt_index;
|
||||
@@ -2428,6 +2429,7 @@ typedef void (*job_free_cb) (void *);
|
||||
#define JOB_KEEPWRITE 0x2
|
||||
#define JOB_PTY 0x4
|
||||
#define JOB_DEFAULTSHELL 0x8
|
||||
#define JOB_SHOWSTDERR 0x10
|
||||
struct job *job_run(const char *, int, char **, struct environ *,
|
||||
struct session *, const char *, job_update_cb,
|
||||
job_complete_cb, job_free_cb, void *, int, int, int);
|
||||
|
3
tty.c
3
tty.c
@@ -2756,8 +2756,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
if (changed & GRID_ATTR_ITALICS)
|
||||
tty_set_italics(tty);
|
||||
if (changed & GRID_ATTR_ALL_UNDERSCORE) {
|
||||
if ((changed & GRID_ATTR_UNDERSCORE) ||
|
||||
!tty_term_has(tty->term, TTYC_SMULX))
|
||||
if (changed & GRID_ATTR_UNDERSCORE)
|
||||
tty_putcode(tty, TTYC_SMUL);
|
||||
else if (changed & GRID_ATTR_UNDERSCORE_2)
|
||||
tty_putcode_i(tty, TTYC_SMULX, 2);
|
||||
|
Reference in New Issue
Block a user