4

Working with big projects, I often find myself needing to view/edit several files at once.

If I have multiple buffers open, is there a way to split the window to view multiple files in one command?

E.g. usually I begin my workflow by entering my project's root directory, entering vim in the terminal, and then entering :n **/*.py to recursively load all python files that exist in the project as buffers.

Simple example, I have these buffers:

:ls
  1 %a   ".vimrc"                       line 1
  2      "rsync_to_home.bash"           line 0
  3      "README.md"                    line 0
  4      ".zshrc"                       line 0

I want to split the screen to show "rsync_to_home.bash", ".zshrc", along with the current buffer (.vimrc), as horizontally split windows. To accomplish this, I would have to do:

:sb 2 <Enter>
:sb 4 <Enter>

But calling :sb for each file individually is tedious, and :sb 2 4 doesn't work. Also, if I'm working with a lot of files, I would probably have to repeat :ls between the :sb calls to make sure I'm calling the right buffer numbers.

2
  • 2
    You can also pass :sb a buffer name... For example :sb rsy followed by :sb zsh, with any unique substring of the buffer (file) name. Regarding using a single command, how about joining them with |? :sb rsy|sb zsh should work...
    – filbranden
    May 14, 2020 at 0:05
  • Joining the calls works, I'll go with that or I'll create a function and add to .vimrc if that's the only way
    – WalksB
    May 14, 2020 at 0:49

4 Answers 4

5

You could write a wrapper to do all the commands at once:

command -bar -nargs=+ -complete=buffer Sbuffers execute map([<f-args>], {_, b -> printf("sbuffer %s", b)})->join("|")

Usage: Sbuffers file1 file2 file3

Completion will use buffer names (so the buffers have to have been loaded). You can tweak this to use any file names with -complete=file, though according to :help :sbuffer files loaded from outside the buffer list will not have 'buflisted' set.

The general idea is to build up the string sbuffer b for each buffer b, and then join them with | to be one command:

sbuffer b1|sbuffer b2|sbuffer b3

And then :execute the whole lot.

We can do this by mapping over the list of arguments ([<f-args>]<f-args> turns the arguments into a list suitable for a function call, which happens to the be same form as needed to make a literal list with []). The one subtlety is that lambdas/Funcrefs given to map are given both the index/key and the value, hence the _ wildcard in the lambda arguments.

4

As filbranden pointed out, it is possible by joining the sb calls like e.g. this:

:sb rsy|sb zsh

This is useful for when first loading a large project. E.g. by going to project root directory, entering vim in terminal, calling :n **/*.py to load all python files recursively under the current directory (project root), then calling :ls to view all loaded files in buffer, and then to view multiple individual files on one window you use :sb file1.py|sb file2.py|sb file3.py ...

1

Just adding on to d-ben-knoble's answer (stackexchange won't let me comment on it yet), I mapped:

  • <leader>v (Vertical splits)
  • <leader>z (horiZontal splits)

I'm sure others will need to use other letters for the mapping.

command -bar -nargs=+ -complete=buffer Sbuffers execute map([<f-args>], {_, b -> printf("sbuffer %s", b)})->join("|")
nnoremap <leader>z :ls<cr>:Sbuffers<space>
command -bar -nargs=+ -complete=buffer Vbuffers execute map([<f-args>], {_, b -> printf("vsplit \#%s", b)})->join("|")
nnoremap <leader>v :ls<cr>:Vbuffers<space>

So, to get 4 vertically split windows with buffers 1-4, if your leader key is default \, you can type straight from normal mode:

\v 2 3 4

Note: Vim 8.0.1763 (and earlier?) don't like the post command: ->join, so

command -bar -nargs=+ -complete=buffer Sbuffers execute join(map([<f-args>], {_, b -> printf("sbuffer %s", b)}), "|")
nnoremap <leader>z :ls<cr>:Sbuffers<space>
command -bar -nargs=+ -complete=buffer Vbuffers execute join(map([<f-args>], {_, b -> printf("vsplit \#%s", b)}), "|")
nnoremap <leader>v :ls<cr>:Vbuffers<space>
0

If you know you want to open the files in multiple windows you can call vim with the following flags:

   -o[N]        Open N windows (default: one for each file)
   -O[N]        Like -o but split vertically

in your example:

vim -o **/*.py

would load all the files into their own window.

1
  • 1
    Note: this may not open a separate window for all the files, if there is not enough room (e.g. you are trying to open too many files at once) Dec 23, 2022 at 11:33

Your Answer

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

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