Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2025-05-12 14:01:10 +01:00
7 changed files with 93 additions and 52 deletions

View File

@@ -44,8 +44,8 @@ const struct cmd_entry cmd_run_shell_entry = {
.name = "run-shell", .name = "run-shell",
.alias = "run", .alias = "run",
.args = { "bd:Ct:c:", 0, 1, cmd_run_shell_args_parse }, .args = { "bd:Ct:Es:c:", 0, 1, cmd_run_shell_args_parse },
.usage = "[-bC] [-c start-directory] [-d delay] " CMD_TARGET_PANE_USAGE .usage = "[-bCE] [-c start-directory] [-d delay] " CMD_TARGET_PANE_USAGE
" [shell-command]", " [shell-command]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL }, .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@@ -158,6 +158,9 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
else else
cdata->cwd = xstrdup(server_client_get_cwd(c, s)); cdata->cwd = xstrdup(server_client_get_cwd(c, s));
if (args_has(args, 'E'))
cdata->flags |= JOB_SHOWSTDERR;
cdata->s = s; cdata->s = s;
if (s != NULL) if (s != NULL)
session_add_ref(s, __func__); session_add_ref(s, __func__);

View File

@@ -106,6 +106,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
#define FORMAT_CLIENTS 0x40000 #define FORMAT_CLIENTS 0x40000
#define FORMAT_NOT 0x80000 #define FORMAT_NOT 0x80000
#define FORMAT_NOT_NOT 0x100000 #define FORMAT_NOT_NOT 0x100000
#define FORMAT_REPEAT 0x200000
/* Limit on recursion. */ /* Limit on recursion. */
#define FORMAT_LOOP_LIMIT 100 #define FORMAT_LOOP_LIMIT 100
@@ -3992,7 +3993,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
/* /*
* Modifiers are a ; separated list of the forms: * 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
* =/a/ * =/a/
@@ -4031,7 +4032,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
} }
/* Now try single character with arguments. */ /* Now try single character with arguments. */
if (strchr("mCNst=peq", cp[0]) == NULL) if (strchr("mCNst=pReq", cp[0]) == NULL)
break; break;
c = cp[0]; 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 *list, *cmp = NULL, *search = NULL;
struct format_modifier **sub = NULL, *mexp = NULL, *fm; struct format_modifier **sub = NULL, *mexp = NULL, *fm;
struct format_modifier *bool_op_n = NULL; 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; struct format_expand_state next;
/* Make a copy of the key. */ /* 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': case 'L':
modifiers |= FORMAT_CLIENTS; modifiers |= FORMAT_CLIENTS;
break; break;
case 'R':
modifiers |= FORMAT_REPEAT;
break;
} }
} else if (fm->size == 2) { } else if (fm->size == 2) {
if (strcmp(fm->modifier, "||") == 0 || if (strcmp(fm->modifier, "||") == 0 ||
@@ -4790,6 +4794,25 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
value = format_search(search, wp, new); value = format_search(search, wp, new);
} }
free(new); free(new);
} 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) { } else if (modifiers & FORMAT_NOT) {
value = format_bool_op_1(es, copy, 1); value = format_bool_op_1(es, copy, 1);
} else if (modifiers & FORMAT_NOT_NOT) { } else if (modifiers & FORMAT_NOT_NOT) {

17
job.c
View File

@@ -77,7 +77,7 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e,
struct job *job; struct job *job;
struct environ *env; struct environ *env;
pid_t pid; pid_t pid;
int nullfd, out[2], master; int nullfd, out[2], master, do_close = 1;
const char *home, *shell; const char *home, *shell;
sigset_t set, oldset; sigset_t set, oldset;
struct winsize ws; struct winsize ws;
@@ -150,12 +150,15 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e,
if (~flags & JOB_PTY) { if (~flags & JOB_PTY) {
if (dup2(out[1], STDIN_FILENO) == -1) if (dup2(out[1], STDIN_FILENO) == -1)
fatal("dup2 failed"); fatal("dup2 failed");
do_close = do_close && out[1] != STDIN_FILENO;
if (dup2(out[1], STDOUT_FILENO) == -1) if (dup2(out[1], STDOUT_FILENO) == -1)
fatal("dup2 failed"); fatal("dup2 failed");
if (out[1] != STDIN_FILENO && out[1] != STDOUT_FILENO) do_close = do_close && out[1] != STDOUT_FILENO;
close(out[1]); if (flags & JOB_SHOWSTDERR) {
close(out[0]); 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); nullfd = open(_PATH_DEVNULL, O_RDWR);
if (nullfd == -1) if (nullfd == -1)
fatal("open failed"); fatal("open failed");
@@ -164,6 +167,10 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e,
if (nullfd != STDERR_FILENO) if (nullfd != STDERR_FILENO)
close(nullfd); close(nullfd);
} }
if (do_close)
close(out[1]);
close(out[0]);
}
closefrom(STDERR_FILENO + 1); closefrom(STDERR_FILENO + 1);
if (cmd != NULL) { if (cmd != NULL) {

View File

@@ -631,17 +631,18 @@ status_prompt_set(struct client *c, struct cmd_find_state *fs,
if (input == NULL) if (input == NULL)
input = ""; input = "";
if (flags & PROMPT_NOFORMAT)
tmp = xstrdup(input);
else
tmp = format_expand_time(ft, input);
status_message_clear(c); status_message_clear(c);
status_prompt_clear(c); status_prompt_clear(c);
status_push_screen(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) { if (flags & PROMPT_INCREMENTAL) {
c->prompt_last = xstrdup(tmp); c->prompt_last = xstrdup(tmp);
c->prompt_buffer = utf8_fromcstr(""); 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_buffer = utf8_fromcstr(tmp);
} }
c->prompt_index = utf8_strlen(c->prompt_buffer); c->prompt_index = utf8_strlen(c->prompt_buffer);
free(tmp);
c->prompt_inputcb = inputcb; c->prompt_inputcb = inputcb;
c->prompt_freecb = freecb; c->prompt_freecb = freecb;
@@ -668,9 +670,6 @@ status_prompt_set(struct client *c, struct cmd_find_state *fs,
if (flags & PROMPT_INCREMENTAL) if (flags & PROMPT_INCREMENTAL)
c->prompt_inputcb(c, c->prompt_data, "=", 0); c->prompt_inputcb(c, c->prompt_data, "=", 0);
free(tmp);
format_free(ft);
if ((flags & PROMPT_SINGLE) && (flags & PROMPT_ACCEPT)) if ((flags & PROMPT_SINGLE) && (flags & PROMPT_ACCEPT))
cmdq_append(c, cmdq_get_callback(status_prompt_accept, c)); cmdq_append(c, cmdq_get_callback(status_prompt_accept, c));
} }
@@ -688,6 +687,9 @@ status_prompt_clear(struct client *c)
free(c->prompt_last); free(c->prompt_last);
c->prompt_last = NULL; c->prompt_last = NULL;
format_free(c->prompt_formats);
c->prompt_formats = NULL;
free(c->prompt_string); free(c->prompt_string);
c->prompt_string = NULL; c->prompt_string = NULL;
@@ -707,27 +709,20 @@ status_prompt_clear(struct client *c)
void void
status_prompt_update(struct client *c, const char *msg, const char *input) status_prompt_update(struct client *c, const char *msg, const char *input)
{ {
struct format_tree *ft;
char *tmp; char *tmp;
ft = format_create(c, NULL, FORMAT_NONE, 0);
format_defaults(ft, c, NULL, NULL, NULL);
tmp = format_expand_time(ft, input);
free(c->prompt_string); free(c->prompt_string);
c->prompt_string = format_expand_time(ft, msg); c->prompt_string = xstrdup(msg);
free(c->prompt_buffer); free(c->prompt_buffer);
tmp = format_expand_time(c->prompt_formats, input);
c->prompt_buffer = utf8_fromcstr(tmp); c->prompt_buffer = utf8_fromcstr(tmp);
c->prompt_index = utf8_strlen(c->prompt_buffer); c->prompt_index = utf8_strlen(c->prompt_buffer);
free(tmp);
memset(c->prompt_hindex, 0, sizeof c->prompt_hindex); memset(c->prompt_hindex, 0, sizeof c->prompt_hindex);
c->flags |= CLIENT_REDRAWSTATUS; c->flags |= CLIENT_REDRAWSTATUS;
free(tmp);
format_free(ft);
} }
/* Redraw character. Return 1 if can continue redrawing, 0 otherwise. */ /* 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 i, lines, offset, left, start, width, n;
u_int pcursor, pwidth, promptline; u_int pcursor, pwidth, promptline;
struct grid_cell gc; 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) if (c->tty.sx == 0 || c->tty.sy == 0)
return (0); return (0);
@@ -811,14 +807,17 @@ status_prompt_redraw(struct client *c)
if (promptline > lines - 1) if (promptline > lines - 1)
promptline = lines - 1; promptline = lines - 1;
ft = format_create_defaults(NULL, c, NULL, NULL, NULL);
if (c->prompt_mode == PROMPT_COMMAND) if (c->prompt_mode == PROMPT_COMMAND)
style_apply(&gc, s->options, "message-command-style", ft); style_apply(&gc, s->options, "message-command-style", ft);
else else
style_apply(&gc, s->options, "message-style", ft); 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) if (start > c->tty.sx)
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++) for (offset = 0; offset < c->tty.sx; offset++)
screen_write_putc(&ctx, &gc, ' '); screen_write_putc(&ctx, &gc, ' ');
screen_write_cursormove(&ctx, 0, promptline, 0); 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); screen_write_cursormove(&ctx, start, promptline, 0);
left = c->tty.sx - start; left = c->tty.sx - start;

10
tmux.1
View File

@@ -5835,6 +5835,12 @@ expands to the length of the variable and
.Ql w .Ql w
to its width when displayed, for example to its width when displayed, for example
.Ql #{n:window_name} . .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 .Pp
Prefixing a time variable with Prefixing a time variable with
.Ql t:\& .Ql t:\&
@@ -7283,7 +7289,7 @@ Lock each client individually by running the command specified by the
option. option.
.Tg run .Tg run
.It Xo Ic run-shell .It Xo Ic run-shell
.Op Fl bC .Op Fl bCE
.Op Fl c Ar start-directory .Op Fl c Ar start-directory
.Op Fl d Ar delay .Op Fl d Ar delay
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
@@ -7311,6 +7317,8 @@ the command is run in the background.
waits for waits for
.Ar delay .Ar delay
seconds before starting the command. seconds before starting the command.
.Fl E
redirects the command's stderr to stdout instead of ignoring it.
If If
.Fl c .Fl c
is given, the current working directory is set to is given, the current working directory is set to

2
tmux.h
View File

@@ -2024,6 +2024,7 @@ struct client {
struct event message_timer; struct event message_timer;
char *prompt_string; char *prompt_string;
struct format_tree *prompt_formats;
struct utf8_data *prompt_buffer; struct utf8_data *prompt_buffer;
char *prompt_last; char *prompt_last;
size_t prompt_index; size_t prompt_index;
@@ -2428,6 +2429,7 @@ typedef void (*job_free_cb) (void *);
#define JOB_KEEPWRITE 0x2 #define JOB_KEEPWRITE 0x2
#define JOB_PTY 0x4 #define JOB_PTY 0x4
#define JOB_DEFAULTSHELL 0x8 #define JOB_DEFAULTSHELL 0x8
#define JOB_SHOWSTDERR 0x10
struct job *job_run(const char *, int, char **, struct environ *, struct job *job_run(const char *, int, char **, struct environ *,
struct session *, const char *, job_update_cb, struct session *, const char *, job_update_cb,
job_complete_cb, job_free_cb, void *, int, int, int); job_complete_cb, job_free_cb, void *, int, int, int);

3
tty.c
View File

@@ -2756,8 +2756,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
if (changed & GRID_ATTR_ITALICS) if (changed & GRID_ATTR_ITALICS)
tty_set_italics(tty); tty_set_italics(tty);
if (changed & GRID_ATTR_ALL_UNDERSCORE) { if (changed & GRID_ATTR_ALL_UNDERSCORE) {
if ((changed & GRID_ATTR_UNDERSCORE) || if (changed & GRID_ATTR_UNDERSCORE)
!tty_term_has(tty->term, TTYC_SMULX))
tty_putcode(tty, TTYC_SMUL); tty_putcode(tty, TTYC_SMUL);
else if (changed & GRID_ATTR_UNDERSCORE_2) else if (changed & GRID_ATTR_UNDERSCORE_2)
tty_putcode_i(tty, TTYC_SMULX, 2); tty_putcode_i(tty, TTYC_SMULX, 2);