I want vim to open Tagbar with :TagbarToggle when vim is starting up, but only:

  • If the file is Python
  • If it's not vimdiff
  • If I'm not using vim -O file1.py file2.py to open multiple windows

I would expect this to work:

if ! &diff && winnr('$') == 1    
    autocmd FileType python :TagbarToggle

Especially since :echo winnr('$') in vim does show the number of windows currently open, but adding echo winnr('$') to vimrc always returns 1, even if multiple windows are being opened with vim -O.

Is there a different way to check in vimrc if multiple windows are being opened?

I'm pretty sure I can hack together a solution based on timers (timer_start), where it waits for vim to open a hard-coded amount of time before checking winnr('$'), but that seems dumb. On slower systems, like a raspberry pi (which I use), the hardcoded value would need to be longer to adjust for longer startup time, but a longer timer on a faster system would be noticeable (the files would open, and half a second later, tagbar would open, which is annoying).

  • Maybe put the checks in autocmd VimEnter python if (...) | :TagbarToggle | endif.. is what I'm thinking but that's off the top of my noodle. – B Layer Dec 11 '20 at 19:44
  • 1
    Welcome to Vi and Vim! – filbranden Dec 11 '20 at 19:48

You can use a VimEnter auto-command, which only runs at Vim initialization, but after it has loaded all plug-ins and opened all buffers.

I just tested this combination below. It behaves the way you describe your requirements for the specific use cases you mentioned.

autocmd VimEnter * ++once if !&diff && winnr('$') == 1 && &filetype ==# 'python' | execute 'TagbarToggle' | endif

As suggested by @Matt, we can check for bufnr('$') == 1 instead of winnr('$') == 1 to also cover the case you're opening multiple files in separate tabs with vim -p (but maybe you do want to toggle the tagbar in that case?) I also updated my answer to include a ++once modifier on the autocmd, to avoid accumulating multiple copies of the autocmd when you reload your vimrc (source it again.)

As pointed out by @B.Layer, it might be possible to use a match for *.py on the VimEnter event, so you could use autocmd VimEnter *.py and skip the check for &filetype ==# 'python'

The :execute in the call to :TagbarToggle is to prevent that user-defined command to take the | as an argument. By default, user-defined commands take the bar as an argument, unless they've been carefully defined to allow it as a separator. Using :execute to call it is the standard way to work around this issue.

  • *.py? And why execute rather than just TagbarToggle? – B Layer Dec 11 '20 at 19:51
  • 1
    Checking bufnr('$') == 1 instead of winnr also allows for -p option. ++once is always a right thing to put after VimEnter. – Matt Dec 11 '20 at 20:08
  • @BLayer regarding *.py, I'm not sure what the event looks like for VimEnter. I haven't looked, but I don't think it's related to the files opened, since the autocmd runs even if you open no files, or multiple files... exe 'TagbarToggle' is to be safe from commands defined without -bar (unfortunately the -bar behavior is not the default one), in which case :exe is required. I haven't checked whether TagbarToggle is defined without -bar, but using exe is guaranteed to work, so I included that. – filbranden Dec 11 '20 at 20:10
  • 1
    My response was going to be "It's a toggle, i.e. no args, so put anything you want after it" but tested it and the silly thing needs -bar for -nargs=0 commands. What ever for I don't know. – B Layer Dec 11 '20 at 20:25
  • 1
    As for *.py it works fine with VimEnter...but agree that docs could be better. – B Layer Dec 11 '20 at 20:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.