14

When I open vim with multiple files (vim f1 f2 ...), how can I make it open them in tabs directly, without using -p?

I'm looking to separate out shell behaviour from vim behaviour, removing vim-based aliases, etc. That's why I'd prefer not to use aliases, etc. (hence, no -p).

I'm pretty sure this one has been asked on a few SE sites (such as on SO). However, I'm in no position to judge what would be the best way to do this, so I'm also hoping for a note on why a suggested method is good.

For the particular SO post linked:

  • the accepted answer does tabpagemax=9999. Call it personal bias, but I see a limit being set to a large number and I think there's something wrong (the way I'd feel if I saw chmod 777).

    :au VimEnter * set tabpagemax=9999|sil tab ball|set tabpagemax&vim
    
  • the other answer leads to an extra empty tab being opened, while being far more concise.

    :autocmd VimEnter * argdo tabedit
    

I'm hoping for an answer which doesn't have an extra tab opened and doesn't set a limit to a large value (or explain why that's not a bad thing).

11
  • @OrangeTux I posted in the spirit of Gilles' answer. But with the downvote I wonder what would Gilles say to a post linking to an existing post?
    – muru
    Feb 4, 2015 at 15:20
  • @Carpetsmoker I didn't see your comment update. An empty tabpage is not a big problem when your sessions tend to end with :qa by force of habit. If that's the only advantage I'd go with the other one, since it does seem simpler.
    – muru
    Feb 4, 2015 at 15:24
  • 3
    @muru WWGS? Do you have a reason to think the answers on Stack Overflow aren't satisfactory? If so, explain that in your question. In any case, summarize the SO answers in your question. If that leads to the question containing its own answer, don't post. Feb 4, 2015 at 15:29
  • @Gilles Updated. I didn't post the actual commands, do you think I should?
    – muru
    Feb 4, 2015 at 15:34

3 Answers 3

9

After some experimentation I've found this to be the best way; it should behave the same as vim -p:

augroup open-tabs
    au!
    au VimEnter * ++nested if !&diff | tab all | tabfirst | endif
augroup end

tab all opens all the entries in the argument list (:args) in a tab. The argument list is a list of files you passed to Vim on startup. And the tabfirst makes sure the first tab is focused rather than the last (this is optional).

We don't do any of this if &diff is set; if it is, we're using vimdiff or vim -d, where we want to have 2 windows, and not 2 tabs.

In this answer I've also written a bit about the argument list and tab all which may be of interest.

The ++nested part is required to run autocommands such as BufRead for the files we open.


Some notes about the other solutions:

  • tab ball opens a tab for every entry in the buffer list, not the argument list. The "problem" is that the buffer list may be saved in the viminfo file when quiting and is restored on startup if % is in 'viminfo' (not enabled by default). So if you just type vim it will open those files. Personally I wouldn't want that, though I can imagine some people finding it useful; so use what you prefer.

  • set tabpagemax=9999 is not required; the default of 10 should be fine. You can increase this in your vimrc if you want more, but 9999 is a silly number. If you use -p, you also get tabpagemax tabs so this should respect that. Remember that this will open (read) a buffer on startup, so it's rather slow.

  • autocmd VimEnter * argdo tabedit is just the same way of saying tab all. However, the initial buffer isn't cleared, so you're left with that extra tab (tab all replaces all tabs). To fix this, you need the workaround in Josh Petrie's answer.

5
  • Thanks a lot for this answer. It works great on vim >= 8.1, but not on vim 8.0 which I am stuck with on a legacy machine. Any idea as to why it does not work on vim 8.0 and how to get it to work?
    – gothicVI
    May 27, 2022 at 14:54
  • 1
    What error do you get @gothicVI? And which Vim patchlevel are you using (i.e. the third digit after 8.0)? May 27, 2022 at 17:37
  • @MartinTournoij thanks for the reply. No third digit but: $ vim --version VIM - Vi IMproved 8.0 (2016 Sep 12) Included patches: 1-1568 The error when opening vim or one or more files is: Error detected while processing VimEnter Auto commands for "*": E492: Not an editor command: ++nested if !&diff | tab all | tabfirst | endif
    – gothicVI
    May 28, 2022 at 19:19
  • 1
    @gothicVI ++nested was added in Vim 8.1.1113; but I believe just nested without the ++ should work in older versions, but I didn't try it to confirm. May 29, 2022 at 22:05
  • Amazing that seems to work. Could you briefly explain why, or what (++)nested even does, respectively in this case?
    – gothicVI
    May 31, 2022 at 7:54
2

I think adding something like this to your .vimrc may solve your problems (note, however, that I don't actually use this and have only done minimal testing, it may do strange things in some cases):

function! OpenArgumentsInTabs()
  ardo tabedit
  if tabpagenr("$") > 1
    tabclose
  endif
endfunction

autocmd VimEnter * call OpenArgumentsInTabs()

As you noted, argdo tabedit will leave you an empty extra tab. So you can simply close that tab automatically. However, you can't just invoke tabclose unchecked, or vim will give you an error when you launch it without arguments or a single file (you "can't close the last tab"). Instead, check to see if the total number of tabs is greater than one (that's what $ causes tabpagenr to return) and only then do you need to close the last tab.


That said, I feel like it's worth pointing out that vim's tabs aren't quite like other editors' tabs, and that's something to keep in mind when considering how to use tabs in your workflow (you seem to be aware of this, but I want to make the point for the benefit of future readers who might not so they can make their own decisions).

0
0

I've come up with a simpler solution that meets my own needs.

It doesn't meet the OP's requirement of not using -p (unless hiding it behind a script is good enough).

Note that vim -p single_file seems to behave the same as vim single_file, so always using the -p option doesn't appear to be a problem.

I habitually invoke vim by typing vi or view. I find the behavior of the -p option preferable to the default behavior, but I still want to be able to fall back to the default, or to use -o or -O, if I want to.

I've created wrapper scripts called vi and view and added them to my $HOME/bin directory, which precedes /usr/bin and /bin in my $PATH.

vi:

#!/bin/sh
exec vim -p "$@"

view:

#!/bin/sh
exec vim -R -p "$@"

An alias or shell function would do the same thing.

If I want to fall back to the default behavior, I can type vim or vim -R rather than vi or view.

(I still have $EDITOR set to vim. I might consider changing it to vi if it becomes an issue, but most programs that use $EDITOR don't invoke the editor with multiple file names.)

5
  • Could have just used an alias.
    – muru
    Aug 28, 2021 at 0:27
  • @muru True, but a script lets me add refinements later. For example, I might decide I want it not to use -p if it sees -o or -O. (For now I just do that by typing vim rather than vi.) Aug 28, 2021 at 1:29
  • 2
    Don't those options anyway override each other? So a vim -p alias with -O filename would use the -O behaviour
    – muru
    Aug 28, 2021 at 1:42
  • @muru I hadn't thought about that. It appears they do, but as far as I can tell it's not documented. Aug 28, 2021 at 1:51
  • If you use zsh then =word expands to the full path of word from $PATH; e.g. print vim will print /usr/bin/vim. This can be useful to override aliases if you need it: =vim file will skip any aliases, as if you typed /usr/bin/vim file. I don't think bash has anything similar. May 29, 2022 at 22:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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