2

I can use % to get the name of the focused window for commands. How can I get a space-separated list of all buffers for use in a command?

For example, I would like to call

:!cat [all]

where [all] is something that evaluates to what I want.

  • 1
    Hi. Welcome to Vi/Vim SE. Either :args or :buffers/:ls depending on what value you have for :set hidden? :) Less cryptically, do you navigate files mostly with :next/:prev or other means? – B Layer Aug 27 '19 at 10:36
  • 1
    I use :e having :set hidden. I hope my edit clarifies what I mean, thank you. – August Janse Aug 27 '19 at 11:29
  • 2
    for the argument list, have a look at :h :_## – Christian Brabandt Aug 27 '19 at 11:58
  • where [all] is something that evaluates Note that the whole line after ! is simply passed to the shell. You have either to use execute, or pass the value inside an environment variable (so shell can expand it). – Matt Aug 27 '19 at 12:03
  • 1
    @AugustJanse It's a "special" (:h cmdline-special). Yes, the specials get expanded as a step separate from normal evaluation. So they are pretty much restricted. Therefore, you'll have to use :execute very often (that's a sort of "eval operator" for Vim). Another possible alternative is the expression register (<C-R>=), but an interactive input is not always convenient. – Matt Aug 28 '19 at 8:14
3

I suppose by "open files" you mean active buffers (see :h windows-intro). That could be achieved with the command :ls a (use h-flag to get hidden buffers if needed).

To pack it into a function you could use a redirection or a dedicated getbufinfo() interface. For example

function! GetActiveBuffers()
    let l:blist = getbufinfo({'bufloaded': 1, 'buflisted': 1})
    let l:result = []
    for l:item in l:blist
        "skip unnamed buffers; also skip hidden buffers?
        if empty(l:item.name) || l:item.hidden
            continue
        endif
        call add(l:result, shellescape(l:item.name))
    endfor
    return l:result
endfunction

" the result is a list
" use join() when a single string is needed
":exec '!cat' join(GetActiveBuffers())
| improve this answer | |
  • 2
    instead of parsing the output of :ls, you can use the getbufinfo() function – Christian Brabandt Aug 27 '19 at 12:42
  • @ChristianBrabandt Thank you. I knew there must be something like this... – Matt Aug 27 '19 at 13:12
  • 1
    With :!cat $myargs you're likely to run into escaping issues (it's actually probably going to ruin your use of shellescape()!) Much better is :execute '!cat' join(GetActiveBuffers()), which would assemble the command-line in Vim, rather than use a variable expansion in the spawned shell. (Hint: test it with files containing spaces and special characters and you'll see the difference.) – filbranden Aug 27 '19 at 15:00
  • 1
    @filbranden Yes, you're right. It turns out that it's quite hard to escape the things in the right way. exec looks easier to deal with. – Matt Aug 27 '19 at 15:46

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.