vim 活动窗口状态行上的自定义文本与基于窗口模式的状态行颜色

f45qwnt8  于 2022-11-11  发布在  其他
关注(0)|答案(1)|浏览(181)

我在我的.vimrc中有以下代码,它在活动窗口的状态行中显示Y,在非活动窗口的状态行中显示X,以防窗口被拆分。

set laststatus=2

function MyStatusLine() abort
  let l:filename = '%f'
  let l:mod = '%m'
  let l:ell = '%l'
  let l:Ell = '%L'
  let l:Pee = '%P'
  let sl = ""
  if g:statusline_winid == win_getid(winnr())
    let sl .= "Y "
  else
    let sl .= "X "
  endif  
  return sl.l:filename.' '.l:mod.' '.l:ell.' '.l:Ell.' '.l:Pee
endfunction

set statusline+=%!MyStatusLine()

我正在尝试合并一个建议的方法here,它本身对我很有效。这会根据窗口所处的模式改变状态行的颜色。
在尝试将两者结合起来,即在活动窗口的状态行上显示Y,在非活动窗口的状态行上显示N,并根据它们(上次)所处的模式改变它们的颜色时,我尝试了以下方法:

set laststatus=2

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

function MyStatusLine() abort
  let l:filename = '%f'
  let l:mod = '%m'
  let l:ell = '%l'
  let l:Ell = '%L'
  let l:Pee = '%P'
  let sl = ""
  if g:statusline_winid == win_getid(winnr())
    let sl .= "Y "
  else
    let sl .= "X "
  endif  
  return sl.l:filename.' '.l:mod.' '.l:ell.' '.l:Ell.' '.l:Pee
endfunction

set statusline+=%!MyStatusLine()
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\ ':''}

但是,这并不起作用,并且当获取.vimrc时,会获得以下错误消息:
E121: Undefined variable: #NormalColor#
是否有办法同时获得这两种功能?
ETA:按照romainl提供的必须从函数返回整个字符串的建议,我尝试了以下操作:

set laststatus=2
function MyStatusLine() abort
  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
  let l:filename = '%f'
  let l:mod = '%m'
  let l:ell = '%l'
  let l:Ell = '%L'
  let l:Pee = '%P'
  let sl = ""
  if g:statusline_winid == win_getid(winnr())
    let sl .= "Y "
  else
    let sl .= "X "
  endif  
  let l:normcol=%#NormalColor#%{(g:currentmode[mode()]=='n')?'\ \ normal\ ':''}
  let l:insert=%#InsertColor#%{(g:currentmode[mode()]=='i')?'\ \ insert\ ':''}
  let l:replace=%#ReplaceColor#%{(g:currentmode[mode()]=='r')?'\ \ replace\ ':''}
  let l:vreplace=%#ReplaceColor#%{(g:currentmode[mode()]=='rv')?'\ \ v-replace\ ':''}
  let l:visual=%#VisualColor#%{(g:currentmode[mode()]=='v')?'\ \ visual\ ':''}
  let l:v-line=%#VisualColor#%{(g:currentmode[mode()]=='vl')?'\ \ v-line\ ':''}
  let l:v-block=%#VisualColor#%{(g:currentmode[mode()]=='vb')?'\ \ v-block\ ':''}
  let l:command=%#NormalColor#%{(g:currentmode[mode()]=='c')?'\ \ command\ ':''}
  let l:finder=%#NormalColor#%{(g:currentmode[mode()]=='f')?'\ \ finder\ ':''}
  return sl.l:filename.' '.l:mod.' '.l:ell.' '.l:Ell.' '.l:Pee.' '.l:normcol.' '.l:insert.' '.l:replace.' '.l:vreplace.' '.l:visual.' '.l:v-line.' '.l:v-block.' '.l:command.' '.l:finder
endfunction

set statusline+=%!MyStatusLine()

这也不起作用。得到的错误是:

Error detected while processing function MyStatusLine:
line   27:
E15: Invalid expression: %#NormalColor#%{(g:currentmode[mode()]=='n')?'\ \ normal\ ':''}
ogsagwnx

ogsagwnx1#

在以下行中:

set statusline+=%!MyStatusLine()

%!之后的所有内容都将作为表达式进行计算,以生成选项的值,但您需要向表达式中添加更多内容:

set statusline+=%#NormalColor#%{(g:currentmode[mode()]=='n')?'\ \ normal\ ':''}
[...]

这些东西在表达式求值的上下文中是没有意义的,因此求值失败,状态行不起作用。
您需要从MyStatusLine()返回 full 字符串。
---后续---
函数的输出应该是字符串,因此连接到该字符串中的所有变量都应该是字符串或计算结果为字符串的表达式。
%#NormalColor#%,其余的都是垃圾:它既不是字符串,也不是计算结果为字符串的表达式。
因此,应改为:

let l:normcol=%#NormalColor#%{(g:currentmode[mode()]=='n')?'\ \ normal\ ':''}

您应该执行以下操作:

let l:normcol = "%#NormalColor#%{(g:currentmode[mode()]=='n')?'\ \ normal\ ':''}"

而且,最后的巨大连接至少可以说是笨拙的。我会把所有这些字符串放在一个列表中,然后用一个连接结束。类似于:

return [
    \ "my first string",
    \ "my second string",
    \ ]->join()

相关问题