用于管理窗口的 vimscript 需要一些回顾

问题描述 投票:0回答:1

有人可以检查一下我下面的 vim 脚本吗? 我尝试制作一个键映射来执行以下操作:

1. Closes tagbar and/or nerdtree if exist
2. Do <C-W>H or <C-W>J or <C-W>K or <C-W>L
3. Recover tagbar and/or nerdtree if originally exited

对于其中包含文件内容的窗口,此键映射效果很好。 仅对于其中没有文件内容的窗口(此类窗口可以通过 n 创建)此代码有效,但 nerdtree 和 tagbar 不会重新出现。

恢复那些插件窗口就是函数RecoverThe2()的作用。 我无法调试这个脚本。我只能想象我的大脑中正在发生什么。但我无法弄清楚。

  1. 我想就这个问题得到一些建议。
  2. 我想获得一些有关全局变量 - g:nerdtree_open 和 g:tagbar_open 的使用的建议。我不确定 vimscript 中全局变量的正确用法。我正确使用全局变量吗?
let g:nerdtree_open = 0                                                          
let g:tagbar_open = 0                                                            
                                                                                 
function! CloseThe2()                                                            
  " Detect which plugins are open                                                
  if exists('t:NERDTreeBufName')                                                 
    let g:nerdtree_open = bufwinnr(t:NERDTreeBufName) != -1                      
  else                                                                           
    let g:nerdtree_open = 0                                                      
  endif                                                                          
  let g:tagbar_open = bufwinnr('__Tagbar__') != -1                               
                                                                                 
  " Perform the appropriate action                                               
  if g:nerdtree_open                                                             
    NERDTreeClose                                                                
  endif                                                                          
  if g:tagbar_open                                                               
    TagbarClose                                                                  
  endif                                                                          
endfunction                                                                      
                                                                                 
function! RecoverThe2()                                                          
  " Perform the appropriate action                                               
  if g:nerdtree_open                                                             
    NERDTree                                                                     
    let g:nerdtree_open = 0                                                      
  endif                                                                          
  if g:tagbar_open                                                               
    TagbarOpen                                                                   
    let g:tagbar_open = 0                                                        
  endif                                                                          
endfunction                                                                      
                                                                                 
noremap <C-W>HH :call CloseThe2()<cr><C-W>H :call RecoverThe2()<cr>              
noremap <C-W>JJ :call CloseThe2()<cr><C-W>J :call RecoverThe2()<cr>              
noremap <C-W>KK :call CloseThe2()<cr><C-W>K :call RecoverThe2()<cr>              
noremap <C-W>LL :call CloseThe2()<cr><C-W>L :call RecoverThe2()<cr>

仅供参考我在 Ubuntu 22.04 Gnome 终端上测试了这个

你可以在这里找到我的 vimrc

variables vim global
1个回答
0
投票

映射的右侧是宏,因此是一系列命令。在您的情况下,RHS 可以细分为 N 个正常模式命令:

:call CloseThe2()<cr><C-W>H :call RecoverThe2()<cr>
AAAAAAAAAAAAAAAAAAAAA
                     BBBBBB
                           C
                            DDDDDDDDDDDDDDDDDDDDDDD

在宏中,当其中一个命令抛出错误时,其余命令不会执行。因此,如果您绝对希望执行所有命令,请务必确保所有命令都不会抛出错误。

现在,让我们看看这四个命令的作用:

  • 命令 A 调用函数。
  • 命令 B 移动当前窗口。
  • 命令 C 将光标向右移动一个字符。
  • 命令 D 调用函数。

您的问题就在这里:您在命令 B 和 D 之间添加的空格被解释为合法的正常模式命令 C:

:help <space>
。当光标右侧有一些文本时,
<Space>
可以工作,但如果不是这种情况,它会抛出错误。由于缓冲区为空,命令 C 会抛出错误并阻止命令 D 的执行。

因此,一个简单的解决方法是删除该空间:

:call CloseThe2()<cr><C-W>H:call RecoverThe2()<cr>

请注意,您问题中的示例也有很多尾随空格。您应该确保它们不在您的

vimrc
中。

现在,由于这两个函数总是以相同的方式调用,夹着窗口移动,您可能可以将整个函数包装到一个函数中,以保持映射简单:

function! Whatever(direction)
    call CloseThe2()
    execute "wincmd " .. a:direction
    call RecoverThe2()
endfunction
nnoremap <C-W>HH <Cmd>call Whatever("H")<cr>

或者甚至丢弃这两个函数,这两个函数在该上下文之外并没有真正的用处,并将所有内容放在一个函数中。请注意,它具有将所有内容保留在本地的额外好处,从而防止全局范围内不必要的污染:

function! Whatever(direction)
    " the setup
    let l:nerdtree_open = 0
    let l:tagbar_open = 0

    " the first step
    if exists('t:NERDTreeBufName')
    […]

    " the second step
    execute "wincmd " .. a:direction

    " the third step
    if l:nerdtree_open
    […]
endfunction
nnoremap <C-W>HH <Cmd>call Whatever("H")<cr>

FWIW,请参阅

:help get()
了解从范围获取值的便捷方法,在本例中为
l:
,不会引发错误,并且具有默认值。

参见

:help :wincmd

© www.soinside.com 2019 - 2024. All rights reserved.