From d5a8c9d7666796311abb55f30afd53c1eb8d8c1b Mon Sep 17 00:00:00 2001 From: glepnir Date: Wed, 11 Feb 2026 12:18:07 +0800 Subject: [PATCH 1/2] fix(highlight): correct change detection in do_highlight for gui colors 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. --- src/nvim/highlight_group.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index c731cf4cdc..e726538c73 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1418,7 +1418,8 @@ void do_highlight(const char *line, const bool forceit, const bool init) hl_table[idx].sg_rgb_fg_idx = kColorIdxNone; } - did_change = hl_table[idx].sg_rgb_fg != old_color || hl_table[idx].sg_rgb_fg != old_idx; + did_change = hl_table[idx].sg_rgb_fg != old_color + || hl_table[idx].sg_rgb_fg_idx != old_idx; } if (is_normal_group) { @@ -1442,7 +1443,8 @@ void do_highlight(const char *line, const bool forceit, const bool init) hl_table[idx].sg_rgb_bg_idx = kColorIdxNone; } - did_change = hl_table[idx].sg_rgb_bg != old_color || hl_table[idx].sg_rgb_bg != old_idx; + did_change = hl_table[idx].sg_rgb_bg != old_color + || hl_table[idx].sg_rgb_bg_idx != old_idx; } if (is_normal_group) { @@ -1463,9 +1465,11 @@ void do_highlight(const char *line, const bool forceit, const bool init) hl_table[idx].sg_rgb_sp = name_to_color(arg, indexp); } else { hl_table[idx].sg_rgb_sp = -1; + hl_table[idx].sg_rgb_sp_idx = kColorIdxNone; } - did_change = hl_table[idx].sg_rgb_sp != old_color || hl_table[idx].sg_rgb_sp != old_idx; + did_change = hl_table[idx].sg_rgb_sp != old_color + || hl_table[idx].sg_rgb_sp_idx != old_idx; } if (is_normal_group) { From d7903982ae54f45429b22c7cb6a768807865102b Mon Sep 17 00:00:00 2001 From: glepnir Date: Thu, 12 Mar 2026 14:25:01 +0800 Subject: [PATCH 2/2] refactor(highlight): extract set_gui_color() from do_highlight() 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. --- src/nvim/highlight_group.c | 88 +++++++++++--------------------------- 1 file changed, 25 insertions(+), 63 deletions(-) diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index e726538c73..b26b485ccd 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1004,6 +1004,25 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id) need_highlight_changed = true; } +static bool set_gui_color(int idx, bool init, const char *arg, RgbValue *color, int *color_idx) +{ + if (init && (hl_table[idx].sg_set & SG_GUI)) { + return false; + } + if (!init) { + hl_table[idx].sg_set |= SG_GUI; + } + RgbValue old_color = *color; + int old_idx = *color_idx; + if (strcmp(arg, "NONE") != 0) { + *color = name_to_color(arg, color_idx); + } else { + *color = -1; + *color_idx = kColorIdxNone; + } + return *color != old_color || *color_idx != old_idx; +} + /// Handle ":highlight" command /// /// When using ":highlight clear" this is called recursively for each group with @@ -1401,77 +1420,20 @@ void do_highlight(const char *line, const bool forceit, const bool init) } } } else if (strcmp(key, "GUIFG") == 0) { - int *indexp = &hl_table[idx].sg_rgb_fg_idx; - - if (!init || !(hl_table[idx].sg_set & SG_GUI)) { - if (!init) { - hl_table[idx].sg_set |= SG_GUI; - } - - RgbValue old_color = hl_table[idx].sg_rgb_fg; - int old_idx = hl_table[idx].sg_rgb_fg_idx; - - if (strcmp(arg, "NONE") != 0) { - hl_table[idx].sg_rgb_fg = name_to_color(arg, indexp); - } else { - hl_table[idx].sg_rgb_fg = -1; - hl_table[idx].sg_rgb_fg_idx = kColorIdxNone; - } - - did_change = hl_table[idx].sg_rgb_fg != old_color - || hl_table[idx].sg_rgb_fg_idx != old_idx; - } - + did_change = set_gui_color(idx, init, arg, &hl_table[idx].sg_rgb_fg, + &hl_table[idx].sg_rgb_fg_idx); if (is_normal_group) { normal_fg = hl_table[idx].sg_rgb_fg; } } else if (strcmp(key, "GUIBG") == 0) { - int *indexp = &hl_table[idx].sg_rgb_bg_idx; - - if (!init || !(hl_table[idx].sg_set & SG_GUI)) { - if (!init) { - hl_table[idx].sg_set |= SG_GUI; - } - - RgbValue old_color = hl_table[idx].sg_rgb_bg; - int old_idx = hl_table[idx].sg_rgb_bg_idx; - - if (strcmp(arg, "NONE") != 0) { - hl_table[idx].sg_rgb_bg = name_to_color(arg, indexp); - } else { - hl_table[idx].sg_rgb_bg = -1; - hl_table[idx].sg_rgb_bg_idx = kColorIdxNone; - } - - did_change = hl_table[idx].sg_rgb_bg != old_color - || hl_table[idx].sg_rgb_bg_idx != old_idx; - } - + did_change = set_gui_color(idx, init, arg, &hl_table[idx].sg_rgb_bg, + &hl_table[idx].sg_rgb_bg_idx); if (is_normal_group) { normal_bg = hl_table[idx].sg_rgb_bg; } } else if (strcmp(key, "GUISP") == 0) { - int *indexp = &hl_table[idx].sg_rgb_sp_idx; - - if (!init || !(hl_table[idx].sg_set & SG_GUI)) { - if (!init) { - hl_table[idx].sg_set |= SG_GUI; - } - - RgbValue old_color = hl_table[idx].sg_rgb_sp; - int old_idx = hl_table[idx].sg_rgb_sp_idx; - - if (strcmp(arg, "NONE") != 0) { - hl_table[idx].sg_rgb_sp = name_to_color(arg, indexp); - } else { - hl_table[idx].sg_rgb_sp = -1; - hl_table[idx].sg_rgb_sp_idx = kColorIdxNone; - } - - did_change = hl_table[idx].sg_rgb_sp != old_color - || hl_table[idx].sg_rgb_sp_idx != old_idx; - } - + did_change = set_gui_color(idx, init, arg, &hl_table[idx].sg_rgb_sp, + &hl_table[idx].sg_rgb_sp_idx); if (is_normal_group) { normal_sp = hl_table[idx].sg_rgb_sp; }