From a5fd80bbc3e6a65ce0e3bce4cf820db3ae0f3165 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 7 Aug 2023 10:04:29 +0000 Subject: [PATCH 1/9] Trim can generate strings longer than the original if there are many #s, so create a bigger buffer. Reported by Robert Morris. --- format-draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/format-draw.c b/format-draw.c index 1a7e60b3..3ea1f52f 100644 --- a/format-draw.c +++ b/format-draw.c @@ -1083,7 +1083,7 @@ format_trim_left(const char *expanded, u_int limit) struct utf8_data ud; enum utf8_state more; - out = copy = xcalloc(1, strlen(expanded) + 1); + out = copy = xcalloc(2, strlen(expanded) + 1); while (*cp != '\0') { if (width >= limit) break; @@ -1150,7 +1150,7 @@ format_trim_right(const char *expanded, u_int limit) return (xstrdup(expanded)); skip = total_width - limit; - out = copy = xcalloc(1, strlen(expanded) + 1); + out = copy = xcalloc(2, strlen(expanded) + 1); while (*cp != '\0') { if (*cp == '#') { end = format_leading_hashes(cp, &n, &leading_width); From 7b1030293ceade6b17f4b046be0add11755c8602 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 7 Aug 2023 10:52:00 +0000 Subject: [PATCH 2/9] Free title earlier, from Alexis Hildebrandt. --- cmd-display-menu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd-display-menu.c b/cmd-display-menu.c index 4f230ae5..5f9dc459 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -316,6 +316,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) else title = xstrdup(""); menu = menu_create(title); + free(title); for (i = 0; i != count; /* nothing */) { name = args_string(args, i++); @@ -326,7 +327,6 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) if (count - i < 2) { cmdq_error(item, "not enough arguments"); - free(title); menu_free(menu); return (CMD_RETURN_ERROR); } @@ -338,7 +338,6 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) menu_add_item(menu, &menu_item, item, tc, target); } - free(title); if (menu == NULL) { cmdq_error(item, "invalid menu arguments"); return (CMD_RETURN_ERROR); From 2b535bc173548a9a6d57a92c9f4f7c74bfae7709 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 8 Aug 2023 07:19:48 +0000 Subject: [PATCH 3/9] Fix a couple of rounded border characters, from Alexis Hildebrandt. --- tty-acs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tty-acs.c b/tty-acs.c index 64ba367e..3dab31b6 100644 --- a/tty-acs.c +++ b/tty-acs.c @@ -155,8 +155,8 @@ static const struct utf8_data tty_acs_rounded_borders_list[] = { { "\342\225\257", 0, 3, 1 }, /* U+256F */ { "\342\224\263", 0, 3, 1 }, /* U+2533 */ { "\342\224\273", 0, 3, 1 }, /* U+253B */ - { "\342\224\243", 0, 3, 1 }, /* U+2523 */ - { "\342\224\253", 0, 3, 1 }, /* U+252B */ + { "\342\224\234", 0, 3, 1 }, /* U+2524 */ + { "\342\224\244", 0, 3, 1 }, /* U+251C */ { "\342\225\213", 0, 3, 1 }, /* U+254B */ { "\302\267", 0, 2, 1 } /* U+00B7 */ }; From 1071ef8fc5bd5d2776dd6b413ce0535a0f81be65 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 8 Aug 2023 07:41:04 +0000 Subject: [PATCH 4/9] Extend the menu drawing function to support custom characters and styles, from Alexis Hildebrandt. --- menu.c | 3 +- screen-write.c | 148 +++++++++++++++++++++++++++--------------------- tmux.h | 4 +- window-client.c | 2 +- 4 files changed, 89 insertions(+), 68 deletions(-) diff --git a/menu.c b/menu.c index 288030b2..dd9dcb41 100644 --- a/menu.c +++ b/menu.c @@ -203,7 +203,8 @@ menu_draw_cb(struct client *c, void *data, screen_write_start(&ctx, s); screen_write_clearscreen(&ctx, 8); - screen_write_menu(&ctx, menu, md->choice, &gc); + screen_write_menu(&ctx, menu, md->choice, BOX_LINES_DEFAULT, + &grid_default_cell, &grid_default_cell, &gc); screen_write_stop(&ctx); for (i = 0; i < screen_size_y(&md->s); i++) { diff --git a/screen-write.c b/screen-write.c index d7c196e1..177395a6 100644 --- a/screen-write.c +++ b/screen-write.c @@ -30,7 +30,6 @@ static void screen_write_collect_clear(struct screen_write_ctx *, u_int, static void screen_write_collect_scroll(struct screen_write_ctx *, u_int); static void screen_write_collect_flush(struct screen_write_ctx *, int, const char *); - static int screen_write_overwrite(struct screen_write_ctx *, struct grid_cell *, u_int); static const struct grid_cell *screen_write_combine(struct screen_write_ctx *, @@ -592,9 +591,46 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src, } } +/* Select character set for drawing border lines. */ +static void +screen_write_box_border_set(enum box_lines lines, int cell_type, + struct grid_cell *gc) +{ + switch (lines) { + case BOX_LINES_NONE: + break; + case BOX_LINES_DOUBLE: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_double_borders(cell_type)); + break; + case BOX_LINES_HEAVY: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type)); + break; + case BOX_LINES_ROUNDED: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type)); + break; + case BOX_LINES_SIMPLE: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); + break; + case BOX_LINES_PADDED: + gc->attr &= ~GRID_ATTR_CHARSET; + utf8_set(&gc->data, PADDED_BORDERS[cell_type]); + break; + case BOX_LINES_SINGLE: + case BOX_LINES_DEFAULT: + gc->attr |= GRID_ATTR_CHARSET; + utf8_set(&gc->data, CELL_BORDERS[cell_type]); + break; + } +} + /* Draw a horizontal line on screen. */ void -screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right) +screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right, + enum box_lines lines, const struct grid_cell *border_gc) { struct screen *s = ctx->s; struct grid_cell gc; @@ -603,13 +639,27 @@ screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right) cx = s->cx; cy = s->cy; - memcpy(&gc, &grid_default_cell, sizeof gc); + if (border_gc != NULL) + memcpy(&gc, border_gc, sizeof gc); + else + memcpy(&gc, &grid_default_cell, sizeof gc); gc.attr |= GRID_ATTR_CHARSET; - screen_write_putc(ctx, &gc, left ? 't' : 'q'); + if (left) + screen_write_box_border_set(lines, CELL_LEFTJOIN, &gc); + else + screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc); + screen_write_cell(ctx, &gc); + + screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc); for (i = 1; i < nx - 1; i++) - screen_write_putc(ctx, &gc, 'q'); - screen_write_putc(ctx, &gc, right ? 'u' : 'q'); + screen_write_cell(ctx, &gc); + + if (right) + screen_write_box_border_set(lines, CELL_RIGHTJOIN, &gc); + else + screen_write_box_border_set(lines, CELL_LEFTRIGHT, &gc); + screen_write_cell(ctx, &gc); screen_write_set_cursor(ctx, cx, cy); } @@ -641,86 +691,54 @@ screen_write_vline(struct screen_write_ctx *ctx, u_int ny, int top, int bottom) /* Draw a menu on screen. */ void -screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, - int choice, const struct grid_cell *choice_gc) +screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, int choice, + enum box_lines lines, const struct grid_cell *menu_gc, + const struct grid_cell *border_gc, const struct grid_cell *choice_gc) { struct screen *s = ctx->s; struct grid_cell default_gc; const struct grid_cell *gc = &default_gc; - u_int cx, cy, i, j; + u_int cx, cy, i, j, width = menu->width; const char *name; cx = s->cx; cy = s->cy; - memcpy(&default_gc, &grid_default_cell, sizeof default_gc); + memcpy(&default_gc, menu_gc, sizeof default_gc); - screen_write_box(ctx, menu->width + 4, menu->count + 2, - BOX_LINES_DEFAULT, &default_gc, menu->title); + screen_write_box(ctx, menu->width + 4, menu->count + 2, lines, + border_gc, menu->title); for (i = 0; i < menu->count; i++) { name = menu->items[i].name; if (name == NULL) { screen_write_cursormove(ctx, cx, cy + 1 + i, 0); - screen_write_hline(ctx, menu->width + 4, 1, 1); - } else { - 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 < menu->width; j++) - screen_write_putc(ctx, gc, ' '); - screen_write_cursormove(ctx, cx + 2, cy + 1 + i, 0); - if (*name == '-') { - name++; - default_gc.attr |= GRID_ATTR_DIM; - format_draw(ctx, gc, menu->width, name, NULL, - 0); - default_gc.attr &= ~GRID_ATTR_DIM; - } else - format_draw(ctx, gc, menu->width, name, NULL, - gc == choice_gc); - gc = &default_gc; + screen_write_hline(ctx, width + 4, 1, 1, lines, 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_putc(ctx, gc, ' '); + + screen_write_cursormove(ctx, cx + 2, cy + 1 + i, 0); + if (*name == '-') { + default_gc.attr |= GRID_ATTR_DIM; + format_draw(ctx, gc, width, name + 1, NULL, 0); + default_gc.attr &= ~GRID_ATTR_DIM; + continue; + } + + format_draw(ctx, gc, width, name, NULL, gc == choice_gc); + gc = &default_gc; } screen_write_set_cursor(ctx, cx, cy); } -static void -screen_write_box_border_set(enum box_lines box_lines, int cell_type, - struct grid_cell *gc) -{ - switch (box_lines) { - case BOX_LINES_NONE: - break; - case BOX_LINES_DOUBLE: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_copy(&gc->data, tty_acs_double_borders(cell_type)); - break; - case BOX_LINES_HEAVY: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type)); - break; - case BOX_LINES_ROUNDED: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type)); - break; - case BOX_LINES_SIMPLE: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]); - break; - case BOX_LINES_PADDED: - gc->attr &= ~GRID_ATTR_CHARSET; - utf8_set(&gc->data, PADDED_BORDERS[cell_type]); - break; - case BOX_LINES_SINGLE: - case BOX_LINES_DEFAULT: - gc->attr |= GRID_ATTR_CHARSET; - utf8_set(&gc->data, CELL_BORDERS[cell_type]); - break; - } -} - /* Draw a box on screen. */ void screen_write_box(struct screen_write_ctx *ctx, u_int nx, u_int ny, diff --git a/tmux.h b/tmux.h index 9588c285..07a12d63 100644 --- a/tmux.h +++ b/tmux.h @@ -2889,9 +2889,11 @@ void screen_write_putc(struct screen_write_ctx *, const struct grid_cell *, u_char); void screen_write_fast_copy(struct screen_write_ctx *, struct screen *, u_int, u_int, u_int, u_int); -void screen_write_hline(struct screen_write_ctx *, u_int, int, int); +void screen_write_hline(struct screen_write_ctx *, u_int, int, int, + enum box_lines, const struct grid_cell *); void screen_write_vline(struct screen_write_ctx *, u_int, int, int); void screen_write_menu(struct screen_write_ctx *, struct menu *, int, + enum box_lines, const struct grid_cell *, const struct grid_cell *, const struct grid_cell *); void screen_write_box(struct screen_write_ctx *, u_int, u_int, enum box_lines, const struct grid_cell *, const char *); diff --git a/window-client.c b/window-client.c index 8d501b0d..b704b530 100644 --- a/window-client.c +++ b/window-client.c @@ -242,7 +242,7 @@ window_client_draw(__unused void *modedata, void *itemdata, screen_write_cursormove(ctx, cx, cy + 2, 0); else screen_write_cursormove(ctx, cx, cy + sy - 1 - lines, 0); - screen_write_hline(ctx, sx, 0, 0); + screen_write_hline(ctx, sx, 0, 0, BOX_LINES_DEFAULT, NULL); if (at != 0) screen_write_cursormove(ctx, cx, cy, 0); From dee72ed41f54d9ba12b1ce20c18476d9276a876d Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 8 Aug 2023 08:08:47 +0000 Subject: [PATCH 5/9] Add options and flags for menu styles similar to those existing for popups, from Alexis Hildebrandt. GitHub issue 3650. --- cmd-display-menu.c | 39 ++++++++++++++++++++++++++--------- menu.c | 51 ++++++++++++++++++++++++++++++++++++++++------ mode-tree.c | 4 ++-- options-table.c | 27 ++++++++++++++++++++++++ popup.c | 4 ++-- screen-write.c | 7 ++++--- status.c | 10 +++++---- 7 files changed, 115 insertions(+), 27 deletions(-) diff --git a/cmd-display-menu.c b/cmd-display-menu.c index 5f9dc459..a0a86b1f 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -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/menu.c b/menu.c index dd9dcb41..4d2fb95a 100644 --- a/menu.c +++ b/menu.c @@ -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/mode-tree.c b/mode-tree.c index 9d465e7b..5a213df4 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -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/options-table.c b/options-table.c index 6fc5a96f..745f2b3b 100644 --- a/options-table.c +++ b/options-table.c @@ -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/popup.c b/popup.c index 9ab8490f..2fb6f1fa 100644 --- a/popup.c +++ b/popup.c @@ -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/screen-write.c b/screen-write.c index 177395a6..25158ee5 100644 --- a/screen-write.c +++ b/screen-write.c @@ -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/status.c b/status.c index 2bb42c0c..66f2dfb6 100644 --- a/status.c +++ b/status.c @@ -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); From 7a44984069328b3eaab36d590c403d23d109aa47 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 8 Aug 2023 08:21:29 +0000 Subject: [PATCH 6/9] Add flag to next-prompt/previous-prompt to go to command output instead, from Magnus Gross. --- input.c | 3 ++ tmux.1 | 107 ++++++++++++++++++++++++++++++++++++-------------- tmux.h | 11 ++++-- window-copy.c | 23 +++++++---- 4 files changed, 103 insertions(+), 41 deletions(-) diff --git a/input.c b/input.c index 5f2cac46..67b5ee66 100644 --- a/input.c +++ b/input.c @@ -2756,6 +2756,9 @@ input_osc_133(struct input_ctx *ictx, const char *p) case 'A': gl->flags |= GRID_LINE_START_PROMPT; break; + case 'C': + gl->flags |= GRID_LINE_START_OUTPUT; + break; } } diff --git a/tmux.1 b/tmux.1 index 0fdbe41b..8647ea4c 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1782,29 +1782,35 @@ Exit copy mode. .Xc Clear the current selection. .It Xo -.Ic copy-end-of-line [] +.Ic copy-end-of-line +.Op Ar prefix .Xc Copy from the cursor position to the end of the line. .Ar prefix is used to name the new paste buffer. .It Xo -.Ic copy-end-of-line-and-cancel [] +.Ic copy-end-of-line-and-cancel +.Op Ar prefix .Xc Copy from the cursor position and exit copy mode. .It Xo -.Ic copy-line [] +.Ic copy-line +.Op Ar prefix .Xc Copy the entire line. .It Xo -.Ic copy-line-and-cancel [] +.Ic copy-line-and-cancel +.Op Ar prefix .Xc Copy the entire line and exit copy mode. .It Xo -.Ic copy-selection [] +.Ic copy-selection +.Op Ar prefix .Xc Copies the current selection. .It Xo -.Ic copy-selection-and-cancel [] +.Ic copy-selection-and-cancel +.Op Ar prefix (vi: Enter) (emacs: M-w) .Xc @@ -1840,7 +1846,8 @@ Move the cursor up. .Xc Move the cursor to the end of the line. .It Xo -.Ic goto-line +.Ic goto-line +.Ar line (vi: :) (emacs: g) .Xc @@ -1864,13 +1871,15 @@ Scroll to the top of the history. .Xc Repeat the last jump. .It Xo -.Ic jump-backward +.Ic jump-backward +.Ar to (vi: F) (emacs: F) .Xc Jump backwards to the specified text. .It Xo -.Ic jump-forward +.Ic jump-forward +.Ar to (vi: f) (emacs: f) .Xc @@ -1901,6 +1910,7 @@ Move to the next matching bracket. Move to the next paragraph. .It Xo .Ic next-prompt +.Op Fl o .Xc Move to the next prompt. .It Xo @@ -1933,6 +1943,7 @@ Move to the previous matching bracket. Move to the previous paragraph. .It Xo .Ic previous-prompt +.Op Fl o .Xc Move to the previous prompt. .It Xo @@ -1960,12 +1971,14 @@ Refresh the content from the pane. .Xc Repeat the last search. .It Xo -.Ic search-backward +.Ic search-backward +.Ar text (vi: ?) .Xc Search backwards for the specified text. .It Xo -.Ic search-forward +.Ic search-forward +.Ar text (vi: /) .Xc Search forward for the specified text. @@ -2033,6 +2046,9 @@ move between shell prompts, but require the shell to emit an escape sequence .Nm where the prompts are located; if the shell does not do this, these commands will do nothing. +The +.Fl o +flag jumps to the beginning of the command output instead of the shell prompt. .Pp Copy commands may take an optional buffer prefix argument which is used to generate the buffer name (the default is @@ -4073,6 +4089,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 +4576,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 +6062,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 +6094,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 +6226,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 +6270,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 +6284,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/tmux.h b/tmux.h index 07a12d63..e26cabdf 100644 --- a/tmux.h +++ b/tmux.h @@ -672,6 +672,7 @@ struct colour_palette { #define GRID_LINE_EXTENDED 0x2 #define GRID_LINE_DEAD 0x4 #define GRID_LINE_START_PROMPT 0x8 +#define GRID_LINE_START_OUTPUT 0x10 /* Grid string flags. */ #define GRID_STRING_WITH_SEQUENCES 0x1 @@ -3306,11 +3307,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 *); diff --git a/window-copy.c b/window-copy.c index b0f14098..54255dd7 100644 --- a/window-copy.c +++ b/window-copy.c @@ -131,7 +131,8 @@ static void window_copy_cursor_previous_word_pos(struct window_mode_entry *, const char *, u_int *, u_int *); static void window_copy_cursor_previous_word(struct window_mode_entry *, const char *, int); -static void window_copy_cursor_prompt(struct window_mode_entry *, int); +static void window_copy_cursor_prompt(struct window_mode_entry *, int, + const char *); static void window_copy_scroll_up(struct window_mode_entry *, u_int); static void window_copy_scroll_down(struct window_mode_entry *, u_int); static void window_copy_rectangle_set(struct window_mode_entry *, int); @@ -2245,8 +2246,9 @@ static enum window_copy_cmd_action window_copy_cmd_next_prompt(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; + const char *arg1 = args_string(cs->args, 1); - window_copy_cursor_prompt(wme, 1); + window_copy_cursor_prompt(wme, 1, arg1); return (WINDOW_COPY_CMD_NOTHING); } @@ -2254,8 +2256,9 @@ static enum window_copy_cmd_action window_copy_cmd_previous_prompt(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; + const char *arg1 = args_string(cs->args, 1); - window_copy_cursor_prompt(wme, 0); + window_copy_cursor_prompt(wme, 0, arg1); return (WINDOW_COPY_CMD_NOTHING); } @@ -2721,7 +2724,7 @@ static const struct { }, { .command = "previous-prompt", .minargs = 0, - .maxargs = 0, + .maxargs = 1, .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, .f = window_copy_cmd_previous_prompt }, @@ -5389,14 +5392,20 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, } static void -window_copy_cursor_prompt(struct window_mode_entry *wme, int direction) +window_copy_cursor_prompt(struct window_mode_entry *wme, int direction, + const char *args) { struct window_copy_mode_data *data = wme->data; struct screen *s = data->backing; struct grid *gd = s->grid; u_int end_line; u_int line = gd->hsize - data->oy + data->cy; - int add; + int add, line_flag; + + if (args != NULL && strcmp(args, "-o") == 0) + line_flag = GRID_LINE_START_OUTPUT; + else + line_flag = GRID_LINE_START_PROMPT; if (direction == 0) { /* up */ add = -1; @@ -5413,7 +5422,7 @@ window_copy_cursor_prompt(struct window_mode_entry *wme, int direction) return; line += add; - if (grid_get_line(gd, line)->flags & GRID_LINE_START_PROMPT) + if (grid_get_line(gd, line)->flags & line_flag) break; } From 57837bbf67c10638e0684c93bb29e88ca9b07b52 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 11 Aug 2023 17:09:00 +0000 Subject: [PATCH 7/9] Do not crash if in buffer mode and the last buffer is deleted using the command. --- mode-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mode-tree.c b/mode-tree.c index 5a213df4..fa251c8d 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -497,7 +497,7 @@ mode_tree_build(struct mode_tree_data *mtd) mode_tree_clear_lines(mtd); mode_tree_build_lines(mtd, &mtd->children, 0); - if (tag == UINT64_MAX) + if (mtd->line_list != NULL && tag == UINT64_MAX) tag = mtd->line_list[mtd->current].item->tag; mode_tree_set_current(mtd, tag); From b770a429c63a8e286dbd3939215fbffa59e73d9a Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 15 Aug 2023 07:01:47 +0000 Subject: [PATCH 8/9] Add an option menu-selected-style to configure the currently selected menu item, from Alexis Hildebrandt. --- cmd-display-menu.c | 11 ++++---- menu.c | 62 ++++++++++++++++++++++++---------------------- mode-tree.c | 2 +- options-table.c | 11 +++++++- popup.c | 2 +- screen-write.c | 2 +- status.c | 8 +++--- tmux.1 | 16 ++++++++++-- tmux.h | 8 +++--- 9 files changed, 73 insertions(+), 49 deletions(-) diff --git a/cmd-display-menu.c b/cmd-display-menu.c index a0a86b1f..7d0d3e59 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -39,11 +39,11 @@ const struct cmd_entry cmd_display_menu_entry = { .name = "display-menu", .alias = "menu", - .args = { "b:c:C:t:s:S:OT:x:y:", 1, -1, cmd_display_menu_args_parse }, + .args = { "b:c:C:H:s:S:Ot:T: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 ...", + "[-C starting-choice] [-H selected-style] [-s style] " + "[-S border-style] " CMD_TARGET_PANE_USAGE "[-T title] " + "[-x position] [-y position] name key command ...", .target = { 't', CMD_FIND_PANE, 0 }, @@ -293,6 +293,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) const char *key, *name, *value; const char *style = args_get(args, 's'); const char *border_style = args_get(args, 'S'); + const char *selected_style = args_get(args, 'H'); enum box_lines lines = BOX_LINES_DEFAULT; char *title, *cause; int flags = 0, starting_choice = 0; @@ -376,7 +377,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) if (!event->m.valid) flags |= MENU_NOMOUSE; if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines, - style, border_style, target, NULL, NULL) != 0) + style, selected_style, border_style, target, NULL, NULL) != 0) return (CMD_RETURN_NORMAL); return (CMD_RETURN_WAIT); } diff --git a/menu.c b/menu.c index 4d2fb95a..8d7b40a2 100644 --- a/menu.c +++ b/menu.c @@ -29,6 +29,7 @@ struct menu_data { struct grid_cell style; struct grid_cell border_style; + struct grid_cell selected_style; enum box_lines border_lines; struct cmd_find_state fs; @@ -201,7 +202,6 @@ menu_draw_cb(struct client *c, void *data, struct menu *menu = md->menu; struct screen_write_ctx ctx; u_int i, px = md->px, py = md->py; - struct grid_cell gc; screen_write_start(&ctx, s); screen_write_clearscreen(&ctx, 8); @@ -210,10 +210,9 @@ menu_draw_cb(struct client *c, void *data, 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); + &md->style, &md->border_style, &md->selected_style); screen_write_stop(&ctx); for (i = 0; i < screen_size_y(&md->s); i++) { @@ -438,16 +437,35 @@ chosen: return (1); } +static void +menu_set_style(struct client *c, struct grid_cell *gc, const char *style, + const char *option) +{ + struct style sytmp; + struct options *o = c->session->curw->window->options; + + memcpy(gc, &grid_default_cell, sizeof *gc); + style_apply(gc, o, option, NULL); + if (style != NULL) { + style_set(&sytmp, &grid_default_cell); + if (style_parse(&sytmp, gc, style) == 0) { + gc->fg = sytmp.gc.fg; + gc->bg = sytmp.gc.bg; + } + } + gc->attr = 0; +} + 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) + enum box_lines lines, const char *style, const char *selected_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) @@ -465,27 +483,10 @@ menu_prepare(struct menu *menu, int flags, int starting_choice, 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; + menu_set_style(c, &md->style, style, "menu-style"); + menu_set_style(c, &md->selected_style, selected_style, + "menu-selected-style"); + menu_set_style(c, &md->border_style, border_style, "menu-border-style"); if (fs != NULL) cmd_find_copy_state(&md->fs, fs); @@ -539,13 +540,14 @@ 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) + enum box_lines lines, const char *style, const char *selected_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, lines, - style, border_style, fs, cb, data); + style, selected_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/mode-tree.c b/mode-tree.c index fa251c8d..cebd4f05 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -963,7 +963,7 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x, else x = 0; if (menu_display(menu, 0, 0, NULL, x, y, c, BOX_LINES_DEFAULT, NULL, - NULL, NULL, mode_tree_menu_callback, mtm) != 0) + NULL, NULL, NULL, mode_tree_menu_callback, mtm) != 0) menu_free(menu); } diff --git a/options-table.c b/options-table.c index 745f2b3b..eacf0947 100644 --- a/options-table.c +++ b/options-table.c @@ -336,6 +336,15 @@ const struct options_table_entry options_table[] = { .text = "Default style of menu." }, + { .name = "menu-selected-style", + .type = OPTIONS_TABLE_STRING, + .scope = OPTIONS_TABLE_WINDOW, + .flags = OPTIONS_TABLE_IS_STYLE, + .default_str = "bg=yellow,fg=black", + .separator = ",", + .text = "Default style of selected menu item." + }, + { .name = "menu-border-style", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, @@ -962,8 +971,8 @@ const struct options_table_entry options_table[] = { { .name = "mode-style", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .default_str = "bg=yellow,fg=black", .flags = OPTIONS_TABLE_IS_STYLE, + .default_str = "bg=yellow,fg=black", .separator = ",", .text = "Style of indicators and highlighting in modes." }, diff --git a/popup.c b/popup.c index 2fb6f1fa..38a4c17f 100644 --- a/popup.c +++ b/popup.c @@ -576,7 +576,7 @@ menu: else x = 0; pd->md = menu_prepare(pd->menu, 0, 0, NULL, x, m->y, c, - BOX_LINES_DEFAULT, NULL, NULL, NULL, popup_menu_done, pd); + BOX_LINES_DEFAULT, NULL, NULL, NULL, NULL, popup_menu_done, pd); c->flags |= CLIENT_REDRAWOVERLAY; out: diff --git a/screen-write.c b/screen-write.c index 25158ee5..ee3a31a1 100644 --- a/screen-write.c +++ b/screen-write.c @@ -733,7 +733,7 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, int choice, continue; } - format_draw(ctx, gc, width, name, NULL, gc == choice_gc); + format_draw(ctx, gc, width, name, NULL, 0); gc = &default_gc; } diff --git a/status.c b/status.c index 66f2dfb6..a15981e9 100644 --- a/status.c +++ b/status.c @@ -1765,8 +1765,8 @@ status_prompt_complete_list_menu(struct client *c, char **list, u_int size, offset = 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) { + BOX_LINES_DEFAULT, NULL, NULL, NULL, NULL, + status_prompt_menu_callback, spm) != 0) { menu_free(menu); free(spm); return (0); @@ -1859,8 +1859,8 @@ status_prompt_complete_window_menu(struct client *c, struct session *s, offset = 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) { + BOX_LINES_DEFAULT, NULL, NULL, NULL, NULL, + status_prompt_menu_callback, spm) != 0) { menu_free(menu); free(spm); return (NULL); diff --git a/tmux.1 b/tmux.1 index 8647ea4c..8191b6dc 100644 --- a/tmux.1 +++ b/tmux.1 @@ -4096,6 +4096,13 @@ See the section on how to specify .Ar style . Attributes are ignored. +.It Ic menu-selected-style Ar style +Set the selected menu item 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 @@ -4108,7 +4115,7 @@ Set the type of characters used for drawing menu borders. See .Ic popup-border-lines for possible values for -.Ar type . +.Ar border-lines . .It Ic message-command-style Ar style Set status line message command style. This is used for the command prompt with @@ -6064,10 +6071,11 @@ the default is .Op Fl O .Op Fl b Ar border-lines .Op Fl c Ar target-client +.Op Fl C Ar starting-choice +.Op Fl H Ar selected-style .Op Fl s Ar style .Op Fl S Ar border-style .Op Fl t Ar target-pane -.Op Fl C Ar starting-choice .Op Fl T Ar title .Op Fl x Ar position .Op Fl y Ar position @@ -6101,6 +6109,10 @@ See for possible values for .Ar border-lines . .Pp +.Fl H +sets the style for the selected menu item (see +.Sx STYLES ) . +.Pp .Fl s sets the style for the menu and .Fl S diff --git a/tmux.h b/tmux.h index e26cabdf..378871b7 100644 --- a/tmux.h +++ b/tmux.h @@ -3308,12 +3308,12 @@ void menu_add_item(struct menu *, const struct menu_item *, void menu_free(struct menu *); struct menu_data *menu_prepare(struct menu *, int, int, struct cmdq_item *, u_int, u_int, struct client *, enum box_lines, const char *, - const char *, struct cmd_find_state *, menu_choice_cb, - void *); + 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 *, enum box_lines, const char *, - const char *, struct cmd_find_state *, menu_choice_cb, - void *); + 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 *); From d9942c769eb059e2cadfb63f2050fad8d0357d19 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 15 Aug 2023 09:51:48 +0000 Subject: [PATCH 9/9] Add meta bindings for status line menus as well as the existing pane one for terminals which steal the mouse menu button. --- key-bindings.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/key-bindings.c b/key-bindings.c index d0697544..eaf05f02 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -466,9 +466,11 @@ key_bindings_init(void) /* Mouse button 3 down on status left. */ "bind -n MouseDown3StatusLeft { display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU " }", + "bind -n M-MouseDown3StatusLeft { display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU " }", /* Mouse button 3 down on status line. */ "bind -n MouseDown3Status { display-menu -t= -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU "}", + "bind -n M-MouseDown3Status { display-menu -t= -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU "}", /* Mouse button 3 down on pane. */ "bind -n MouseDown3Pane { if -Ft= '#{||:#{mouse_any_flag},#{&&:#{pane_in_mode},#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}}}' { select-pane -t=; send -M } { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " } }",