aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/highlight_group.c
Commit message (Collapse)AuthorAge
* fix(highlight): link TabLine to base highlight group TabLineFillSébastien Hoffmann2026-10-03
| | | | | | | | | | | | | | | | | | | Problem: the tabline's base highlight that all other highlights inherit from is TabLineFill. Therefore, when only TabLine is customised, one would expect TabLine to inherit unspecified colors/attributes from an unchanged, default TabLineFill. But, in the default theme, TabLine should look exactly like TabLineFill, such that unselected tabs distinguish themselves from the background only by virtue of containing text, which has been solved by linking TabLineFill -> TabLine -> StatusLineNC Therefore, customising TabLine automatically changes TabLineFill, which it inherits from, and both look the same again. Solution: break this circular dependency by linking TabLine -> TabLineFill -> StatusLineNC ref https://github.com/neovim/neovim/issues/41173
* vim-patch:5cbadec: runtime(syntax): Add Regexp default highlight groupzeertzjq2026-10-03
| | | | | | | | | | | Most syntax files currently use String or Normal for highlighting regular expression literals; these should have a dedicated group. closes: vim/vim#21141 https://github.com/vim/vim/commit/5cbadec2e63b0e38c7c1fe4ae9c07b07123299b8 Co-authored-by: Doug Kearns <dougkearns@gmail.com>
* vim-patch:9.1.1568: need a few more default highlight groupszeertzjq2026-10-03
| | | | | | | | | | | | | Problem: need a few more default highlight groups Solution: Add Bold, Italic and BoldItalic default highlight groups (Maxim Kim). related: https://github.com/vim/vim/pull/17598#issuecomment-3007320523 closes: vim/vim#17804 https://github.com/vim/vim/commit/16f7098e68951ce421512c34d03810bdd1efbaed Co-authored-by: Maxim Kim <habamax@gmail.com>
* fix(lint): fix some warnings in clang-tidy 22bfredl2026-09-23
| | | | CI is currently using clang-tidy 21 but prepare for the future
* fix(multicursor): link default MCursor to CurSearch #41900Evgeni Chasnovski2026-09-13
| | | | | | | | | | | | | | | | | | | | | | Problem: When `MCursor` is linked to `Cursor` it is not easy to distinguish the main and extra cursors. Although this is rarely needed when editing (since edit is applied at all of them), it is fairly needed when jumping between the cursors with `[C` / `]C`. Plus different highlighting for main and extra cursor looks (subjectively) more pleasent. Solution: Link `MCursor` by default to `CurSearch`. Linking to an existing group (instead of forcing fixed default attributes) makes the highlighting more readily useful for user color schemes. The `CurSearch` is chosen because: 1. It is semantically close as "something at cursor". This also means that it is not meant to be used for something not at cursor, so highlighting for extra cursors should rarely be confused with something else. 2. It is meant to be visible, usually via visible background. This is also valuable for showing cursors, as it plays nicely when this group is used for coloring extra cursor in Kitty multiple-cursors protocol: cursors in Insert mode are usually thin vertical bars which require a visible color.
* fix(highlight): cterm default for Cursor hlgroupJustin M. Keyes2026-09-02
| | | | | | | | Problem: The `Cursor` highlight is invisible if 'termguicolors' is disabled. Solution: Change its default.
* feat(multicursor): MC HAMMER #41587Justin M. Keyes2026-09-01
| | | | | | | | | | | | | | | | | | | | | Other (squashed) commits: fix(tui): emit ui_send output atomically with the frame Problem: tui_ui_send() writes directly to the TTY, bypassing the output buffer. Sequences sent via nvim_ui_send() (e.g. kitty multiple-cursors, or visual-dot-repeat) always arrive in a separate TTY write from the frame they were computed for. This manifests as "tearing", or e.g. in the case of multicursor the terminal renders text with stale cursor overlays. Solution: - tui_ui_send(): while a frame is being assembled (pending invalid regions or buffered output), buffer instead of writing directly. - Out-of-frame sends (tty queries, clear-on-disable) still write immediately. - mcursor.lua: emit the terminal-cursor update at the end of the redraw cycle (`on_end`, when screen positions are final) instead of vim.schedule().
* fix(ui): too many win_float_pos events for the popupmenu (partial fix)bfredl2026-08-27
| | | | | | | | | | | | | | | | | | | | I got annoyed about so many repeated `win_float_pos` events for the popupmenu. This fixes some of them but not all of them. vibe-less explanation: `need_highlight_changed = true` is very expensive should not be needed when using a window-local highlight namespace. This was only necessary when overriding the global highlight namespace. This can instead be handled by using the correct `hl_attr_active` instead of `highlight_attr`. Also `pum_grid.pending_comp_index_update` can be cleared when using win_float_pos prior to redraw. I wanted to add a test for no repeated win_float_pos event in the same redraw:flush cycle but that requires deeper cleanups, like getting rid of crazy redraw panic intermingled deep into insexpand.c (if "state" is correct, a single update_screen() after the weird multilayer recursive dance should be enough.)
* fix(highlight): explicitly define `TabLineSel` bg/fg #41196Evgeni Chasnovski2026-08-07
| | | | | | | | | | | | | | | | | | | | Problem: `TabLineSel` by default is defined with only bold attribute. This makes selected tabpage stand out relatively well, but when used in custom tabline it will be combined with `TabLineFill` (which is reserved for the "non tabpage" part of the tabline). Plus the behavior is not consistent with the default 'tabline' which combines it with `Normal`. Solution: Explicitly define background and foreground colors to come from `Normal` to ensure the current default 'tabline' behavior even in custom tabline. The more semantically driven solution here is to link `TabLineSel` to `StatusLine`. This makes it more aligned with how `TabLine` is linked to `StatusLineNC`. But the current "bold text with `Normal` colors" is argued to look better as a default. Also make sure that 'notermguicolors' highlighting in default and custom tablines is the same: the current tabpage does not have underline and is not bold.
* fix(highlight): make Ignore hidden by default #41115not_compiled2026-08-04
| | | | | | | | | Problem: Ignore is linked to Normal by default, making the text visible instead of hidden. Solution: Replace the default link with an explicit highlight definition using ctermfg=0 guifg=bg.
* refactor(options): drop OptVal, use ObjectJustin M. Keyes2026-07-29
| | | | | | | | | | | | | Problem: The object subsystem has an intermediate representation for no real reason. Besides the code cost, this also adds an extra (api <=> OptVal) conversion step, which is a (small) perf cost. Solution: We already have `Object`, so use it instead. - drop `OptVal`, `OptValData`, `OptValType`, and related boilerplate. - add `kObjectTypeUnset`.
* vim-patch:9.2.0743: string macros silently accept a size of the wrong type ↵zeertzjq2026-06-29
| | | | | | | | | | | | | | | | | | | | | | | | | | | (#40470) Problem: Several string and memory wrapper macros cast their size argument to size_t although the wrapped function's prototype already declares that parameter size_t; such casts silence the warning a compiler would otherwise give when a value of the wrong type, such as a pointer, is passed as the size. Solution: Where the wrapped function's prototype already declares the parameter size_t, remove the cast so that a size argument of the wrong type can be reported at compile time (K.Takata, Shane Harper). From gcc 14 on, -Wint-conversion is an error by default. With gcc, passing a signed value where size_t is expected triggers -Wsign-conversion, but the check is off by default and the build already emits many such warnings. related: vim/vim#20642 closes: vim/vim#20656 https://github.com/vim/vim/commit/7f122f9effba51adc107909b8ca4d9b220c2bfaf Co-authored-by: Shane Harper <shane@shaneharper.net> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* build: lint "strtol" #40442Justin M. Keyes2026-06-28
| | | | | | | | | | | | | | | | | | Problem: No lint for strtol(). Solution: Add lint, and update existing usages. Callers that previously got a (garbage) large positive value: - `indent.c`: use getdigits() (intmax, no int truncation) with def=1 so overflow/too-large values stay positive and fall through to the existing "too big" check (E475). - `file_search.c`: use getdigits() with def=255 so overflow/too-large values keep the "max expand" (else) branch. The other conversions (api/command.c, eval/window.c, highlight_group.c, tui/tui.c) only diverge on pathological overflow inputs where strtol's result was already garbage and the observable outcome is unchanged.
* fix(api): keep highlight font through set/get and redraws #40200glepnir2026-06-15
| | | | | | | | | | | | Problem: a font set via nvim_set_hl is lost or corrupted with font-only groups, attribute combining, and update=true, and is dropped on any attr-table rebuild. nvim__inspect_cell also frees the font name while a returned dict still borrows it. Solution: register font-only groups, carry font through hl_combine_attr, inherit it on update, and persist sg_font so a rebuild can restore it. Keep interned font names across a rebuild instead of clearing them. Add the missing font field to get_hl_info. Co-authored-by: Ryan Patterson <cgamesplay@cgamesplay.com>
* feat(highlights): new Dimmed hl group for de-emphasized text #39505Michele Campeotto2026-05-13
| | | | | | | | | | | | | Problem: Many color schemes assume the Comment hl group is dim text and use it for secondary text, decorations, or parts of UI. This is true for many color schemes but not all. Solution: Introducing a new highlight group with a more specific meaning, similar to Underlined or Ignore. The new group links to Comment by default so the behavior is unchanged for color schemes that don't define it.
* fix(style): some clang-tidy 22 fixesbfredl2026-05-11
| | | | | | | | | | | | | | | | | | | | | | CI currently uses clang-tidy 20, but this affects local builds and CI is going to be upgraded sooner or later. Some remaining systematic issues: - clang-tidy warns agains any atoi() or atol() usage (because of no error handling) - functions which takes (char *fmt, char *only_string_arg) and expect fmt to contain exactly one "%s" usage. - error: initializing non-local variable with non-const expression depending on uninitialized non-local variable (cppcoreguidelines-interfaces-global-init) This is a much worse problem in C++ (hence C++ core guidelines) where initialization is intermingled with arbitrary code execution. I "think" in plain C, the linker will either resolve all these deterministically or barf an error. But with some restructuring we could make all static initialization actually static..
* build: update clang v21, fix warningsdundargoc2026-04-14
| | | | | - `src/nvim/ex_cmds_defs.h`: use "U" instead of "u" per `readability-uppercase-literal-suffix`
* feat(api): nvim_set_hl can set "font" #37668glepnir2026-04-12
| | | | | | Problem: Cannot set highlight group fonts via API, only via :highlight command. Solution: Add font parameter in nvim_set_hl().
* fix(api): nvim_get_hl drops groups defined with link_global #38492glepnir2026-04-12
| | | | | | | | | Problem: hlgroup2dict passes &ns_id to ns_get_hl twice. The first call (link=true) sets *ns_hl = 0 when link_global is set, so the second call and the sg_cleared guard both see ns_id == 0 and bail out. The group is silently dropped from the result. Solution: use a temporary copy of ns_id for each ns_get_hl call so the original value is preserved.
* fix(highlight): preserve inherited colors when update=true breaks links #38750glepnir2026-04-11
| | | | | | | Problem: Breaking a link with update=true loses colors inherited from the linked group. Solution: Copy color indices from the linked group so inherited colors remain visible in :hi output.
* feat(api): nvim_set_hl{update:boolean} #37546glepnir2026-03-25
| | | | | | | Problem: nvim_set_hl always replaces all attributes. Solution: Add update field. When true, merge with existing attributes instead of replacing. Unspecified attributes are preserved. If highlight group doesn't exist, falls back to reset mode.
* refactor(highlight): extract set_gui_color() from do_highlight()glepnir2026-03-12
| | | | | | | Problem: GUIFG, GUIBG, GUISP handling in do_highlight() is basically the same code copy-pasted three times. Solution: Pull the shared logic into a small set_gui_color() helper.
* fix(highlight): correct change detection in do_highlight for gui colorsglepnir2026-03-12
| | | | | | | | | Problem: The GUIFG/GUIBG/GUISP handlers compare sg_rgb_{fg,bg,sp} (RgbValue) against old_idx (color table index) instead of comparing sg_rgb_{fg,bg,sp}_idx against old_idx, making did_change unreliable. Solution: Use the _idx field for the index comparison and add the missing sg_rgb_sp_idx assignment.
* feat(highlight): support more SGR attributes #37901Riccardo Mazzarini2026-02-20
| | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: TUI does not support several standard SGR text attributes: - dim/faint (SGR 2) - blink (SGR 5) - conceal (SGR 8) - overline (SGR 53) This means that when a program running in the embedded terminal emits one of these escape codes, we drop it and don't surface it to the outer terminal. Solution: - Add support for those attributes. - Also add corresponding flags to `nvim_set_hl` opts, so users can set these attributes in highlight groups. - refactor(highlight): widen `HlAttrFlags` from `int16_t` to `int32_t` Widen the `rgb_ae_attr` and `cterm_ae_attr` fields in HlAttrs from int16_t to int32_t to make room for new highlight attribute flags, since there was only one spare bit left. - The C flag is named HL_CONCEALED to avoid colliding with the existing HL_CONCEAL in syntax.h (which is a syntax group flag, not an SGR attribute). - Also note that libvterm doesn't currently support the dim and overline attributes, so e.g. `printf '\e[2mThis should be dim\n'` and `printf '\e[53mThis should have an overline\n'` are still not rendered correctly when run from the embedded terminal.
* fix(highlight): link HLF_8 to something more prominent #34910Justin M. Keyes2026-02-14
| | | | | | | | | | | | Problem: HLF_8 is used by :intro and :map. And none of the other HLF_x things use the other Special groups. So we have a darkgray highlight that's very common, and not easy to read. Darkgray makes sense for "Conceal", "non-printing chars", etc. But not for keycodes or similar common elements. Solution: Link SpecialKey to Special.
* fix(messages): unwanted newlines with ext_messages #37733luukvbaal2026-02-08
| | | | | | | | | | | | | | | Problem: Newlines intended to write messages below the cmdline or to mark the start of a new message on message grid are emitted through ext_messages. This results in unnecessary newlines for a UI that has decoupled its message area from the cmdline. msg_col is set directly in some places which is not transmitted to msg_show events. Various missing message kind for list commands. Trailing newlines on various list commands. Solution: Only emit such newlines without ext_messages enabled. Use msg_advance() instead of setting msg_col directly. Assign them the "list_cmd" kind. Ensure no trailing newline is printed.
* fix(pum): pumborder=shadow not blending properly (#37328)zeertzjq2026-01-09
| | | | | Problem: Setting pumborder=shadow doesn't blend proerly. Solution: Check fconfig.shadow when setting pum_grid.blending, like what is done in check_blending().
* test(messages): skip os_delay during testsJustin M. Keyes2025-12-20
| | | | | | | | | | | Problem: Tests that trigger `os_delay` messages may take 1-3 seconds, wasting build/CI time, since this serves no purpose in tests. Solution: - Introduce `msg_delay` for cases where `os_delay` is being used as a "UI feature". - Skip `msg_delay` in tests.
* fix(colorscheme): adjust `StatusLine[NC]` for diagnostics #36719Evgeni Chasnovski2025-11-29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: It is desirable for the default statusline to contain colored diagnostics information. However, current `StatusLine` group is purposefully defined as almost inverted `Normal` to "make current window obvious". This makes diagnostic information from `vim.diagnostic.status()` barely visible: it uses established `DiagnosticSignXxx` groups which have colored foreground with lightness close to `StatusLine` background. Also the `StatusLineNC` group is fairly different from `Normal` in order to both "makes window separators clear" and "be different from `CursorLine`". But not as mush different as `StatusLine` because "`StatusLine` and `StatusLineNC` should be clearly different". Solution: Make both `StatusLine` and `StatusLineNC` be slightly closer in lightness to `Normal`. This makes `StatusLine` and `StatusLineNC` groups satisfy their conditions in the following way: - `vim.diagnostic.count()` is readable on `StatusLine` - yes. - `vim.diagnostic.count()` is readable on `StatusLineNC` - yes. - `StatusLine` makes current window obvious - I'd say yes. - `StatusLine` and `StatusLineNC` are clearly different - it depends on the eyes and monitor. The current is clearly better, but the new ones I'd say are still visibly different. - `StatusLineNC` makes window separators clear - I'd say yes, but depends on the eyes and monitor. - `StatuslineNC` is different from `CursorLine` - NO, they are same. Another approach to solve this would be to introduce dedicated `DiagnosticStatuslineXxx` groups to use in `vim.diagnostics.status()`. They can be defined using foreground colors from the same lightness as `Normal`. This would make them readable in `StatusLine`. But not `StatusLineNC`, though.
* feat(ui): overlay scrollbar on 'pumborder' #36273glepnir2025-10-23
| | | | | | | Problem: When pumborder is set, the scrollbar still occupies a column on the screen, wasting a 1 column of space. Solution: Render the scrollbar on the right/left (rl mode) side of the border when pumborder is set.
* feat(ui): 'pumborder' (popup menu border) #25541glepnir2025-10-10
| | | | | | | | | Problem: Popup menu cannot have a border. Solution: Support 'pumborder' option. Generalize `win_redr_border` to `grid_redr_border`, which redraws border for window grid and pum grid.
* vim-patch:9.1.1742: complete: preinsert does not work well with ↵zeertzjq2025-09-09
| | | | | | | | | | | | | | | | | | | | 'autocomplete' (#35692) Problem: complete: preinsert does not work well with preinsert Solution: Make "preinsert" completeopt value work with autocompletion (Girish Palya) This change extends Insert mode autocompletion so that 'preinsert' also works when 'autocomplete' is enabled. Try: `:set ac cot=preinsert` See `:help 'cot'` for more details. closes: vim/vim#18213 https://github.com/vim/vim/commit/fa6fd41a943e6442c1a2ce6b0a237298b00ecca0 Co-authored-by: Girish Palya <girishji@gmail.com>
* feat(progress): better default format + history sync #35533Shadman2025-09-01
| | | | | | | | | | | Problem: The default progress message doesn't account for message-status. Also, the title and percent sections don't get written to history. And progress percent is hard to find with variable length messages. Solution: Apply highlighting on Title based on status. And sync the formated msg in history too. Also updates the default progress message format to {title}: {percent}% msg
* feat(lsp): support `textDocument/inlineCompletion`Yi Ming2025-08-25
|
* feat(snippet): highlight active tabstop (#35378)TheBlob422025-08-19
|
* refactor(build): remove INCLUDE_GENERATED_DECLARATIONS guardsbfredl2025-08-14
| | | | | | | | | These are not needed after #35129 but making uncrustify still play nice with them was a bit tricky. Unfortunately `uncrustify --update-config-with-doc` breaks strings with backslashes. This issue has been reported upstream, and in the meanwhile auto-update on every single run has been disabled.
* feat(messages): hl-StderrMsg, hl-StdoutMsg #33429Sathya Pramodh2025-05-02
| | | | | | | | | Problem: stderr messages from executing ":!cmd" show up with highlight hl-ErrorMsg. But some shell utilites use stderr for debug logging, progress updates, etc. Solution: Highlight shell command outputs hl-StderrMsg and hl-StdoutMsg.
* vim-patch:9.1.1243: diff mode is lacking for changes within lineszeertzjq2025-03-28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Diff mode's inline highlighting is lackluster. It only performs a line-by-line comparison, and calculates a single shortest range within a line that could encompass all the changes. In lines with multiple changes, or those that span multiple lines, this approach tends to end up highlighting much more than necessary. Solution: Implement new inline highlighting modes by doing per-character or per-word diff within the diff block, and highlight only the relevant parts, add "inline:simple" to the defaults (which is the old behaviour) This change introduces a new diffopt option "inline:<type>". Setting to "none" will disable all inline highlighting, "simple" (the default) will use the old behavior, "char" / "word" will perform a character/word-wise diff of the texts within each diff block and only highlight the differences. The new char/word inline diff only use the internal xdiff, and will respect diff options such as algorithm choice, icase, and misc iwhite options. indent-heuristics is always on to perform better sliding. For character highlight, a post-process of the diff results is first applied before we show the highlight. This is because a naive diff will create a result with a lot of small diff chunks and gaps, due to the repetitive nature of individual characters. The post-process is a heuristic-based refinement that attempts to merge adjacent diff blocks if they are separated by a short gap (1-3 characters), and can be further tuned in the future for better results. This process results in more characters than necessary being highlighted but overall less visual noise. For word highlight, always use first buffer's iskeyword definition. Otherwise if each buffer has different iskeyword settings we would not be able to group words properly. The char/word diffing is always per-diff block, not per line, meaning that changes that span multiple lines will show up correctly. Added/removed newlines are not shown by default, but if the user has 'list' set (with "eol" listchar defined), the eol character will be be highlighted correctly for the specific newline characters. Also, add a new "DiffTextAdd" highlight group linked to "DiffText" by default. It allows color schemes to use different colors for texts that have been added within a line versus modified. This doesn't interact with linematch perfectly currently. The linematch feature splits up diff blocks into multiple smaller blocks for better visual matching, which makes inline highlight less useful especially for multi-line change (e.g. a line is broken into two lines). This could be addressed in the future. As a side change, this also removes the bounds checking introduced to diff_read() as they were added to mask existing logic bugs that were properly fixed in vim/vim#16768. closes: vim/vim#16881 https://github.com/vim/vim/commit/9943d4790e42721a6777da9e12637aa595ba4965 Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
* fix(colorscheme): distinguish CursorLine/Folded/StatusLineNC highlights #32256Evgeni Chasnovski2025-01-30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: currently `CursorLine`, `Folded`, `StatusLineNC` highlight groups have the same background color in default color scheme (Grey3). This is a result of optimizing their highlighting to be different from `Normal` but not draw too much attention. However, this design has a usability issue as those groups are sometimes appear together which can make it hard (but not impossible) to differentiate between them. This was previously partially resolved with `StatusLineNC` using Grey1 as background (and thus be different from `CursorLine` but closer to `Normal`), but optimizing more towards it being a visible separator between windows was decided to be more important. Solution: make `Folded` use Grey1 and `StatusLineNC` use Grey4. This makes all three highlight groups have different backgrounds with the following consequences: - Folds now have the same background as floating windows. It makes them there differentiable only by the value of 'foldtext' (which is usually enough). Optimizing for the case "cursor line is next to the fold" seems to be more useful than for the case "make folds in floating window differ by background". - Statusline of inactive windows now draw more attention to them. The benefits are that they are different from cursor column and are better window separators. - Inactive tabline (both `TabLine` and `TabLineFill`) now also draws a bit more attention to it (as they are linked to `StatusLineNC`) but with the benefit of also being different from `CursorLine`.
* feat(diagnostic): virtual_lines #31959Maria José Solano2025-01-26
|
* fix(highlight): make TablineSel more noticeable with 'notermguicolors' #31905Evgeni Chasnovski2025-01-07
| | | | | | | | Problem: Linking `TablineSel` to `Normal` makes it more noticeable with `notermguicolors` but less so with `termguicolors` (compared to using bold text in both cases). Solution: use bold text with `termguicolors` and regular with `notermguicolors`.
* fix(highlight): make `TablineSel` more noticeable #31896Jared Baur2025-01-07
| | | | The default `TablineSel` highlighting makes it subjectively difficult to differentiate the selected tab from unselected ones.
* refactor: iwyu #31637Justin M. Keyes2024-12-23
| | | Result of `make iwyu` (after some "fixups").
* fix(messages): better formatting for :highlight with ext_messages #31627luukvbaal2024-12-19
| | | Also avoid going down message callstack with empty message, and remove expected grid for some tests where it did not change, and we are just testing for expected messages.
* vim-patch:9.1.0945: ComplMatchIns highlight doesn't end after inserted text ↵zeertzjq2024-12-18
| | | | | | | | |