skip to Main Content

Could someone check my vimscript below.
I tried to make a key mapping that does:

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

For a window that has file content in it this key-mapping works well.
Only for a window that has no file content in it(this kind of window can be created by <C-W>n) this code works but nerdtree and tagbar does not reappear.

Recovering those plugin window is the role of the function RecoverThe2().
I cannot debug this script. I can only IMAGINE what is going on in my brain. But I cannot figure out.

  1. I’d like to get some advice on this problem.
  2. I’d like to get some advice about the usage of the global variables – g:nerdtree_open and g:tagbar_open. I am not certain about the correct usage of the global variable in vimscript. Am I using global variable correctly?
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>

F.Y.I. I tested this on Ubuntu 22.04 Gnome Terminal

You can find my vimrc here

2

Answers


  1. Chosen as BEST ANSWER

    Thanks to romainl, I was able to write working script as shown below:

    "The keymap below can be implemented with the help of stackoverflow and it's        
    "member romainl (https://stackoverflow.com/users/546861/romainl)                 
    "https://stackoverflow.com/questions/77578019/vimscript-for-managing-windows-need-some-review
    function! MoveTheWindowAllTheWayTo(direction)                                    
      "Detect which plugins are open                                                 
      if exists('t:NERDTreeBufName')                                                 
        let l:nerdtree_open = bufwinnr(t:NERDTreeBufName) != -1                      
      else                                                                           
        let l:nerdtree_open = 0                                                      
      endif                                                                          
      let l:tagbar_open = bufwinnr('__Tagbar__') != -1                               
                                                                                     
      "Close any open one                                                            
      if l:nerdtree_open                                                             
        NERDTreeClose                                                                
      endif                                                                          
      if l:tagbar_open                                                               
        TagbarClose                                                                  
      endif                                                                          
                                                                                     
      "Move the Window the cursor is in                                              
      exe "wincmd " .. a:direction                                                   
                                                                                     
      "Reopen any temporarily closed one                                             
      if l:nerdtree_open                                                             
        NERDTree                                                                     
      endif                                                                          
      if l:tagbar_open                                                               
        TagbarOpen                                                                   
      endif                                                                          
    endfunction                                                                      
                                                                                     
    noremap <C-W>HH :call MoveTheWindowAllTheWayTo('H')<CR>                          
    noremap <C-W>JJ :call MoveTheWindowAllTheWayTo('J')<CR>                          
    noremap <C-W>KK :call MoveTheWindowAllTheWayTo('K')<CR>                          
    noremap <C-W>LL :call MoveTheWindowAllTheWayTo('L')<CR> 
    

    https://vimdoc.sourceforge.net/htmldoc/windows.html#:wincmd

    helped also

    Thank you romainl. Please upvote romainl not this one.


  2. The right-hand side of a mapping is a macro, and thus a series of commands. In your case, the RHS can be subdivided in 4 normal mode commands:

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

    In a macro, when one of the commands throws an error, the remaining commands are not executed. Therefore, it is important to make sure that none of the commands can throw an error if you absolutely want all your commands to be executed.

    Now, let’s see what those four commands do:

    • Command A calls a function.
    • Command B moves the current window.
    • Command C moves the cursor one character to the right.
    • Command D calls a function.

    And here lies your problem: that space you added between commands B and D is interpreted as a legitimate normal mode command C: :help <space>. <Space> works when there is some text on the right of the cursor but it throws an error when that’s not the case. Since your buffer is empty, command C throws and error and prevents the execution of command D.

    An easy fix would thus be to remove that space:

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

    Note that the sample in your question has lots of trailing spaces, too. You should make sure they are not in your vimrc.

    Now, since those two functions are always called the same way, sandwiching a window movement, you could probably wrap the whole thing into a single function in order to keep your mappings simple:

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

    or even throw away those two functions, which are not really useful outside of that context, and put everything together in a single one. Note that it has the added benefit of keeping everything local and thus preventing unnecessary pollution of the global scope:

    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, see :help get() for a handy way to get a value from a scope, l: in this case, without throwing an error, and with a default value.

    See :help :wincmd.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search