How to redirect ex command output into current buffer or file?

前端 未结 6 1848
面向向阳花
面向向阳花 2020-11-30 21:58

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 registers into the curre

相关标签:
6条回答
  • 2020-11-30 22:27

    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')
    
    0 讨论(0)
  • 2020-11-30 22:33

    @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
    
    0 讨论(0)
  • 2020-11-30 22:37
    :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 :-)

    0 讨论(0)
  • 2020-11-30 22:40

    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

    0 讨论(0)
  • 2020-11-30 22:41
    :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.

    0 讨论(0)
  • 2020-11-30 22:41

    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
    
    1. :write the file so that any changes won't be lost
    2. Begin redirecting output to %, the name of the current file.
    3. Silently run the :registers command.
    4. END redirecting to the file.
    5. :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.

    0 讨论(0)
提交回复
热议问题