itchyny / lightline.vim

A light and configurable statusline/tabline plugin for Vim
MIT License
6.77k stars 316 forks source link

Custom colorscheme mode #667

Closed Svalorzen closed 9 months ago

Svalorzen commented 9 months ago

First of all, absolutely great plugin.

I'm looking to add a colorscheme mode that can be recognized through a function; i.e. ideally one could create a function that returns the current mode, which defaults to the standard ones lightline provides, but could also return something else.

In particular, I often use Fugitive with the preview window; and I'd really love to give lightline a different (and permanent through inactivity) look to it. The preview window can be identified via the previewwindow boolean, so ideally I could set its window mode to always be "preview", and then in the colorscheme I'd have p.preview.left = and so on and so forth.

I have looked a bit in the code, and while most statuses seems to be taken directly from mode(), inactive for example is determined separately in lightline#update() via winnr(), so it can't be checked directly. Perhaps there one could call a custom function to inject additional possible modes? In my head it would be something like (pseudocode vimscript since I'm not that great at it):

let g:lightline.colormode = 'MyColorMode'

function! MyColorMode()
  " includes 'inactive', 'terminal' etc
  let l:lightlinemode = lightline#colormode()
  if &previewwindow && l:lightlinemode == "inactive"
    return "previewinactive"
  elseif &previewwindow
    return "preview"
  else
   return l:lightlinemode
  endif
endfunction

Thanks in advance for your time!

itchyny commented 9 months ago

I don't support such custom color modes, because it might force lightline colorscheme creators to support endless request for each window types. Having said that, you can use lightline#link to change the colors to a Vim mode from component functions, and there is an example in the help for CtrlP plugin to make the statusline look like insert/replace mode even if it is actually in the normal mode. The argument of lightline#link should be one of the Vim modes, but configuring the internal g:lightline._mode_ might work as you expected.

Svalorzen commented 9 months ago

Thanks. I feel this fear might be a bit unfounded, especially considering that many colorschemes don't even support all the modes (I'm seeing that terminal is quite underused), but obviously I won't push.

Also given this, I've decided to add some colors to the terminal mode to the wombat colorscheme, and opt them in for my preview window. I have then added a new function in place of the default 'mode'; hopefully what I did is correct:

function! PreviewWindowMode()
    if &previewwindow
        call lightline#link('t')
        return "PREVIEW [" . lightline#mode() . "]"
    else
        return lightline#mode()
    endif
endfunction

Thanks again for the help!

Svalorzen commented 9 months ago

@itchyny Sorry to bother you again; I was wondering (since I wasn't able to figure it out) if there was a way to also override the inactive state?

itchyny commented 9 months ago

That's impossible unfortunately, there is only one mode for the active window. Although the modes and inactive are both keys for the colorscheme palette, they are totally different concept. Three "mode" (active, inactive, tabline) to switch the components and colors, and lightline#link links the colors of the active window statusline to that for the Vim modes (normal, insert, etc).

Svalorzen commented 9 months ago

I see. In a bit of a hacking attempt I have made the following patch to lightline#update():

    for n in range(1, winnr('$'))
      let z = (n!=w)
      if has_key(s:lightline, 'inactive_override') && z == 1
        let z = eval(s:lightline['inactive_override'] . '(' . n . ')')
      endif
      call setwinvar(n, '&statusline', s[z])
    endfor

It seems to work in my case by setting:

function! MyOverride(n)
    return !getwinvar(a:n, '&previewwindow')
endfunction

let g:lightline = {
\  ...
\   'inactive_override': 'MyOverride'
\ }

Do you think I'm risking lightline breaking horribly with this? Thanks again for the help!