If display-popup is used inside a popup, modify that popup. From

m-einfalt at gmx dot de in GitHub issue 4678.
This commit is contained in:
nicm
2025-11-12 13:47:51 +00:00
parent 40600eebfa
commit 3c9e10139f
4 changed files with 157 additions and 63 deletions

View File

@@ -55,8 +55,8 @@ const struct cmd_entry cmd_display_popup_entry = {
.name = "display-popup",
.alias = "popup",
.args = { "Bb:Cc:d:e:Eh:ks:S:t:T:w:x:y:", 0, -1, NULL },
.usage = "[-BCEk] [-b border-lines] [-c target-client] "
.args = { "Bb:Cc:d:e:Eh:kNs:S:t:T:w:x:y:", 0, -1, NULL },
.usage = "[-BCEkN] [-b border-lines] [-c target-client] "
"[-d start-directory] [-e environment] [-h height] "
"[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE
" [-T title] [-w width] [-x position] [-y position] "
@@ -93,7 +93,7 @@ cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause)
}
static int
cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
cmd_display_menu_get_pos(struct client *tc, struct cmdq_item *item,
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
{
struct tty *tty = &tc->tty;
@@ -354,8 +354,8 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
menu_free(menu);
return (CMD_RETURN_NORMAL);
}
if (!cmd_display_menu_get_position(tc, item, args, &px, &py,
menu->width + 4, menu->count + 2)) {
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, menu->width + 4,
menu->count + 2)) {
menu_free(menu);
return (CMD_RETURN_NORMAL);
}
@@ -393,8 +393,10 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
const char *value, *shell, *shellcmd = NULL;
const char *style = args_get(args, 's');
const char *border_style = args_get(args, 'S');
char *cwd, *cause = NULL, **argv = NULL, *title;
int flags = 0, argc = 0;
char *cwd = NULL, *cause = NULL, **argv = NULL;
char *title;
int modify = popup_present(tc);
int flags = -1, argc = 0;
enum box_lines lines = BOX_LINES_DEFAULT;
u_int px, py, w, h, count = args_count(args);
struct args_value *av;
@@ -406,12 +408,14 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
server_client_clear_overlay(tc);
return (CMD_RETURN_NORMAL);
}
if (tc->overlay_draw != NULL)
if (!modify && tc->overlay_draw != NULL)
return (CMD_RETURN_NORMAL);
if (!modify) {
h = tty->sy / 2;
if (args_has(args, 'h')) {
h = args_percentage(args, 'h', 1, tty->sy, tty->sy, &cause);
h = args_percentage(args, 'h', 1, tty->sy, tty->sy,
&cause);
if (cause != NULL) {
cmdq_error(item, "height %s", cause);
free(cause);
@@ -421,7 +425,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
w = tty->sx / 2;
if (args_has(args, 'w')) {
w = args_percentage(args, 'w', 1, tty->sx, tty->sx, &cause);
w = args_percentage(args, 'w', 1, tty->sx, tty->sx,
&cause);
if (cause != NULL) {
cmdq_error(item, "width %s", cause);
free(cause);
@@ -433,31 +438,18 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
w = tty->sx;
if (h > tty->sy)
h = tty->sy;
if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h))
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, w, h))
return (CMD_RETURN_NORMAL);
value = args_get(args, 'b');
if (args_has(args, 'B'))
lines = BOX_LINES_NONE;
else if (value != NULL) {
oe = options_get(o, "popup-border-lines");
lines = options_find_choice(options_table_entry(oe), value,
&cause);
if (cause != NULL) {
cmdq_error(item, "popup-border-lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
value = args_get(args, 'd');
if (value != NULL)
cwd = format_single_from_target(item, value);
else
cwd = xstrdup(server_client_get_cwd(tc, s));
if (count == 0)
shellcmd = options_get_string(s->options, "default-command");
else if (count == 1)
if (count == 0) {
shellcmd = options_get_string(s->options,
"default-command");
} else if (count == 1)
shellcmd = args_string(args, 0);
if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) {
shellcmd = NULL;
@@ -476,17 +468,49 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
av = args_next_value(av);
}
}
}
value = args_get(args, 'b');
if (args_has(args, 'B'))
lines = BOX_LINES_NONE;
else if (value != NULL) {
oe = options_get(o, "popup-border-lines");
lines = options_find_choice(options_table_entry(oe), value,
&cause);
if (cause != NULL) {
cmdq_error(item, "popup-border-lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
if (args_has(args, 'T'))
title = format_single_from_target(item, args_get(args, 'T'));
else
title = xstrdup("");
if (args_has(args, 'E') > 1)
if (args_has(args, 'N') || !modify)
flags = 0;
if (args_has(args, 'E') > 1) {
if (flags == -1)
flags = 0;
flags |= POPUP_CLOSEEXITZERO;
else if (args_has(args, 'E'))
} else if (args_has(args, 'E')) {
if (flags == -1)
flags = 0;
flags |= POPUP_CLOSEEXIT;
if (args_has(args, 'k'))
}
if (args_has(args, 'k')) {
if (flags == -1)
flags = 0;
flags |= POPUP_CLOSEANYKEY;
}
if (modify) {
popup_modify(tc, title, style, border_style, lines, flags);
free(title);
return (CMD_RETURN_NORMAL);
}
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) {
cmd_free_argv(argc, argv);

50
popup.c
View File

@@ -640,6 +640,56 @@ popup_job_complete_cb(struct job *job)
server_client_clear_overlay(pd->c);
}
int
popup_present(struct client *c)
{
return (c->overlay_draw == popup_draw_cb);
}
int
popup_modify(struct client *c, const char *title, const char *style,
const char *border_style, enum box_lines lines, int flags)
{
struct popup_data *pd = c->overlay_data;
struct style sytmp;
if (title != NULL) {
if (pd->title != NULL)
free(pd->title);
pd->title = xstrdup(title);
}
if (border_style != NULL) {
style_set(&sytmp, &pd->border_cell);
if (style_parse(&sytmp, &pd->border_cell, border_style) == 0) {
pd->border_cell.fg = sytmp.gc.fg;
pd->border_cell.bg = sytmp.gc.bg;
}
}
if (style != NULL) {
style_set(&sytmp, &pd->defaults);
if (style_parse(&sytmp, &pd->defaults, style) == 0) {
pd->defaults.fg = sytmp.gc.fg;
pd->defaults.bg = sytmp.gc.bg;
}
}
if (lines != BOX_LINES_DEFAULT) {
if (lines == BOX_LINES_NONE && pd->border_lines != lines) {
screen_resize(&pd->s, pd->sx, pd->sy, 1);
job_resize(pd->job, pd->sx, pd->sy);
} else if (pd->border_lines == BOX_LINES_NONE && pd->border_lines != lines) {
screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 1);
job_resize(pd->job, pd->sx - 2, pd->sy - 2);
}
pd->border_lines = lines;
tty_resize(&c->tty);
}
if (flags != -1)
pd->flags = flags;
server_redraw_client(c);
return (0);
}
int
popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
u_int py, u_int sx, u_int sy, struct environ *env, const char *shellcmd,

19
tmux.1
View File

@@ -6999,7 +6999,7 @@ forwards any input read from stdin to the empty pane given by
.Ar target-pane .
.Tg popup
.It Xo Ic display-popup
.Op Fl BCEk
.Op Fl BCEkN
.Op Fl b Ar border-lines
.Op Fl c Ar target-client
.Op Fl d Ar start-directory
@@ -7023,6 +7023,20 @@ when omitted) on
.Ar target-client .
A popup is a rectangular box drawn over the top of any panes.
Panes are not updated while a popup is present.
If the command is run inside an existing popup, that popup is modified.
Only the
.Fl b ,
.Fl B ,
.Fl C ,
.Fl E ,
.Fl EE ,
.Fl K ,
.Fl N ,
.Fl s ,
and
.Fl S
options are accepted in this case;
all others are ignored.
.Pp
.Fl E
closes the popup automatically when
@@ -7086,6 +7100,9 @@ is a format for the popup title (see
The
.Fl C
flag closes any popup on the client.
.Pp
.Fl N
disables any previously specified -E, -EE, or -k option.
.Tg showphist
.It Xo Ic show-prompt-history
.Op Fl T Ar prompt-type

3
tmux.h
View File

@@ -3561,6 +3561,9 @@ int popup_display(int, enum box_lines, struct cmdq_item *, u_int,
popup_close_cb, void *);
int popup_editor(struct client *, const char *, size_t,
popup_finish_edit_cb, void *);
int popup_present(struct client *);
int popup_modify(struct client *, const char *, const char *,
const char *, enum box_lines, int);
/* style.c */
int style_parse(struct style *,const struct grid_cell *,