Tabby 颜色异常的根因并非 Tokyonight 覆盖了高亮,而是 Tabby 在 VimEnter 阶段与 ColorScheme 存在启动时序竞争,导致偶发错过 ColorScheme 事件而未正确刷新动态高亮组(TabbyHL_xxx),将 Tabby 延迟到 VeryLazy 加载后即可彻底规避该问题。

Tabby 偶发渲染异常

问题现象

Neovim 启动后,Tabby 偶发出现颜色渲染异常。 Tabby高亮颜色异常

相关 Profile 信息如下:

VimEnter
├── tabby.nvim      3.33ms
└── tokyonight.nvim 3.21ms

特点:

  • 并非每次启动都能复现
  • 手动执行 :colorscheme tokyonight 后立即恢复正常
  • 调整为 VeryLazy 加载后问题消失

第一阶段:检查 TabLine 高亮

最初怀疑是 Tokyonight 与 Tabby 的高亮覆盖问题。

查看高亮组:

:hi TabLine
:hi TabLineSel
:hi TabLineFill

异常状态

TabLine     xxx guifg=#3b4261 guibg=#1e2030
TabLineFill xxx guibg=#1b1d2b
TabLineSel  xxx guifg=#1b1d2b guibg=#82aaff

正常状态

TabLine     xxx guifg=#3b4261 guibg=#1e2030
TabLineFill xxx guibg=#1b1d2b
TabLineSel  xxx guifg=#1b1d2b guibg=#82aaff

结果发现:

TabLine
TabLineFill
TabLineSel

在正常和异常状态下完全一致。

因此排除:

TabLine 高亮被 Tokyonight 覆盖

的可能性。

第二阶段:检查 Tabby 动态高亮

进一步查看 Tabby 自己生成的高亮组:

:filter Tabby hi

异常状态

TabbyHL_5198424_5198424_NONE xxx cleared
TabbyHL_NONE_5198424_NONE xxx cleared

正常状态

TabbyHL_1447454_1381918_NONE xxx guifg=#16161e guibg=#15161e
TabbyHL_8037111_1381918_NONE xxx guifg=#7aa2f7 guibg=#15161e

此时发现:

异常时:

TabbyHL_* -> cleared

正常时:

TabbyHL_* -> 正常存在

说明问题并不在:

TabLine

而在:

Tabby 动态生成的高亮组

上。

第三阶段:验证 ColorScheme 的影响

当异常出现时,执行:

:colorscheme tokyonight

结果:

Tabby 立即恢复正常

这是整个排查过程中最关键的线索。

排除的错误结论

最开始曾怀疑:

Tokyonight 执行 ColorScheme
清理了 TabbyHL
Tabby 没有重新生成
导致异常

但这个推断与实际现象矛盾。

因为如果真是这样:

:colorscheme tokyonight

应该会再次清理 TabbyHL。

实际结果却是:

执行 ColorScheme 后恢复正常

因此该推断不成立。

最终原因分析

更符合实际情况的流程应该是:

正常启动

Tokyonight
ColorScheme
Tabby ColorScheme Handler
重建 TabbyHL_*
显示正常

异常启动

Tabby Setup
Tokyonight ColorScheme 已触发
Tabby 才完成初始化
Tabby 错过本次 ColorScheme
TabbyHL 未刷新
显示异常

或者:

Tabby Setup
ColorScheme

两者发生竞争条件(Race Condition)。

由于启动时:

tabby.nvim
tokyonight.nvim

都位于 VimEnter 阶段。

再加上插件内部可能存在:

vim.schedule(...)

异步逻辑,因此会出现时序漂移。

最终导致:

Tabby 偶发错过启动阶段唯一一次 ColorScheme 事件

从而无法正确刷新动态高亮组。

最终解决方案

将 Tabby 从:

event = "VimEnter"

调整为:

event = "VeryLazy"

例如:

{
    "nanozuki/tabby.nvim",
    event = "VeryLazy",
}

问题彻底消失。

为什么 VeryLazy 能解决问题

原始启动流程:

VimEnter
├── tabby
└── tokyonight

存在如下竞争关系:

Tabby Setup
ColorScheme

导致:

Tabby 可能错过 ColorScheme

调整后的流程:

VimEnter
tokyonight
ColorScheme
主题初始化完成
VeryLazy
Tabby Setup

此时:

主题状态已经稳定

Tabby 不再依赖启动阶段的 ColorScheme 回调。

而是直接基于最终主题状态生成:

TabbyHL_*

因此彻底规避了启动竞态问题。

最终结论

本次问题并非:

Tokyonight 覆盖了 TabLine 高亮

也并非:

Tokyonight 清理了 TabbyHL 且未重建

真正的根因是:

Tabby 依赖 ColorScheme 事件刷新动态高亮组

而在原有配置下:

tabby.nvim
tokyonight.nvim

同时位于 VimEnter 阶段。

启动过程中存在时序竞争,导致 Tabby 偶发错过启动时的 ColorScheme 事件,从而无法正确刷新动态高亮组。

具体表现为:

TabLine 正常
TabbyHL_* 状态异常
Tabby 颜色渲染错误

将 Tabby 延迟至:

event = "VeryLazy"

加载后,主题已经完成初始化,Tabby 能直接基于最终主题状态创建动态高亮组,因此问题得到彻底解决。

推荐配置

Tokyonight:

{
    "folke/tokyonight.nvim",
    lazy = false,
    priority = 1000,
    config = function()
        vim.cmd.colorscheme("tokyonight")
    end,
}

Tabby:

{
    "nanozuki/tabby.nvim",
    event = "VeryLazy",
}

推荐遵循如下加载顺序:

Colorscheme
Statusline
Tabline
Winbar

这种加载方式对于 Tabby、Lualine、Bufferline、Heirline 等 UI 类插件通常最稳定。