How can I redirect or pipe the output of an ex command into my current buffer or a file?
For example, I want to read the contents of all the regist开发者_如何转开发ers into the current buffer, which in ex mode is shown using :registers
.
:redir >name_of_registers_file
:registers
:redir END
:r name_of_registers_file
:help redir
The last command is very useful, since there are lots of options for redirection: to variables, to registers, how to append, further cornucopia.
I still find it weird and annoying that it uses END that way, but since everything else that can follow redir
has to start with a non-word-character, at least it's not ambiguous.
PS AFAIK (which is pretty far in this case) there's no way to read it directly into the buffer: you have to store it in a register or a variable first. Check the help for the various options of how to do that.
PPS If you do want to do this using a variable —maybe to encapsulate it in a function and avoid clobbering registers or global variables— you'll have to convert the multiline string that gets written to the variable into a list. EG
:call append( '.', split(variable_you_redirected_to, "\n") )
Otherwise (if you just do append('.',var)
) you end up with ^@'s (nulls) instead of newlines, since that's what vimscript uses to represent newlines in String variables.
edit: as @Bill Odom mentions, using :put =variable_you_redirected_to
is a lot easier than the complicated append()
expression. Thanks, Bill!
PPPS
I've written a snippet to make this stuff more convenient. It declares a function Redir(command, target)
and a command R
.
The command parses the last series of non-space characters as a redirection target and passes that to the function, which does the boilerplate to redirect the command output to the redirection target.
The command is everything after R
and before the last space.
EG
" Store the vim buffer list in buffer_list.txt
:R ls >buffer_list.txt
" Store error messages emitted by a function being debugged
" in the 'unnamed register'
:R call FunctionBeingDebugged() @">
There are a few limitations with this: for example you won't be able to write to a filename that contains a space. The upside to this is that you don't have to quote your command. I've got it posted on gist.github.com, and I'll try to keep it updated if I end up improving it. Or you can fork it yourself</noeuphemism>!
Anyway the snippet is available here. It can be dropped into a .vimrc file or into a file in ~/.vim/plugins.
@intuited is right; the redir
command is what you want. A one-liner like this will insert the output of :registers
into the current buffer:
redir => m | silent registers | redir END | put=m
That's not something you'll want to type very often, however, and it's not exactly amenable to a key map. I found myself doing this fairly often, so I wrote a function and a handful of commands to make it easier. As a bonus, I can now send command output to a new window or new tab as easily as inserting it into the current buffer. Here's the code (with a few command examples at the very end):
" redir_messages.vim
"
" Inspired by the TabMessage function/command combo found
" at <http://www.jukie.net/~bart/conf/vimrc>.
"
function! RedirMessages(msgcmd, destcmd)
"
" Captures the output generated by executing a:msgcmd, then places this
" output in the current buffer.
"
" If the a:destcmd parameter is not empty, a:destcmd is executed
" before the output is put into the buffer. This can be used to open a
" new window, new tab, etc., before :put'ing the output into the
" destination buffer.
"
" Examples:
"
" " Insert the output of :registers into the current buffer.
" call RedirMessages('registers', '')
"
" " Output :registers into the buffer of a new window.
" call RedirMessages('registers', 'new')
"
" " Output :registers into a new vertically-split window.
" call RedirMessages('registers', 'vnew')
"
" " Output :registers to a new tab.
" call RedirMessages('registers', 'tabnew')
"
" Commands for common cases are defined immediately after the
" function; see below.
"
" Redirect messages to a variable.
"
redir => message
" Execute the specified Ex command, capturing any messages
" that it generates into the message variable.
"
silent execute a:msgcmd
" Turn off redirection.
"
redir END
" If a destination-generating command was specified, execute it to
" open the destination. (This is usually something like :tabnew or
" :new, but can be any Ex command.)
"
" If no command is provided, output will be placed in the current
" buffer.
"
if strlen(a:destcmd) " destcmd is not an empty string
silent execute a:destcmd
endif
" Place the messages in the destination buffer.
"
silent put=message
endfunction
" Create commands to make RedirMessages() easier to use interactively.
" Here are some examples of their use:
"
" :BufMessage registers
" :WinMessage ls
" :TabMessage echo "Key mappings for Control+A:" | map <C-A>
"
command! -nargs=+ -complete=command BufMessage call RedirMessages(<q-args>, '' )
command! -nargs=+ -complete=command WinMessage call RedirMessages(<q-args>, 'new' )
command! -nargs=+ -complete=command TabMessage call RedirMessages(<q-args>, 'tabnew' )
" end redir_messages.vim
:redir @a
:registers
:redir END
"ap
:redir @a
redirects all messages from here on to a register named a
. You follow this with your command whose output you want to capture (:registers
in your case). :redir END
ends the redirection. "ap
means, "a
uses the register named a
and p
puts the contents of the selected register into the current buffer.
See Capture ex command output at Vim Tips Wiki for more information :-)
In addition, :h :redir
:
...To get the output of one command the |execute()| function can be used.
e.g.
put = execute('scriptnames')
put = execute('filter /vimfiles/ scriptnames')
It is not necessary to use a temporary variable as long as you can save the current buffer and are ok with appending the messages to the end of the current file.
From the Vim documentation:
:redi[r] >> {file} Redirect messages to file {file}. Append if {file}
already exists. {not in Vi}
http://vimdoc.sourceforge.net/htmldoc/various.html#:redir
So, to append the messages from :registers
to the bottom of the current file, do this:
:write | redir >> % | silent registers | redir END | edit
:write
the file so that any changes won't be lost- Begin redirecting output to
%
, the name of the current file. - Silently run the
:registers
command. END
redirecting to the file.:edit
the file to see the new changes.
You can also forcefully truncate the current file and replace it with the output messages:
:redir! > % | silent registers | redir END | edit!
But that is probably not what you want to do.
Unfortunately I have no rep, so I cannot add this as a comment to 'Francis Niu'.
The execute()
function looks like the easiest way to accomplish this, and it was added in vim 8 .
Listed in the new/extended features on vim's github. version8.txt
精彩评论