vifm / vifm.vim

Vim plugin that allows use of vifm as a file picker
325 stars 18 forks source link

vifm plugin and 24-bit color support #88

Closed hombrey closed 1 year ago

hombrey commented 1 year ago

I use vifm both as my primary o/s-level file manager in Arch Linux and as my file picker within neovim. I've been living with a bug since 24-bit color support has been introduced in vifm.

I know that I can get 24-bit colors when I use a terminal that that has *-direct as its $TERM value. I do indeed get to enjoy the richer color palette whenever I use vifm inside a terminal that supports this feature.

A problem pops up though when I use the same terminal within neovim and invoke the vifm plugin. Instead of getting either the gui or the cterm colors in the defined color scheme, it seems to use its own colors - mostly in the shades of blue.

Vifm in nvim, bad colors

To work around this problem, I could do either of the following:

  1. reassign $TERM so that vifm only uses 256 colors (both in the o/s and in neovim).
  2. keep using *-direct in $TERM so I can keep 24-bit colors at the o/s level but define a different colorscheme for vifm within neovim. In this special colorscheme for the plugin, the only cterm color values that I can use are "Black", "Red", "Green", "Yellow", "Blue", "Magenta", "Cyan", "White", and "none". Using either #nnnnnn for gui or nnn for cterm don't work.

I use neovim/vifm within tmux and use st as my terminal. I can also replicate this issue when I try Konsole with $TERM set to "konsole-direct".

Does anyone else get this same problem?

xaizek commented 1 year ago

when I use the same terminal within neovim

You don't. When you're using a terminal buffer (if it's called that way in neovim), the shell and all apps in it are running in a separate terminal managed by libvterm inside neovim, which then draws its current content on the actual terminal emulator that was used to start neovim.

If inside that session $TERM is set to something like st-direct, you're lying to the applications about their environment and weird things can happen. Try using xterm-direct and maybe it will work (libvterm is xterm-like), in Vim I get a lot of red color instead, but 24-bit colors kinda work. It's all about that embedded terminal, what it supports and how colors are handled by host application (neovim in this case).

hombrey commented 1 year ago

My bad. I didn't mean to say that I launched vifm within the terminal buffer inside neovim.

CORRECTION: ... when I use the same terminal with neovim ...

Anyway, I was able to confirm that the problem I see just occurs in neovim. Vim seems to work fine for me with either color depth.

Defining TERM as xterm-direct in st but outside a tmux session for neovim gives me something else but does seem usable.

Here is a rundown of different permutations that I've tried and the resulting colors in vifm:

st -> tmux -> vifm
($TERM = st-direct) ($TERM = tmux-256color) (colors=cterm)
st -> tmux -> neovim -> vifm plugin
($TERM = st-direct) ($TERM = tmux-256color) (colors=cterm)
st -> tmux -> vim -> vifm plugin
($TERM = st-direct) ($TERM = tmux-256color (colors=cterm)
st -> tmux -> vifm
($TERM = st-direct) ($TERM = tmux-direct) (colors=gui)
st -> tmux -> vifm
($TERM = st-direct) ($TERM = xterm-direct) (colors=gui)
st -> tmux -> neovim -> vifm plugin
($TERM = st-direct) ($TERM = xterm-direct) (colors=blue)
st -> tmux -> neovim -> vifm plugin
($TERM = st-direct) ($TERM = tmux-direct) (colors=blue)
st -> tmux -> vim -> vifm plugin
($TERM = st-direct) ($TERM = tmux-direct) (colors=gui)
st -> neovim -> vifm plugin
($TERM = st-direct) (colors=blue)
st -> neovim -> vifm plugin
($TERM = xterm-direct) (colors=monochrome)
st -> vifm
($TERM = xterm-direct) (colors=monochrome)
st -> vim -> vifm plugin
($TERM = st-direct) (colors=gui)
st -> neovim -> vifm plugin
($TERM=xterm-256color) (colors=cterm)
st -> vim -> vifm plugin
($TERM=xterm-256color) (colors=cterm)
alacritty or konsole -> neovim -> vifm plugin
($TERM = *-direct) (colors=blue)
alacritty or konsole -> neovim -> vifm plugin
($TERM = *-256color) (colors=cterm)
xaizek commented 1 year ago

My bad. I didn't mean to say that I launched vifm within the terminal buffer inside neovim.

But that's what vifm.vim does to run vifm command in neovim (in Vim :!vifm can also be used), just implicitly. So my comment still applies.

Defining TERM as xterm-direct in st but outside a tmux session for neovim gives me something else but does seem usable.

That's accidental. st-direct and tmux-direct are correct $TERM values for outside and inside tmux respectively.

What's more important is the $TERM value Vifm gets when it's run. I meant that this one should be xterm-direct. See information at the bottom of :version menu in Vifm (it should be copyable even if invisible). You can try comparing that information in Vim/neovim. Running :let $TERM = "xterm-direct" in neovim might affect this $TERM value.

hombrey commented 1 year ago

These are the terminal names I get from :version when used in an st terminal (no tmux) with $TERM = "st-direct"

Terminal name
vifm st-direct
vim -> vifm st-direct
nvim -> vifm xterm-256color

Unlike in vim, running :let $TERM = "xterm-direct" in neovim does not change vifm's terminal name.

Just in case it might be useful, here is the rest of the text from :version

Version: 0.12.1 Git info: built out of repository Compiled at: Sep 27 2022 18:26:07

Support of extended keys is on Parsing of .desktop files is enabled Without GTK+ library With magic library Without X11 library Without dynamic loading of X11 library With file program With -n option for cp and mv With remote command execution

xaizek commented 1 year ago

Looks like neovim deliberately doesn't let one set TERM in this case (the value is ignored by termopen()) and yet direct colors are probably supported there. Try using this workaround:

:let g:vifm_exec = 'TERM=xterm-direct vifm'
hombrey commented 1 year ago

That command did work! The :version command now shows the value of TERM defined by this workaround. I think it now tries to use gui colors but with a reddish tint.

xaizek commented 1 year ago

It seems that libvterm doesn't use the same format of RGB escape-sequences as xterm, but matches that of st. Here's a workaround:

  1. Create a file containing:
    libvterm-direct| libvterm with direct colors,
    use=xterm-direct,
    setab=\E[%?%p1%{8}%<%t4%p1%d%e48;2;%p1%{65536}%/%d;%p1%{256}%/%{255}%&%d;%p1%{255}%&%d%;m,
    setaf=\E[%?%p1%{8}%<%t3%p1%d%e38;2;%p1%{65536}%/%d;%p1%{256}%/%{255}%&%d;%p1%{255}%&%d%;m,
  2. Run tic on that file (e.g., tic -s libvterm-direct.info).

This adds a new terminfo entry to your ~/.terminfo based on xterm-direct but with setab and setaf taken from st-direct. Using that in g:vifm_exec (:let g:vifm_exec = 'TERM=libvterm-direct vifm') seems to make it work.

libvterm should probably start accepting codes compatible with xterm and neovim shouldn't hard-code xterm-256color. Until then, a workaround like this is necessary. Using st-direct also works, but it has many differences from xterm-256color (infocmp st-direct xterm-256color), so making a separate entry should be less fragile.

hombrey commented 1 year ago

Great! This does fix the colors in my system. I've tried it in st, tmux, Konsole, alacritty, and lxterminal. Thanks!