diff --git a/runtime/doc/api-ui-events.txt b/runtime/doc/api-ui-events.txt index 34e9135f3f..35e71e0cee 100644 --- a/runtime/doc/api-ui-events.txt +++ b/runtime/doc/api-ui-events.txt @@ -335,6 +335,10 @@ numerical highlight ids to the actual attributes. `underdotted`: underdotted text. The dots have `special` color. `underdashed`: underdashed text. The dashes have `special` color. `altfont`: alternative font. + `dim`: half-bright/faint text. + `blink`: blinking text. + `conceal`: concealed/hidden text. + `overline`: overlined text. `blend`: blend level (0-100). Could be used by UIs to support blending floating windows to the background or to signal a transparent cursor. @@ -504,6 +508,10 @@ is not active. New UIs should implement |ui-linegrid| instead. `underdouble`: double underlined text. The lines have `special` color. `underdotted`: underdotted text. The dots have `special` color. `underdashed`: underdashed text. The dashes have `special` color. + `dim`: half-bright/faint text. + `blink`: blinking text. + `conceal`: concealed/hidden text. + `overline`: overlined text. ["put", text] ~ The (utf-8 encoded) string `text` is put at the cursor position diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 526cd62b1e..24c2e0dcb7 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1553,6 +1553,11 @@ nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()* • sp: color name or "#RRGGBB" • blend: integer between 0 and 100 • bold: boolean + • altfont: boolean + • blink: boolean + • dim: boolean + • conceal: boolean + • overline: boolean • standout: boolean • underline: boolean • undercurl: boolean diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index c24f131e08..fbe2a4540d 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -248,6 +248,8 @@ HIGHLIGHTS • |hl-OkMsg| |hl-StderrMsg| |hl-StdoutMsg| • |hl-SnippetTabstopActive| highlights the currently active tabstop. • |hl-PmenuBorder| |hl-PmenuShadow| |hl-PmenuShadowThrough| see 'pumborder'. +• |nvim_set_hl()| and |nvim_get_hl()| support the SGR attributes "dim", + "blink", "conceal", and "overline". LSP @@ -404,6 +406,8 @@ TUI • |TermResponse| now supports DA1 and APC query responses. • Native progress bars are displayed for |Progress| events using the OSC 9;4 sequence. +• The TUI now renders the SGR dim (faint), blink, conceal, and overline + attributes. UI diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 5ca92d1289..3ddd567969 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -5059,7 +5059,7 @@ the same syntax file on all UIs. *underdouble* *underdotted* *underdashed* *inverse* *italic* *standout* *strikethrough* *altfont* - *nocombine* + *dim* *blink* *hl-conceal* *overline* *nocombine* cterm={attr-list} *attr-list* *highlight-cterm* *E418* attr-list is a comma-separated list (without spaces) of the following items (in any order): @@ -5075,6 +5075,10 @@ cterm={attr-list} *attr-list* *highlight-cterm* *E418* italic standout altfont + dim half-bright/faint text + blink blinking text + conceal concealed/hidden text + overline overlined text nocombine override attributes instead of combining them NONE no attributes used (used to reset it) diff --git a/runtime/doc/vimfn.txt b/runtime/doc/vimfn.txt index e5a31ec0cf..35d3b34df9 100644 --- a/runtime/doc/vimfn.txt +++ b/runtime/doc/vimfn.txt @@ -11046,6 +11046,10 @@ synIDattr({synID}, {what} [, {mode}]) *synIDattr()* "strikethrough" "1" if struckthrough "altfont" "1" if alternative font "nocombine" "1" if nocombine + "dim" "1" if half-bright/dimmed + "blink" "1" if blinking + "conceal" "1" if concealed + "overline" "1" if overlined Returns an empty string on error. diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 9e40aa01cc..13699c76d4 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -2208,6 +2208,11 @@ function vim.api.nvim_set_decoration_provider(ns_id, opts) end --- - sp: color name or "#RRGGBB" --- - blend: integer between 0 and 100 --- - bold: boolean +--- - altfont: boolean +--- - blink: boolean +--- - dim: boolean +--- - conceal: boolean +--- - overline: boolean --- - standout: boolean --- - underline: boolean --- - undercurl: boolean diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 595e54686d..6d3b4aedf1 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -306,6 +306,10 @@ error('Cannot require a meta file') --- @field italic? boolean --- @field reverse? boolean --- @field altfont? boolean +--- @field dim? boolean +--- @field blink? boolean +--- @field conceal? boolean +--- @field overline? boolean --- @field nocombine? boolean --- @field default? boolean --- @field cterm? vim.api.keyset.highlight_cterm @@ -338,6 +342,10 @@ error('Cannot require a meta file') --- @field italic? boolean --- @field reverse? boolean --- @field altfont? boolean +--- @field dim? boolean +--- @field blink? boolean +--- @field conceal? boolean +--- @field overline? boolean --- @field nocombine? boolean --- @class vim.api.keyset.keymap diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 2b859fc8f9..2c95ae8c92 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -10078,6 +10078,10 @@ function vim.fn.synID(lnum, col, trans) end --- "strikethrough" "1" if struckthrough --- "altfont" "1" if alternative font --- "nocombine" "1" if nocombine +--- "dim" "1" if half-bright/dimmed +--- "blink" "1" if blinking +--- "conceal" "1" if concealed +--- "overline" "1" if overlined --- --- Returns an empty string on error. --- diff --git a/src/gen/gen_terminfo.lua b/src/gen/gen_terminfo.lua index d7c4221cd3..ce78cfe087 100644 --- a/src/gen/gen_terminfo.lua +++ b/src/gen/gen_terminfo.lua @@ -53,10 +53,13 @@ local wanted_strings = { 'cursor_up', 'cursor_right', 'delete_line', + 'enter_blink_mode', 'enter_bold_mode', 'enter_ca_mode', + 'enter_dim_mode', 'enter_italics_mode', 'enter_reverse_mode', + 'enter_secure_mode', 'enter_standout_mode', 'enter_underline_mode', 'erase_chars', diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h index cecbbf143b..f084b196bf 100644 --- a/src/nvim/api/keysets_defs.h +++ b/src/nvim/api/keysets_defs.h @@ -179,6 +179,10 @@ typedef struct { Boolean italic; Boolean reverse; Boolean altfont; + Boolean dim; + Boolean blink; + Boolean conceal; + Boolean overline; Boolean nocombine; Boolean default_ DictKey(default); DictAs(highlight_cterm) cterm; @@ -212,6 +216,10 @@ typedef struct { Boolean italic; Boolean reverse; Boolean altfont; + Boolean dim; + Boolean blink; + Boolean conceal; + Boolean overline; Boolean nocombine; } Dict(highlight_cterm); diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 29239f4481..b0f4350ae8 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -152,6 +152,11 @@ DictAs(get_hl_info) nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena /// - sp: color name or "#RRGGBB" /// - blend: integer between 0 and 100 /// - bold: boolean +/// - altfont: boolean +/// - blink: boolean +/// - dim: boolean +/// - conceal: boolean +/// - overline: boolean /// - standout: boolean /// - underline: boolean /// - undercurl: boolean diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 70f83d1444..099dd418e9 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -9681,7 +9681,7 @@ M.funcs = { The optional argument {opts} is a Dict and supports the following items: - peer : If |TRUE|, servers not started by |serverstart()| + peer : If |TRUE|, servers not started by |serverstart()| will also be returned. (default: |FALSE|) Not supported on Windows yet. @@ -12158,6 +12158,10 @@ M.funcs = { "strikethrough" "1" if struckthrough "altfont" "1" if alternative font "nocombine" "1" if nocombine + "dim" "1" if half-bright/dimmed + "blink" "1" if blinking + "conceal" "1" if concealed + "overline" "1" if overlined Returns an empty string on error. diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index eb98aad9cf..9eb549f64b 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7371,10 +7371,21 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) case 'b': if (TOLOWER_ASC(what[1]) == 'g') { // bg[#] p = highlight_color(id, what, modec); + } else if (TOLOWER_ASC(what[1]) == 'l') { // blink + p = highlight_has_attr(id, HL_BLINK, modec); } else { // bold p = highlight_has_attr(id, HL_BOLD, modec); } break; + case 'c': // conceal + p = highlight_has_attr(id, HL_CONCEALED, modec); + break; + case 'd': // dim + p = highlight_has_attr(id, HL_DIM, modec); + break; + case 'o': // overline + p = highlight_has_attr(id, HL_OVERLINE, modec); + break; case 'f': // fg[#] or font p = highlight_color(id, what, modec); break; diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index df15b98bfb..5a174775e9 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -562,11 +562,11 @@ void hl_invalidate_blends(void) /// Combine HlAttrFlags. /// The underline attribute in "prim_ae" overrules the one in "char_ae" if both are present. -static int16_t hl_combine_ae(int16_t char_ae, int16_t prim_ae) +static int32_t hl_combine_ae(int32_t char_ae, int32_t prim_ae) { - int16_t char_ul = char_ae & HL_UNDERLINE_MASK; - int16_t prim_ul = prim_ae & HL_UNDERLINE_MASK; - int16_t new_ul = prim_ul ? prim_ul : char_ul; + int32_t char_ul = char_ae & HL_UNDERLINE_MASK; + int32_t prim_ul = prim_ae & HL_UNDERLINE_MASK; + int32_t new_ul = prim_ul ? prim_ul : char_ul; return (char_ae & ~HL_UNDERLINE_MASK) | (prim_ae & ~HL_UNDERLINE_MASK) | new_ul; } @@ -946,6 +946,22 @@ void hlattrs2dict(Dict *hl, Dict *hl_attrs, HlAttrs ae, bool use_rgb, bool short PUT_C(*hl_attrs, "altfont", BOOLEAN_OBJ(true)); } + if (mask & HL_DIM) { + PUT_C(*hl_attrs, "dim", BOOLEAN_OBJ(true)); + } + + if (mask & HL_BLINK) { + PUT_C(*hl_attrs, "blink", BOOLEAN_OBJ(true)); + } + + if (mask & HL_CONCEALED) { + PUT_C(*hl_attrs, "conceal", BOOLEAN_OBJ(true)); + } + + if (mask & HL_OVERLINE) { + PUT_C(*hl_attrs, "overline", BOOLEAN_OBJ(true)); + } + if (mask & HL_NOCOMBINE) { PUT_C(*hl_attrs, "nocombine", BOOLEAN_OBJ(true)); } @@ -997,8 +1013,8 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e int32_t ctermbg = -1; int32_t sp = -1; int blend = -1; - int16_t mask = 0; - int16_t cterm_mask = 0; + int32_t mask = 0; + int32_t cterm_mask = 0; bool cterm_mask_provided = false; #define CHECK_FLAG(d, m, name, extra, flag) \ @@ -1020,6 +1036,10 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e CHECK_FLAG(dict, mask, standout, , HL_STANDOUT); CHECK_FLAG(dict, mask, strikethrough, , HL_STRIKETHROUGH); CHECK_FLAG(dict, mask, altfont, , HL_ALTFONT); + CHECK_FLAG(dict, mask, dim, , HL_DIM); + CHECK_FLAG(dict, mask, blink, , HL_BLINK); + CHECK_FLAG(dict, mask, conceal, , HL_CONCEALED); + CHECK_FLAG(dict, mask, overline, , HL_OVERLINE); if (use_rgb) { CHECK_FLAG(dict, mask, fg_indexed, , HL_FG_INDEXED); CHECK_FLAG(dict, mask, bg_indexed, , HL_BG_INDEXED); @@ -1100,6 +1120,10 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e CHECK_FLAG(cterm, cterm_mask, standout, , HL_STANDOUT); CHECK_FLAG(cterm, cterm_mask, strikethrough, , HL_STRIKETHROUGH); CHECK_FLAG(cterm, cterm_mask, altfont, , HL_ALTFONT); + CHECK_FLAG(cterm, cterm_mask, dim, , HL_DIM); + CHECK_FLAG(cterm, cterm_mask, blink, , HL_BLINK); + CHECK_FLAG(cterm, cterm_mask, conceal, , HL_CONCEALED); + CHECK_FLAG(cterm, cterm_mask, overline, , HL_OVERLINE); CHECK_FLAG(cterm, cterm_mask, nocombine, , HL_NOCOMBINE); } #undef CHECK_FLAG diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h index 78b1b25f55..4ba17bf437 100644 --- a/src/nvim/highlight_defs.h +++ b/src/nvim/highlight_defs.h @@ -25,7 +25,10 @@ typedef enum { HL_STANDOUT = 0x0040, HL_STRIKETHROUGH = 0x0080, HL_ALTFONT = 0x0100, - // 0x0200 spare + HL_DIM = 0x0200, + HL_BLINK = 0x8000, + HL_CONCEALED = 0x10000, + HL_OVERLINE = 0x20000, HL_NOCOMBINE = 0x0400, HL_BG_INDEXED = 0x0800, HL_FG_INDEXED = 0x1000, @@ -36,7 +39,7 @@ typedef enum { /// Stores a complete highlighting entry, including colors and attributes /// for both TUI and GUI. typedef struct { - int16_t rgb_ae_attr, cterm_ae_attr; ///< HlAttrFlags + int32_t rgb_ae_attr, cterm_ae_attr; ///< HlAttrFlags RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color; int16_t cterm_fg_color, cterm_bg_color; int32_t hl_blend; @@ -175,4 +178,4 @@ typedef struct { #define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, .version = -1, \ .is_default = false, .link_global = false } -enum { HLATTRS_DICT_SIZE = 16, }; +enum { HLATTRS_DICT_SIZE = 20, }; diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 0a7bcb3d64..c731cf4cdc 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -77,12 +77,12 @@ static char *(hl_name_table[]) = { "bold", "standout", "underline", "undercurl", "underdouble", "underdotted", "underdashed", "italic", "reverse", "inverse", "strikethrough", "altfont", - "nocombine", "NONE" }; + "dim", "blink", "conceal", "overline", "nocombine", "NONE" }; static int hl_attr_table[] = { HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERCURL, HL_UNDERDOUBLE, HL_UNDERDOTTED, HL_UNDERDASHED, HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_STRIKETHROUGH, HL_ALTFONT, - HL_NOCOMBINE, 0 }; + HL_DIM, HL_BLINK, HL_CONCEALED, HL_OVERLINE, HL_NOCOMBINE, 0 }; /// Structure that stores information about a highlight group. /// The ID of a highlight group is also called group ID. It is the index in @@ -1951,10 +1951,10 @@ static void set_hl_attr(int idx) HlAttrs at_en = HLATTRS_INIT; HlGroup *sgp = hl_table + idx; - at_en.cterm_ae_attr = (int16_t)sgp->sg_cterm; + at_en.cterm_ae_attr = (int32_t)sgp->sg_cterm; at_en.cterm_fg_color = (int16_t)sgp->sg_cterm_fg; at_en.cterm_bg_color = (int16_t)sgp->sg_cterm_bg; - at_en.rgb_ae_attr = (int16_t)sgp->sg_gui; + at_en.rgb_ae_attr = (int32_t)sgp->sg_gui; // FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is // initialized with 0 (by garray functions), check for sg_rgb_{f,b}g_name // before setting attr_entry->{f,g}g_color to a other than -1 diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 4cc9dd7848..31cbf6d559 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -1405,6 +1405,8 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te bool bg_set = vt_bg_idx && vt_bg_idx <= 16 && term->color_set[vt_bg_idx - 1]; int hl_attrs = (cell.attrs.bold ? HL_BOLD : 0) + | (cell.attrs.blink ? HL_BLINK : 0) + | (cell.attrs.conceal ? HL_CONCEALED : 0) | (cell.attrs.italic ? HL_ITALIC : 0) | (cell.attrs.reverse ? HL_INVERSE : 0) | get_underline_hl_flag(cell.attrs) @@ -1416,10 +1418,10 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te if (hl_attrs || !fg_default || !bg_default) { attr_id = hl_get_term_attr(&(HlAttrs) { - .cterm_ae_attr = (int16_t)hl_attrs, + .cterm_ae_attr = (int32_t)hl_attrs, .cterm_fg_color = vt_fg_idx, .cterm_bg_color = vt_bg_idx, - .rgb_ae_attr = (int16_t)hl_attrs, + .rgb_ae_attr = (int32_t)hl_attrs, .rgb_fg_color = vt_fg, .rgb_bg_color = vt_bg, .rgb_sp_color = -1, diff --git a/src/nvim/tui/terminfo_builtin.h b/src/nvim/tui/terminfo_builtin.h index 26318e0ee6..9e102e9ea3 100644 --- a/src/nvim/tui/terminfo_builtin.h +++ b/src/nvim/tui/terminfo_builtin.h @@ -28,10 +28,13 @@ static const TerminfoEntry ansi_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = NULL, + [kTerm_enter_dim_mode] = NULL, [kTerm_enter_italics_mode] = NULL, [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = "\033[8m", [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -104,10 +107,13 @@ static const TerminfoEntry ghostty_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = NULL, [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h", + [kTerm_enter_dim_mode] = "\033[2m", [kTerm_enter_italics_mode] = "\033[3m", [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = "\033[8m", [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -243,10 +249,13 @@ static const TerminfoEntry interix_8colour_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = NULL, [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[s\033[1b", + [kTerm_enter_dim_mode] = NULL, [kTerm_enter_italics_mode] = NULL, [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = NULL, @@ -379,10 +388,13 @@ static const TerminfoEntry iterm_256colour_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h\033[22;0;0t", + [kTerm_enter_dim_mode] = "\033[2m", [kTerm_enter_italics_mode] = "\033[3m", [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = NULL, @@ -479,10 +491,13 @@ static const TerminfoEntry linux_16colour_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = NULL, + [kTerm_enter_dim_mode] = "\033[2m", [kTerm_enter_italics_mode] = NULL, [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -575,10 +590,13 @@ static const TerminfoEntry putty_256colour_terminfo = { [kTerm_cursor_up] = "\033M", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h", + [kTerm_enter_dim_mode] = NULL, [kTerm_enter_italics_mode] = NULL, [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -671,10 +689,13 @@ static const TerminfoEntry rxvt_256colour_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\0337\033[?47h", + [kTerm_enter_dim_mode] = NULL, [kTerm_enter_italics_mode] = NULL, [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = NULL, @@ -791,10 +812,13 @@ static const TerminfoEntry screen_256colour_terminfo = { [kTerm_cursor_up] = "\033M", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h", + [kTerm_enter_dim_mode] = "\033[2m", [kTerm_enter_italics_mode] = NULL, [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[3m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = NULL, @@ -879,10 +903,13 @@ static const TerminfoEntry st_256colour_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h", + [kTerm_enter_dim_mode] = "\033[2m", [kTerm_enter_italics_mode] = "\033[3m", [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = "\033[8m", [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -1018,10 +1045,13 @@ static const TerminfoEntry tmux_256colour_terminfo = { [kTerm_cursor_up] = "\033M", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h", + [kTerm_enter_dim_mode] = "\033[2m", [kTerm_enter_italics_mode] = "\033[3m", [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = "\033[8m", [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = NULL, @@ -1157,10 +1187,13 @@ static const TerminfoEntry vte_256colour_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h\033[22;0;0t", + [kTerm_enter_dim_mode] = "\033[2m", [kTerm_enter_italics_mode] = "\033[3m", [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = "\033[8m", [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -1296,10 +1329,13 @@ static const TerminfoEntry xterm_256colour_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = "\033[5m", [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h\033[22;0;0t", + [kTerm_enter_dim_mode] = "\033[2m", [kTerm_enter_italics_mode] = "\033[3m", [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = "\033[8m", [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -1435,10 +1471,13 @@ static const TerminfoEntry cygwin_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = NULL, [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\0337\033[?47h", + [kTerm_enter_dim_mode] = NULL, [kTerm_enter_italics_mode] = NULL, [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = "\033[8m", [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = NULL, @@ -1531,10 +1570,13 @@ static const TerminfoEntry win32con_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = NULL, + [kTerm_enter_blink_mode] = NULL, [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\0337\033[?47h", + [kTerm_enter_dim_mode] = NULL, [kTerm_enter_italics_mode] = NULL, [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = NULL, [kTerm_erase_chars] = NULL, @@ -1651,10 +1693,13 @@ static const TerminfoEntry conemu_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = NULL, [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h", + [kTerm_enter_dim_mode] = NULL, [kTerm_enter_italics_mode] = "\033[3m", [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -1772,10 +1817,13 @@ static const TerminfoEntry vtpcon_terminfo = { [kTerm_cursor_up] = "\033[A", [kTerm_cursor_right] = "\033[C", [kTerm_delete_line] = "\033[M", + [kTerm_enter_blink_mode] = NULL, [kTerm_enter_bold_mode] = "\033[1m", [kTerm_enter_ca_mode] = "\033[?1049h", + [kTerm_enter_dim_mode] = NULL, [kTerm_enter_italics_mode] = "\033[3m", [kTerm_enter_reverse_mode] = "\033[7m", + [kTerm_enter_secure_mode] = NULL, [kTerm_enter_standout_mode] = "\033[7m", [kTerm_enter_underline_mode] = "\033[4m", [kTerm_erase_chars] = "\033[%p1%dX", @@ -1886,10 +1934,13 @@ static const TerminfoEntry vtpcon_terminfo = { X(cursor_up) \ X(cursor_right) \ X(delete_line) \ + X(enter_blink_mode) \ X(enter_bold_mode) \ X(enter_ca_mode) \ + X(enter_dim_mode) \ X(enter_italics_mode) \ X(enter_reverse_mode) \ + X(enter_secure_mode) \ X(enter_standout_mode) \ X(enter_underline_mode) \ X(erase_chars) \ diff --git a/src/nvim/tui/terminfo_enum_defs.h b/src/nvim/tui/terminfo_enum_defs.h index d5c7dff50a..7d3500707d 100644 --- a/src/nvim/tui/terminfo_enum_defs.h +++ b/src/nvim/tui/terminfo_enum_defs.h @@ -17,10 +17,13 @@ typedef enum { kTerm_cursor_up, kTerm_cursor_right, kTerm_delete_line, + kTerm_enter_blink_mode, kTerm_enter_bold_mode, kTerm_enter_ca_mode, + kTerm_enter_dim_mode, kTerm_enter_italics_mode, kTerm_enter_reverse_mode, + kTerm_enter_secure_mode, kTerm_enter_standout_mode, kTerm_enter_underline_mode, kTerm_erase_chars, diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 8b965207f4..50ebc71597 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -752,6 +752,10 @@ static void update_attrs(TUIData *tui, int attr_id) bool standout = attr & HL_STANDOUT; bool strikethrough = attr & HL_STRIKETHROUGH; bool altfont = attr & HL_ALTFONT; + bool dim = attr & HL_DIM; + bool blink = attr & HL_BLINK; + bool conceal = attr & HL_CONCEALED; + bool overline = attr & HL_OVERLINE; bool underline; bool undercurl; @@ -777,13 +781,13 @@ static void update_attrs(TUIData *tui, int attr_id) || underdouble || underdotted || underdashed; if (tui->ti.defs[kTerm_set_attributes] != NULL) { - if (bold || reverse || underline || standout) { + if (bold || dim || blink || reverse || underline || standout) { TPVAR params[9] = { 0 }; params[0].num = standout; params[1].num = underline; params[2].num = reverse; - params[3].num = 0; // blink - params[4].num = 0; // dim + params[3].num = blink; + params[4].num = dim; params[5].num = bold; params[6].num = 0; // blank params[7].num = 0; // protect @@ -808,6 +812,12 @@ static void update_attrs(TUIData *tui, int attr_id) if (reverse) { terminfo_out(tui, kTerm_enter_reverse_mode); } + if (dim) { + terminfo_out(tui, kTerm_enter_dim_mode); + } + if (blink) { + terminfo_out(tui, kTerm_enter_blink_mode); + } } if (italic) { terminfo_out(tui, kTerm_enter_italics_mode); @@ -818,6 +828,12 @@ static void update_attrs(TUIData *tui, int attr_id) if (strikethrough) { terminfo_out(tui, kTerm_enter_strikethrough_mode); } + if (conceal) { + terminfo_out(tui, kTerm_enter_secure_mode); + } + if (overline) { + out(tui, S_LEN("\x1b[53m")); + } if (tui->ti.defs[kTerm_set_underline_style]) { if (undercurl) { terminfo_print_num1(tui, kTerm_set_underline_style, 3); @@ -898,14 +914,14 @@ static void update_attrs(TUIData *tui, int attr_id) } tui->default_attr = fg == -1 && bg == -1 - && !bold && !italic && !has_any_underline && !reverse && !standout - && !strikethrough; + && !bold && !dim && !blink && !conceal && !overline && !italic + && !has_any_underline && !reverse && !standout && !strikethrough; // Non-BCE terminals can't clear with non-default background color. Some BCE // terminals don't support attributes either, so don't rely on it. But assume // italic and bold has no effect if there is no text. - tui->can_clear_attr = !reverse && !standout && !has_any_underline - && !strikethrough && (tui->bce || bg == -1); + tui->can_clear_attr = !reverse && !standout && !dim && !blink && !conceal && !overline + && !has_any_underline && !strikethrough && (tui->bce || bg == -1); } static void final_column_wrap(TUIData *tui) diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua index 3be4d83532..7078ce1dd9 100644 --- a/test/functional/api/highlight_spec.lua +++ b/test/functional/api/highlight_spec.lua @@ -46,11 +46,19 @@ describe('API: set highlight', function() underdashed = true, strikethrough = true, altfont = true, + dim = true, + blink = true, + conceal = true, + overline = true, cterm = { italic = true, reverse = true, strikethrough = true, altfont = true, + dim = true, + blink = true, + conceal = true, + overline = true, nocombine = true, }, } @@ -63,6 +71,10 @@ describe('API: set highlight', function() underdashed = true, strikethrough = true, altfont = true, + dim = true, + blink = true, + conceal = true, + overline = true, } local highlight3_result_cterm = { ctermbg = highlight_color.ctermbg, @@ -71,6 +83,10 @@ describe('API: set highlight', function() reverse = true, strikethrough = true, altfont = true, + dim = true, + blink = true, + conceal = true, + overline = true, nocombine = true, } @@ -172,7 +188,7 @@ describe('API: set highlight', function() api.nvim_set_hl(0, 'Test_hl2', highlight3_config) eq( - 'Test_hl2 xxx cterm=italic,reverse,strikethrough,altfont,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont guifg=#ff0000 guibg=#0032aa', + 'Test_hl2 xxx cterm=italic,reverse,strikethrough,altfont,dim,blink,conceal,overline,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont,dim,blink,conceal,overline guifg=#ff0000 guibg=#0032aa', exec_capture('highlight Test_hl2') ) @@ -272,11 +288,19 @@ describe('API: get highlight', function() underdashed = true, strikethrough = true, altfont = true, + dim = true, + blink = true, + conceal = true, + overline = true, cterm = { italic = true, reverse = true, strikethrough = true, altfont = true, + dim = true, + blink = true, + conceal = true, + overline = true, nocombine = true, }, } @@ -291,12 +315,20 @@ describe('API: get highlight', function() underdashed = true, strikethrough = true, altfont = true, + dim = true, + blink = true, + conceal = true, + overline = true, cterm = { italic = true, nocombine = true, reverse = true, strikethrough = true, altfont = true, + dim = true, + blink = true, + conceal = true, + overline = true, }, } @@ -438,15 +470,21 @@ describe('API: get highlight', function() ) -- Test all highlight properties. - command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine') + command( + 'hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,dim,blink,conceal,overline,nocombine' + ) eq({ fg = 16711680, bg = 16776960, sp = 255, altfont = true, + blink = true, bold = true, + conceal = true, + dim = true, italic = true, nocombine = true, + overline = true, reverse = true, strikethrough = true, underline = true,