6

Imagine I'm coding, and I have different split panes open. What settings should I pass into vimrc to change the background color as I switch from one buffer/pane to another?

I have tried:

autocmd BufEnter * highlight Normal ctermbg=black                                                                                                                                                                                                                              
autocmd BufLeave * highlight Normal ctermbg=white 

I would like to add that I am sure that I've got 256 colors enabled

chutsu
  • 13,612
  • 19
  • 65
  • 86
  • A related question is http://stackoverflow.com/questions/4325682/vim-colorschemes-not-changing-background-color – Mihai8 Mar 07 '13 at 22:59
  • sorry not relevant in my case since I do have 256 colors enabled – chutsu Mar 07 '13 at 23:03
  • if you just want to distinguish the current/active window, I suggest taking some other hi-group. e.g. cursorline, or with/without line-number or status bar... there is no hi-group for window. if we define one group, it is also hard to make the non-text area with bg color by `matchadd()` – Kent Mar 07 '13 at 23:54

5 Answers5

13

Actually, there is a way to get this effect. See the answer by @blueyed to this related question: vim - dim inactive split panes. He provides the script below and when placed in my .vimrc it does dim the background of inactive windows. In effect, it makes their background the same colour specified for the colorcolumn (the vertical line indicating your desired text width).

" Dim inactive windows using 'colorcolumn' setting
" This tends to slow down redrawing, but is very useful.
" Based on https://groups.google.com/d/msg/vim_use/IJU-Vk-QLJE/xz4hjPjCRBUJ
" XXX: this will only work with lines containing text (i.e. not '~')
" from 
if exists('+colorcolumn')
  function! s:DimInactiveWindows()
    for i in range(1, tabpagewinnr(tabpagenr(), '$'))
      let l:range = ""
      if i != winnr()
        if &wrap
         " HACK: when wrapping lines is enabled, we use the maximum number
         " of columns getting highlighted. This might get calculated by
         " looking for the longest visible line and using a multiple of
         " winwidth().
         let l:width=256 " max
        else
         let l:width=winwidth(i)
        endif
        let l:range = join(range(1, l:width), ',')
      endif
      call setwinvar(i, '&colorcolumn', l:range)
    endfor
  endfunction
  augroup DimInactiveWindows
    au!
    au WinEnter * call s:DimInactiveWindows()
    au WinEnter * set cursorline
    au WinLeave * set nocursorline
  augroup END
endif
Community
  • 1
  • 1
monotasker
  • 1,985
  • 1
  • 17
  • 22
5

For Neovim users, there is the winhighlight option. The help file provides the following example:

Example: show a different color for non-current windows:

set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
eugenhu
  • 1,168
  • 13
  • 22
  • This is a great way (with nvim at least) to get something even better than custom non-active window background control via NormalNC, e.g. winhighlight allows for per-window override for both Normal and NormalNC, allowing for full control over arbitrary windows' background colors. I really like this because I am creating a tool that does file searching in an external program and being able to highlight a specific open file in a vim window would be really useful. – Steven Lu Nov 28 '20 at 21:01
4

You can't. The :highlight groups are global; i.e. when you have multiple window :splits, all window backgrounds will be colored by the same Normal highlight group.

The only differentiation between active and non-active windows is the (blinking) cursor and the differently highlighted status line (i.e. StatusLine vs. StatusLineNC). (You can add other differences, e.g. by only turning on 'cursorline' in the current buffer (see my CursorLineCurrentWindow plugin.))

One of the design goals of Vim is to work equally well in a primitive, low-color console as in the GUI GVIM. When you have only 16 colors available, a distinction by background color is likely to clash with the syntax highlighting. I guess that is the reason why Vim hasn't and will not have this functionality.

Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
  • You're right, though... I've been doing the autocmd version for so long, I forgot vim had the built-in simple version with those 2 groups. :) – cptstubing06 Mar 08 '13 at 12:08
  • Since this is the first Google result on the topic, and since this is the accepted answer, I should point out that @blueyed has written a script that *does* produce the desired effect. It's a bit of a hack, but it works. See my answer below. – monotasker Oct 25 '13 at 16:13
  • @monotasker Bit of a hack is an understatement; you're completely losing another feature, and it's quite involved. (Also, no need to downvote my answer, whoever just did that.) If I really wanted that feature, I'd rather write a patch for a `NormalNC` highlight group and submit that to Bram. – Ingo Karkat Oct 25 '13 at 20:46
  • @IngoKarkat Yes, you're right that it's not ideal. My point is just that one *can* drop in blueyed's script and get the desired effect (for me at least, I only need the colorcolumn in my active window, so the feature loss isn't a big deal). There are some (including myself) who would have to invest the time in figuring out how the highlighting files work before we could write a patch like that. So my point is that your answer isn't quite correct--it *is* possible to get the desired effect. Not an ideal solution, but it gets the job done in the meantime. Ergo, the effect *is* possible now. – monotasker Nov 01 '13 at 16:41
  • @IngoKarkat For the record, it wasn't me that down-voted your answer. I'll leave that for others to decide. And if you or someone else can write the desired patch for a NormalNC highlight group I'd be grateful. – monotasker Nov 01 '13 at 16:42
4

Basically what Kent said above will work -- surprisingly well at that. The only limitation is that you can only dim the foreground color. Copy this into vimrc, and evoke :call ToggleDimInactiveWin().

let opt_DimInactiveWin=0
hi Inactive ctermfg=235
fun! ToggleDimInactiveWin()
    if g:opt_DimInactiveWin
        autocmd! DimWindows
        windo syntax clear Inactive
    else
        windo syntax region Inactive start='^' end='$'
        syntax clear Inactive
        augroup DimWindows
            autocmd BufEnter * syntax clear Inactive
            autocmd BufLeave * syntax region Inactive start='^' end='$'
        augroup end
    en
    let g:opt_DimInactiveWin=!g:opt_DimInactiveWin
endfun

A few things I had to look up in writing this:

(1) windo conveniently executes a command across all windows

(2) augroup defines autocommand groups, which can be cleared with autocmd! group

q335r49
  • 608
  • 8
  • 10
  • This is very inventive using a syntax highlighting override. Thanks for the idea! Sadly this takes away the syntax highlighting in dimmed windows. – Steven Lu Nov 28 '20 at 20:51
1

Personally, I use my statusline to let me know this. I use the WinEnter and WinLeave autocmds to switch to an inactive status line (grayed out) when leaving and an active statusline (bright colors) when entering. The split panes you mention are windows in vim. This also works because :help statusline tells us that its setting is global or local to a window, so you can use :setlocal statusline=... or let &l:statusline=... to only apply to the current window.

Your method won't work because a) BufEnter and BufLeave aren't necessarily the events that you want and b) highlight groups are global, so changing Normal's definition changes it for every window.

cptstubing06
  • 322
  • 1
  • 4