4

Hopefully, the solution is efficient if it exists.

A solution that tests if it is a vim builtin command suffices.


EDIT To answer @Xiong Chiamiov comment, here is what I do in my .vimrc:
basically get input, then run command, capture and put.

nnoremap <M-x> :<C-u>call GetInputCommandThenCaptureAndPut()<CR>

func! GetInput()    " https://stackoverflow.com/a/15274117/3625404
    call inputsave()
    let cmd = input('ex-command to execute: ')
    call inputrestore()
    return cmd
endfunc
func! GetInputCommandThenCaptureAndPut()
    " cmdline keymap works, eg, <C-k> to get last input, <C-f> to open edit window, <C-r> insert register.
    let cmd = GetInput()
    if cmd =~ '^\s*!'   " eg, '!ls', '!ll', redraw needed.
        exec 'r'.cmd
        redraw!
    elseif cmd =~ '^ [[.a-zA-z0-9].*'    " one space before shell command, add '!', then run and read.
        exec 'r!' cmd
    elseif cmd =~ '^    [[.a-zA-z0-9].*'  " leading '<Tab>' key, execute shell command, witout capture.
        exec '!' cmd
    else
        if strlen(cmd) == 1     " customized shortcut
            if cmd == 's'
                let cmd = 'scr'
            elseif cmd == 'k' || cmd == 'm'   " :k is alias of :mark
                let cmd = 'marks'
            endif
        elseif cmd =~ '^\s*''\(\w*\)''\?\s*$'   " option start with single quote, closing one optional.
            let cmd = 'set '. substitute(cmd, '^\s*''\(\w*\)''\?\s*$', '\1', '').'?'
            " let cmd = 'set '.cmd.'?'
        endif
        let command = matchstr(cmd, '\w\+')
        if exists(':'.command)
            call PutAfterCapture(cmd)
        else    " not ex command, try run and read shell command.
            exec 'r!'.cmd
            redraw!
        endif
    endif
endfunc

The PutAfterCapture() is as below:

func! Capture(excmd) abort  " from tpope's scriptease.vim
try
    redir => out
    exe 'silent! '.a:excmd
finally
    redir END
endtry
return out
endfunc

func! PutAfterCapture(command)
    if a:command =~ '^\s*$'
        return
    endif
    let oldpos = getpos('.')
    silent! let @c = Capture(a:command)
    call setpos('.', oldpos)
    put c
    call setpos('.', oldpos)
endfunc!

command! -bar -nargs=+ Icapture call PutAfterCapture(<q-args>)

The workflow is type <M-x>, then type the cmd to run and capture. <C-f> is handy for longer input here, <C-r> works too.

Examples:

  • ls -- list of open buffers
  • <Space>ls or !ls -- list of files in current directory
  • s -- vim files being sourced
  • m -- marks
  • <Tab>bc -- use bc calculator interactively
11

I you only need to know if it is a built-in command, you can use

exists(':yourstring')

See :h exists() for more details.

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.