vim - 如何根据模式设置状态栏颜色的最佳方式

10

我尝试改善我的vim体验,让vim状态栏的颜色在模式改变时自动改变。

我尝试了以下方法:(从这里找到)

    "Automatically change the statusline color depending on mode
function! ChangeStatuslineColor()
  if (mode() =~# '\v(n|no)')
    exe 'hi! StatusLine ctermfg=008'
  elseif (mode() =~# '\v(v|V)' || g:currentmode[mode()] ==# 'V·Block' || get(g:currentmode, mode(), '') ==# 't')
    exe 'hi! StatusLine ctermfg=005'
  elseif (mode() ==# 'i')
    exe 'hi! StatusLine ctermfg=004'
  else
    exe 'hi! StatusLine ctermfg=006'
  endif

  return ''
endfunction

......并包括:

set statusline+=%{ChangeStatuslineColor()} 

但是有一个问题,如果您切换到插入模式然后按Esc键回到正常模式,它不会改变颜色。只有当您手动进入不同的模式时,它才会改变颜色。

5个回答

13

抱歉因评论了旧帖,但我认为我找到了更好的解决方案。像这样设置所需的颜色。

hi NormalColor guifg=Black guibg=Green ctermbg=46 ctermfg=0
hi InsertColor guifg=Black guibg=Cyan ctermbg=51 ctermfg=0
hi ReplaceColor guifg=Black guibg=maroon1 ctermbg=165 ctermfg=0
hi VisualColor guifg=Black guibg=Orange ctermbg=202 ctermfg=0

现在添加到状态栏

set statusline+=%#NormalColor#%{(mode()=='n')?'\ \ NORMAL\ ':''}
set statusline+=%#InsertColor#%{(mode()=='i')?'\ \ INSERT\ ':''}
set statusline+=%#ReplaceColor#%{(mode()=='R')?'\ \ REPLACE\ ':''}
set statusline+=%#VisualColor#%{(mode()=='v')?'\ \ VISUAL\ ':''}

它完美地工作,不需要任何视觉模式的解决方案,并且不需要额外的光标移动来触发颜色变化。


1
非常简单,我喜欢它!如果你在开头添加一个 set statusline= ,你就可以一遍又一遍地 source 你的 vimrc 文件而不会重复样式。 - Tom Saleeba
(适用于初学者)在代码顶部添加“set laststatus=2”以将状态行设置为“始终可见”。 - rossijonas
我怎样才能获取更多关于这个的信息?我想要为“命令”模式、 “可视块”模式等设置颜色。但是hi CommandColor没有效果。 - Andreja Milosavljevic
1
@AndrejaMilosavljevic,你只需要指定颜色,例如:hi CommandColor ctermbg=23 ctermfg=32,然后你可以按照自己的需求使用它。在这个例子中,CommandColor只是一个变量名,如果你愿意,你可以使用任何名称。 - wasd
1
@wasd 需要几天时间才能理解那是一个变量,谢谢你。 - Andreja Milosavljevic

3

我发现以下方法对我来说是最好的。它为我提供了所有不同模式的颜色,而不仅仅是插入、替换、可视和正常模式。

function! GitBranch()
  return system("git rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\n'")
endfunction

function! StatuslineGit()
  let l:branchname = GitBranch()
  return strlen(l:branchname) > 0?'  '.l:branchname.' ':''
endfunction

let g:currentmode={
      \ 'n'  : 'n',
      \ 'v'  : 'v',
      \ 'V'  : 'vl',
      \ '' : 'vb',
      \ 'i'  : 'i',
      \ 'R'  : 'r',
      \ 'Rv' : 'rv',
      \ 'c'  : 'c',
      \ 't'  : 'f',
      \}

hi NormalColor ctermbg=black ctermfg=white
hi InsertColor ctermbg=darkgreen ctermfg=black
hi ReplaceColor ctermbg=darkred ctermfg=black
hi VisualColor  ctermbg=darkblue ctermfg=black


set laststatus=2
set statusline=
set statusline+=%#NormalColor#%{(g:currentmode[mode()]=='n')?'\ \ normal\ ':''}
set statusline+=%#InsertColor#%{(g:currentmode[mode()]=='i')?'\ \ insert\ ':''}
set statusline+=%#ReplaceColor#%{(g:currentmode[mode()]=='r')?'\ \ replace\ ':''}
set statusline+=%#ReplaceColor#%{(g:currentmode[mode()]=='rv')?'\ \ v-replace\ ':''}
set statusline+=%#VisualColor#%{(g:currentmode[mode()]=='v')?'\ \ visual\ ':''}
set statusline+=%#VisualColor#%{(g:currentmode[mode()]=='vl')?'\ \ v-line\ ':''}
set statusline+=%#VisualColor#%{(g:currentmode[mode()]=='vb')?'\ \ v-block\ ':''}
set statusline+=%#NormalColor#%{(g:currentmode[mode()]=='c')?'\ \ command\ ':''}
set statusline+=%#NormalColor#%{(g:currentmode[mode()]=='f')?'\ \ finder\ ':''}
set statusline+=%#PmenuSel#
set statusline+=%{StatuslineGit()}
set statusline+=%#Statusline#
set statusline+=\ %f
set statusline+=%m
set statusline+=%=
set statusline+=%#StatusLineNc#
set statusline+=\ %y
set statusline+=\ %{&fileencoding?&fileencoding:&encoding}
set statusline+=\ %p%%
set statusline+=\ %l:%c

1
首先,感谢您添加这个。我尝试将此代码复制/粘贴到一个空的.vimrc文件中,在vm上进行全新的vim安装,以测试它并验证答案,但似乎没有任何反应。状态栏上没有改变颜色。请考虑尝试并重构答案,以帮助其他人。请考虑在代码顶部添加set laststatus=2,以帮助初学者。 - rossijonas
1
@rossijonas 很抱歉回复晚了。我已经更新了我的答案,并进行了配置,现在应该可以直接使用了。之前不起作用的原因是termguicolors没有设置。相反,答案不使用cterm颜色。 - dapc

1
我喜欢拥有两个vim配置,一个使用插件,另一个只有一个vimrc文件。为了做到这一点,如果没有像airline这样的插件,我通常会使用来自http://vim.wikia.com/wiki/Change_statusline_color_to_show_insert_or_normal_mode的代码片段。
function! InsertStatuslineColor(mode)
  if a:mode == 'i'
    hi statusline guibg=magenta
  elseif a:mode == 'r'
    hi statusline guibg=blue
  else
    hi statusline guibg=red
  endif
endfunction

au InsertEnter * call InsertStatuslineColor(v:insertmode)
au InsertChange * call InsertStatuslineColor(v:insertmode)
au InsertLeave * hi statusline guibg=green

" default the statusline to 

进入 Vim 时绿色

hi statusline guibg=green

如维基所述:

以下代码片段会在进入插入模式和离开插入模式时更改状态栏的颜色。无需记忆映射键或新命令,它完全自动化。

当然,如果您不喜欢选择的颜色,可以更改以下部分:

guibg=magenta


非常感谢,这正是我在寻找的! - rossijonas
最近我在查看今年发布的另一个答案时,尝试将答案复制/粘贴到一个全新的VM上的干净的.vimrc文件中,并且它没有起作用。请考虑尝试并重构答案以帮助其他人。还请考虑在代码顶部添加“set laststatus=2”以帮助初学者。 - rossijonas
@rossijonas,嘿,谢谢你测试它,你能告诉我出了什么问题吗?在我的干净环境中似乎运行良好。 - axwr
抱歉,我不确定缺少什么,因为我没有花时间进行实际调试。我刚刚再次尝试了一下,在我的Fedora 33(vim8.2)上创建了一个新用户,打开了一个新的.vimrc文件,添加了“set laststatus=2”并粘贴了上面的代码。保存并重新启动vim,切换模式时没有颜色变化。查看代码片段和它所引用的链接,似乎缺少vim.wikia上的代码片段的最后几行。 - rossijonas

1

我知道这个问题很久以前就被问过了,你可能已经得到了你想要的答案,但无论如何我还是会发布我的解决方案,在我看来这足够好,可以在这里分享。

hi StatusLine           ctermfg=253         ctermbg=233         cterm=bold
hi StatusLineNormal     ctermfg=251         ctermbg=26          cterm=bold
hi StatusLineInsert     ctermfg=251         ctermbg=22          cterm=bold
hi StatusLineReplace    ctermfg=251         ctermbg=88          cterm=bold
hi StatusLineVisual     ctermfg=251         ctermbg=130         cterm=bold
hi StatusLineVisualL    ctermfg=251         ctermbg=130         cterm=bold
hi StatusLineVisualB    ctermfg=251         ctermbg=130         cterm=bold
hi StatusLineCommand    ctermfg=251         ctermbg=26          cterm=bold
hi StatusLineSelect     ctermfg=251         ctermbg=130         cterm=bold
hi StatusLineSelectL    ctermfg=251         ctermbg=130         cterm=bold
hi StatusLineSelectB    ctermfg=251         ctermbg=130         cterm=bold
hi StatusLineTerminal   ctermfg=251         ctermbg=22          cterm=bold

let s:statusline_modes_dict = {
    \ 'n' : {
        \ 'text'        : 'NORMAL',
        \ 'color_group' : 'StatusLineNormal'
    \ },
    \ 'i' : {
        \ 'text'        : 'INSERT',
        \ 'color_group' : 'StatusLineInsert'
    \ },
    \ 'R' : {
        \ 'text'        : 'REPLACE',
        \ 'color_group' : 'StatusLineReplace'
    \ },
    \ 'v' : {
        \ 'text'        : 'VISUAL',
        \ 'color_group' : 'StatusLineVisual'
    \ },
    \ 'V' : {
        \ 'text'        : 'V-LINE',
        \ 'color_group' : 'StatusLineVisualL'
    \ },
    \ "\<C-v>" : {
        \ 'text'        : 'V-BLOCK',
        \ 'color_group' : 'StatusLineVisualB'
    \ },
    \ 'c' : {
        \ 'text'        : 'COMMAND',
        \ 'color_group' : 'StatusLineCommand'
    \ },
    \ 's' : {
        \ 'text'        : 'SELECT',
        \ 'color_group' : 'StatusLineSelect'
    \ },
    \ 'S' : {
        \ 'text'        : 'S-LINE',
        \ 'color_group' : 'StatusLineSelectL'
    \ },
    \ "\<C-s>" : {
        \ 'text'        : 'S-BLOCK',
        \ 'color_group' : 'StatusLineSelectB'
    \ },
    \ 't' : {
        \ 'text'        : 'TERMINAL',
        \ 'color_group' : 'StatusLineTerminal'
    \ },
\ }

function Get_current_mode_text ()
    let md = mode()
    if (has_key (s:statusline_modes_dict, md))
        return s:statusline_modes_dict[md]['text']
    endif
    return md
endfunction

function Get_current_mode_color_group ()
    let md = mode()
    if (has_key (s:statusline_modes_dict, md))
        return "%#" . s:statusline_modes_dict[md]['color_group'] . "#"
    endif
    return "%#StatusLine#"
endfunction

" left
set statusline=
set statusline+=%{%Get_current_mode_color_group()%}\ 
set statusline+=%{Get_current_mode_text()}\ 
set statusline+=%#Statusline#\ 


这里的statusline_modes_dict存储了与mode()返回值完全相同的key,它还有要显示在状态栏和高亮组(color_group)中的text。当然,这些高亮组必须添加到颜色方案或其他地方。 也许有可能将Get_current_mode_text()Get_current_mode_color_group()合并为一个函数以减少操作次数,但我尝试在状态栏中运行时失败了。

1

你或许应该尝试这个 vim 插件 vim-airline。它可以根据你设置的颜色主题自动改变状态栏颜色,以反映模式的变化。


谢谢,我已经知道有一些插件可以使它工作,但我实际上正在寻找如何手动设置。了解vim脚本在状态栏上的行为.. - rossijonas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接