diff --git a/cmd-display-menu.c b/cmd-display-menu.c index bd5012f2..894a2f68 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -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,36 +408,68 @@ 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); - h = tty->sy / 2; - if (args_has(args, 'h')) { - h = args_percentage(args, 'h', 1, tty->sy, tty->sy, &cause); - if (cause != NULL) { - cmdq_error(item, "height %s", cause); - free(cause); - return (CMD_RETURN_ERROR); + if (!modify) { + h = tty->sy / 2; + if (args_has(args, 'h')) { + h = args_percentage(args, 'h', 1, tty->sy, tty->sy, + &cause); + if (cause != NULL) { + cmdq_error(item, "height %s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + } + + w = tty->sx / 2; + if (args_has(args, 'w')) { + w = args_percentage(args, 'w', 1, tty->sx, tty->sx, + &cause); + if (cause != NULL) { + cmdq_error(item, "width %s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + } + + if (w > tty->sx) + w = tty->sx; + if (h > tty->sy) + h = tty->sy; + if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, w, h)) + return (CMD_RETURN_NORMAL); + + 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) + shellcmd = args_string(args, 0); + if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) { + shellcmd = NULL; + shell = options_get_string(s->options, "default-shell"); + if (!checkshell(shell)) + shell = _PATH_BSHELL; + cmd_append_argv(&argc, &argv, shell); + } else + args_to_vector(args, &argc, &argv); + + if (args_has(args, 'e') >= 1) { + env = environ_create(); + av = args_first_value(args, 'e'); + while (av != NULL) { + environ_put(env, av->string, 0); + av = args_next_value(av); + } } } - w = tty->sx / 2; - if (args_has(args, 'w')) { - w = args_percentage(args, 'w', 1, tty->sx, tty->sx, &cause); - if (cause != NULL) { - cmdq_error(item, "width %s", cause); - free(cause); - return (CMD_RETURN_ERROR); - } - } - - if (w > tty->sx) - w = tty->sx; - if (h > tty->sy) - h = tty->sy; - if (!cmd_display_menu_get_position(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; @@ -450,43 +484,33 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) } } - 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) - shellcmd = args_string(args, 0); - if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) { - shellcmd = NULL; - shell = options_get_string(s->options, "default-shell"); - if (!checkshell(shell)) - shell = _PATH_BSHELL; - cmd_append_argv(&argc, &argv, shell); - } else - args_to_vector(args, &argc, &argv); - - if (args_has(args, 'e') >= 1) { - env = environ_create(); - av = args_first_value(args, 'e'); - while (av != NULL) { - environ_put(env, av->string, 0); - av = args_next_value(av); - } - } - 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); diff --git a/popup.c b/popup.c index 619a32ce..12cd7362 100644 --- a/popup.c +++ b/popup.c @@ -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, diff --git a/tmux.1 b/tmux.1 index e4c55d33..9a602927 100644 --- a/tmux.1 +++ b/tmux.1 @@ -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 diff --git a/tmux.h b/tmux.h index 356d1157..736d0f55 100644 --- a/tmux.h +++ b/tmux.h @@ -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 *,