From: nicm Date: Tue, 8 Aug 2023 08:08:47 +0000 (+0000) Subject: Add options and flags for menu styles similar to those existing for X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=17d7ce67d59ff14139f556e0c13a9154ce22d22f;p=openbsd Add options and flags for menu styles similar to those existing for popups, from Alexis Hildebrandt. GitHub issue 3650. --- diff --git a/usr.bin/tmux/cmd-display-menu.c b/usr.bin/tmux/cmd-display-menu.c index 712524c9a55..d616d0c4314 100644 --- a/usr.bin/tmux/cmd-display-menu.c +++ b/usr.bin/tmux/cmd-display-menu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-display-menu.c,v 1.40 2023/08/07 10:52:00 nicm Exp $ */ +/* $OpenBSD: cmd-display-menu.c,v 1.41 2023/08/08 08:08:47 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott @@ -39,10 +39,11 @@ const struct cmd_entry cmd_display_menu_entry = { .name = "display-menu", .alias = "menu", - .args = { "c:t:S:OT:x:y:", 1, -1, cmd_display_menu_args_parse }, - .usage = "[-O] [-c target-client] [-S starting-choice] " - CMD_TARGET_PANE_USAGE " [-T title] [-x position] " - "[-y position] name key command ...", + .args = { "b:c:C:t:s:S:OT:x:y:", 1, -1, cmd_display_menu_args_parse }, + .usage = "[-O] [-b border-lines] [-c target-client] " + "[-C starting-choice] [-s style] [-S border-style] " + CMD_TARGET_PANE_USAGE "[-T title] [-x position] [-y position] " + "name key command ...", .target = { 't', CMD_FIND_PANE, 0 }, @@ -289,19 +290,25 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) struct client *tc = cmdq_get_target_client(item); struct menu *menu = NULL; struct menu_item menu_item; - const char *key, *name; + const char *key, *name, *value; + const char *style = args_get(args, 's'); + const char *border_style = args_get(args, 'S'); + enum box_lines lines = BOX_LINES_DEFAULT; char *title, *cause; int flags = 0, starting_choice = 0; u_int px, py, i, count = args_count(args); + struct options *o = target->s->curw->window->options; + struct options_entry *oe; + if (tc->overlay_draw != NULL) return (CMD_RETURN_NORMAL); - if (args_has(args, 'S')) { - if (strcmp(args_get(args, 'S'), "-") == 0) + if (args_has(args, 'C')) { + if (strcmp(args_get(args, 'C'), "-") == 0) starting_choice = -1; else { - starting_choice = args_strtonum(args, 'S', 0, UINT_MAX, + starting_choice = args_strtonum(args, 'C', 0, UINT_MAX, &cause); if (cause != NULL) { cmdq_error(item, "starting choice %s", cause); @@ -352,12 +359,24 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } + value = args_get(args, 'b'); + if (value != NULL) { + oe = options_get(o, "menu-border-lines"); + lines = options_find_choice(options_table_entry(oe), value, + &cause); + if (lines == -1) { + cmdq_error(item, "menu-border-lines %s", cause); + free(cause); + return (CMD_RETURN_ERROR); + } + } + if (args_has(args, 'O')) flags |= MENU_STAYOPEN; if (!event->m.valid) flags |= MENU_NOMOUSE; - if (menu_display(menu, flags, starting_choice, item, px, py, tc, target, - NULL, NULL) != 0) + if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines, + style, border_style, target, NULL, NULL) != 0) return (CMD_RETURN_NORMAL); return (CMD_RETURN_WAIT); } diff --git a/usr.bin/tmux/menu.c b/usr.bin/tmux/menu.c index 4c72a49edde..4b0622020e7 100644 --- a/usr.bin/tmux/menu.c +++ b/usr.bin/tmux/menu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: menu.c,v 1.50 2023/08/08 07:41:04 nicm Exp $ */ +/* $OpenBSD: menu.c,v 1.51 2023/08/08 08:08:47 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott @@ -27,6 +27,10 @@ struct menu_data { struct cmdq_item *item; int flags; + struct grid_cell style; + struct grid_cell border_style; + enum box_lines border_lines; + struct cmd_find_state fs; struct screen s; @@ -199,12 +203,17 @@ menu_draw_cb(struct client *c, void *data, u_int i, px = md->px, py = md->py; struct grid_cell gc; - style_apply(&gc, c->session->curw->window->options, "mode-style", NULL); - screen_write_start(&ctx, s); screen_write_clearscreen(&ctx, 8); - screen_write_menu(&ctx, menu, md->choice, BOX_LINES_DEFAULT, - &grid_default_cell, &grid_default_cell, &gc); + + if (md->border_lines != BOX_LINES_NONE) { + screen_write_box(&ctx, menu->width + 4, menu->count + 2, + md->border_lines, &md->border_style, menu->title); + } + style_apply(&gc, c->session->curw->window->options, "mode-style", NULL); + + screen_write_menu(&ctx, menu, md->choice, md->border_lines, + &md->style, &md->border_style, &gc); screen_write_stop(&ctx); for (i = 0; i < screen_size_y(&md->s); i++) { @@ -432,11 +441,14 @@ chosen: struct menu_data * menu_prepare(struct menu *menu, int flags, int starting_choice, struct cmdq_item *item, u_int px, u_int py, struct client *c, + enum box_lines lines, const char *style, const char *border_style, struct cmd_find_state *fs, menu_choice_cb cb, void *data) { struct menu_data *md; int choice; const char *name; + struct style sytmp; + struct options *o = c->session->curw->window->options; if (c->tty.sx < menu->width + 4 || c->tty.sy < menu->count + 2) return (NULL); @@ -445,9 +457,35 @@ menu_prepare(struct menu *menu, int flags, int starting_choice, if (py + menu->count + 2 > c->tty.sy) py = c->tty.sy - menu->count - 2; + if (lines == BOX_LINES_DEFAULT) + lines = options_get_number(o, "menu-border-lines"); + md = xcalloc(1, sizeof *md); md->item = item; md->flags = flags; + md->border_lines = lines; + + memcpy(&md->style, &grid_default_cell, sizeof md->style); + style_apply(&md->style, o, "menu-style", NULL); + if (style != NULL) { + style_set(&sytmp, &grid_default_cell); + if (style_parse(&sytmp, &md->style, style) == 0) { + md->style.fg = sytmp.gc.fg; + md->style.bg = sytmp.gc.bg; + } + } + md->style.attr = 0; + + memcpy(&md->border_style, &grid_default_cell, sizeof md->border_style); + style_apply(&md->border_style, o, "menu-border-style", NULL); + if (border_style != NULL) { + style_set(&sytmp, &grid_default_cell); + if (style_parse(&sytmp, &md->border_style, border_style) == 0) { + md->border_style.fg = sytmp.gc.fg; + md->border_style.bg = sytmp.gc.bg; + } + } + md->border_style.attr = 0; if (fs != NULL) cmd_find_copy_state(&md->fs, fs); @@ -501,12 +539,13 @@ menu_prepare(struct menu *menu, int flags, int starting_choice, int menu_display(struct menu *menu, int flags, int starting_choice, struct cmdq_item *item, u_int px, u_int py, struct client *c, + enum box_lines lines, const char *style, const char *border_style, struct cmd_find_state *fs, menu_choice_cb cb, void *data) { struct menu_data *md; - md = menu_prepare(menu, flags, starting_choice, item, px, py, c, fs, cb, - data); + md = menu_prepare(menu, flags, starting_choice, item, px, py, c, lines, + style, border_style, fs, cb, data); if (md == NULL) return (-1); server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb, diff --git a/usr.bin/tmux/mode-tree.c b/usr.bin/tmux/mode-tree.c index b90980f9f7a..08a5c294f5f 100644 --- a/usr.bin/tmux/mode-tree.c +++ b/usr.bin/tmux/mode-tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mode-tree.c,v 1.63 2023/01/20 21:36:00 nicm Exp $ */ +/* $OpenBSD: mode-tree.c,v 1.64 2023/08/08 08:08:47 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -962,8 +962,8 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x, x -= (menu->width + 4) / 2; else x = 0; - if (menu_display(menu, 0, 0, NULL, x, y, c, NULL, - mode_tree_menu_callback, mtm) != 0) + if (menu_display(menu, 0, 0, NULL, x, y, c, BOX_LINES_DEFAULT, NULL, + NULL, NULL, mode_tree_menu_callback, mtm) != 0) menu_free(menu); } diff --git a/usr.bin/tmux/options-table.c b/usr.bin/tmux/options-table.c index d7757f7f691..211257f218a 100644 --- a/usr.bin/tmux/options-table.c +++ b/usr.bin/tmux/options-table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options-table.c,v 1.165 2022/09/09 11:02:23 nicm Exp $ */ +/* $OpenBSD: options-table.c,v 1.166 2023/08/08 08:08:47 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -327,6 +327,33 @@ const struct options_table_entry options_table[] = { "Empty does not write a history file." }, + { .name = "menu-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .flags = OPTIONS_TABLE_IS_STYLE, + .default_str = "default", + .separator = ",", + .text = "Default style of menu." + }, + + { .name = "menu-border-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .default_str = "default", + .flags = OPTIONS_TABLE_IS_STYLE, + .separator = ",", + .text = "Default style of menu borders." + }, + + { .name = "menu-border-lines", + .type = OPTIONS_TABLE_CHOICE, + .scope = OPTIONS_TABLE_WINDOW, + .choices = options_table_popup_border_lines_list, + .default_num = BOX_LINES_SINGLE, + .text = "Type of characters used to draw menu border lines. Some of " + "these are only supported on terminals with UTF-8 support." + }, + { .name = "message-limit", .type = OPTIONS_TABLE_NUMBER, .scope = OPTIONS_TABLE_SERVER, diff --git a/usr.bin/tmux/popup.c b/usr.bin/tmux/popup.c index b172f40267b..35adb1b3ccb 100644 --- a/usr.bin/tmux/popup.c +++ b/usr.bin/tmux/popup.c @@ -1,4 +1,4 @@ -/* $OpenBSD: popup.c,v 1.50 2023/06/21 06:28:18 nicm Exp $ */ +/* $OpenBSD: popup.c,v 1.51 2023/08/08 08:08:47 nicm Exp $ */ /* * Copyright (c) 2020 Nicholas Marriott @@ -575,8 +575,8 @@ menu: x = m->x - (pd->menu->width + 4) / 2; else x = 0; - pd->md = menu_prepare(pd->menu, 0, 0, NULL, x, m->y, c, NULL, - popup_menu_done, pd); + pd->md = menu_prepare(pd->menu, 0, 0, NULL, x, m->y, c, + BOX_LINES_DEFAULT, NULL, NULL, NULL, popup_menu_done, pd); c->flags |= CLIENT_REDRAWOVERLAY; out: diff --git a/usr.bin/tmux/screen-write.c b/usr.bin/tmux/screen-write.c index 9f57565a88c..8d98e0e9967 100644 --- a/usr.bin/tmux/screen-write.c +++ b/usr.bin/tmux/screen-write.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen-write.c,v 1.216 2023/08/08 07:41:04 nicm Exp $ */ +/* $OpenBSD: screen-write.c,v 1.217 2023/08/08 08:08:47 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -713,15 +713,16 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, int choice, name = menu->items[i].name; if (name == NULL) { screen_write_cursormove(ctx, cx, cy + 1 + i, 0); - screen_write_hline(ctx, width + 4, 1, 1, lines, gc); + screen_write_hline(ctx, width + 4, 1, 1, lines, + border_gc); continue; } if (choice >= 0 && i == (u_int)choice && *name != '-') gc = choice_gc; - screen_write_cursormove(ctx, cx + 2, cy + 1 + i, 0); - for (j = 0; j < width; j++) + screen_write_cursormove(ctx, cx + 1, cy + 1 + i, 0); + for (j = 0; j < width + 2; j++) screen_write_putc(ctx, gc, ' '); screen_write_cursormove(ctx, cx + 2, cy + 1 + i, 0); diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c index d562ea4dd9d..ce8c9f70506 100644 --- a/usr.bin/tmux/status.c +++ b/usr.bin/tmux/status.c @@ -1,4 +1,4 @@ -/* $OpenBSD: status.c,v 1.238 2023/04/17 18:22:24 nicm Exp $ */ +/* $OpenBSD: status.c,v 1.239 2023/08/08 08:08:47 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1764,8 +1764,9 @@ status_prompt_complete_list_menu(struct client *c, char **list, u_int size, else offset = 0; - if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, 0, NULL, offset, - py, c, NULL, status_prompt_menu_callback, spm) != 0) { + if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, 0, NULL, offset, py, c, + BOX_LINES_DEFAULT, NULL, NULL, NULL, status_prompt_menu_callback, + spm) != 0) { menu_free(menu); free(spm); return (0); @@ -1857,8 +1858,9 @@ status_prompt_complete_window_menu(struct client *c, struct session *s, else offset = 0; - if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, 0, NULL, offset, - py, c, NULL, status_prompt_menu_callback, spm) != 0) { + if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, 0, NULL, offset, py, c, + BOX_LINES_DEFAULT, NULL, NULL, NULL, status_prompt_menu_callback, + spm) != 0) { menu_free(menu); free(spm); return (NULL); diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index cf0f9fdb167..35c6a1187aa 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.924 2023/07/11 16:09:09 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.925 2023/08/08 08:08:47 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: July 11 2023 $ +.Dd $Mdocdate: August 8 2023 $ .Dt TMUX 1 .Os .Sh NAME @@ -4073,6 +4073,26 @@ The default is to run .Xr lock 1 with .Fl np . +.It Ic menu-style Ar style +Set the menu style. +See the +.Sx STYLES +section on how to specify +.Ar style . +Attributes are ignored. +.It Ic menu-border-style Ar style +Set the menu border style. +See the +.Sx STYLES +section on how to specify +.Ar style . +Attributes are ignored. +.It Ic menu-border-lines Ar type +Set the type of characters used for drawing menu borders. +See +.Ic popup-border-lines +for possible values for +.Ar type . .It Ic message-command-style Ar style Set status line message command style. This is used for the command prompt with @@ -4540,20 +4560,18 @@ Attributes are ignored. .Pp .It Ic popup-style Ar style Set the popup style. -For how to specify -.Ar style , -see the +See the .Sx STYLES -section. +section on how to specify +.Ar style . Attributes are ignored. .Pp .It Ic popup-border-style Ar style Set the popup border style. -For how to specify -.Ar style , -see the +See the .Sx STYLES -section. +section on how to specify +.Ar style . Attributes are ignored. .Pp .It Ic popup-border-lines Ar type @@ -6028,9 +6046,12 @@ the default is .Tg menu .It Xo Ic display-menu .Op Fl O +.Op Fl b Ar border-lines .Op Fl c Ar target-client +.Op Fl s Ar style +.Op Fl S Ar border-style .Op Fl t Ar target-pane -.Op Fl S Ar starting-choice +.Op Fl C Ar starting-choice .Op Fl T Ar title .Op Fl x Ar position .Op Fl y Ar position @@ -6057,10 +6078,24 @@ may not be chosen. The name may be empty for a separator line, in which case both the key and command should be omitted. .Pp +.Fl b +sets the type of characters used for drawing menu borders. +See +.Ic popup-border-lines +for possible values for +.Ar border-lines . +.Pp +.Fl s +sets the style for the menu and +.Fl S +sets the style for the menu border (see +.Sx STYLES ) . +.Pp .Fl T is a format for the menu title (see .Sx FORMATS ) . -.Fl S +.Pp +.Fl C sets the menu item selected by default, if the menu is not bound to a mouse key binding. .Pp @@ -6175,8 +6210,8 @@ forwards any input read from stdin to the empty pane given by .Op Fl d Ar start-directory .Op Fl e Ar environment .Op Fl h Ar height -.Op Fl s Ar style -.Op Fl S Ar border-style +.Op Fl s Ar border-style +.Op Fl S Ar style .Op Fl t Ar target-pane .Op Fl T Ar title .Op Fl w Ar width @@ -6219,7 +6254,7 @@ If omitted, half of the terminal size is used. does not surround the popup by a border. .Pp .Fl b -sets the type of border line for the popup. +sets the type of characters used for drawing popup borders. When .Fl B is specified, the @@ -6233,12 +6268,8 @@ for possible values for .Fl s sets the style for the popup and .Fl S -sets the style for the popup border. -For how to specify -.Ar style , -see the -.Sx STYLES -section. +sets the style for the popup border (see +.Sx STYLES ) . .Pp .Fl e takes the form diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 1b994db77e2..b2616b63692 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1202 2023/08/08 07:41:04 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1203 2023/08/08 08:08:47 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -3306,11 +3306,13 @@ void menu_add_item(struct menu *, const struct menu_item *, struct cmd_find_state *); void menu_free(struct menu *); struct menu_data *menu_prepare(struct menu *, int, int, struct cmdq_item *, - u_int, u_int, struct client *, struct cmd_find_state *, - menu_choice_cb, void *); + u_int, u_int, struct client *, enum box_lines, const char *, + const char *, struct cmd_find_state *, menu_choice_cb, + void *); int menu_display(struct menu *, int, int, struct cmdq_item *, - u_int, u_int, struct client *, struct cmd_find_state *, - menu_choice_cb, void *); + u_int, u_int, struct client *, enum box_lines, const char *, + const char *, struct cmd_find_state *, menu_choice_cb, + void *); struct screen *menu_mode_cb(struct client *, void *, u_int *, u_int *); void menu_check_cb(struct client *, void *, u_int, u_int, u_int, struct overlay_ranges *);