I want to use certain settings for the built-in TUI frontend, and other settings in other GUI frontends like Neovide.
GUI frontends usually (but don’t always) source ginit
, so the simple solution is to set my TUI colorscheme in init.vim
/init.lua
and then my GUI colorscheme in ginit.vim
.
However it would be nice to avoid running my TUI-specific setup code entirely when not connecting to a TUI, because I have some other settings (such as cursorline) that I like to set differently. Also, a few frontends (notably VimR) don’t use ginit.vim
.
Is there a reliable way to do this? The best guess I’ve had so far is to get v:event.chan
within a UIEnter
autocommand and use it to inspect the output of nvim_list_chans()
for the current UI channel. Here’s what I put together so far:
let g:term_color =
\ local#utils#isin($TERMCOLOR, ['light', 'dark'])
\ ? $TERMCOLOR
\ : 'dark'
let g:tui_color_schemes = {'light': 'dim', 'dark': 'dim'}
let g:gui_color_scheme = 'catppuccin-frappe'
function s:ui_setup_colors() abort
try
let l:event_chan = v:event.chan
catch /^Vim\%((\a\+)\)\=:E716:/
echomsg 'init-extra.vim:s:ui_setup_colors() was called outside of a UIEnter event. Aborting.'
return
endtry
try
let l:current_chan = filter(nvim_list_chans(), {_, x -> x.id == l:event_chan})[0]
let l:current_ui = filter(nvim_list_uis(), {_, x -> x.chan == l:event_chan})[0]
catch /^Vim\%((\a\+)\)\=:E684:/
echomsg printf('Channel or UI with event chan ID of %s is missing; something went wrong. Aborting.', l:event_chan)
endtry
echo l:current_chan
echo l:current_ui
let l:is_tui = empty(l:current_chan.client)
if l:is_tui
let &background = g:term_color
let l:colorscheme = g:tui_color_schemes[g:term_color]
echomsg printf('TUI detected, setting colorscheme "%s".', l:colorscheme)
try
call nvim_cmd(#{cmd: 'colorscheme', args: [l:colorscheme]}, {})
catch /Vim\%((\a\+)\)\=:E185:/
echomsg printf('Color scheme "%s" is not available.', l:colorscheme)
endtry
else
let l:colorscheme = g:gui_color_scheme
echomsg printf('GUI detected, setting colorscheme "%s".', l:colorscheme)
try
call nvim_cmd(#{cmd: 'colorscheme', args: [l:colorscheme]}, {})
catch /Vim\%((\a\+)\)\=:E185:/
echomsg printf('Color scheme "%s" is not available.', l:colorscheme)
endtry
endif
endfunction
augroup vimrc_init
autocmd UIEnter * call s:ui_setup_colors()
augroup END
This works for Neovide and FVim, but not for Neovim-Qt. It seems like the l:current_chan
for Neovim-Qt at the time UIEnter
is triggered has an empty .client
attribute, which is only filled some time after UIEnter
is triggered but before (or immediately after) the UI appears, so the TUI settings get applied when Neovim-Qt is starting up.
Is this a bug or behavioral deficiency in Neovim-Qt specifically? Or am I just doing it wrong? I can work around it by calling this function in ginit.vim
, which Neovim-Qt seems to run after UIEnter
(whereas Neovide and FVim seem to run ginit.vim
it before UIEnter
).