In Vim we can use add prefix! The way to execute external commands, such as! Ls, whose results will be printed at the bottom

So what do we do if we want to use the result of an external command?

use:read

If we want to insert the result of an external command, use :read! Ls can

usesystem()

If we don’t want to insert the result of a command into the current buffer, is there a way to store it in a variable? Yes, vim provides a function called system() to get the result of an external command. If you’ve ever used a shell, you’ll know that it’s used in the same way as $(command) or ‘command’. In the script we use let var = system(“command”) to get the output

In the terminal we can pass $? To obtain the execution result of the last command, according to this result to determine whether to continue to execute or terminate the program. In VIm we can think in the same way, using the default variable V :shell_error can get the execution result of the last external command

Here is an example of combining system() with v:shell_error

" Swap between target path and source path
function! hl#chezmoi#swap_between_target_and_source(a)
    let current_path = expand('%:p')
    if current_path =~# '.local/share/chezmoi/' " current path is located in ~/.local/share/chezmoi/, now we are inside the source path
        let target_path = s:get_target_file(current_path)
        exec 'edit ' . target_path
    else " now we are in the target path, so we should check this file have corresponding source file or not
        let target_path = system('chezmoi source-path ' . current_path)
        if v:shell_error! =0
            echom 'Current file is not managed by chezmoi!!! '
        else
            exec 'edit ' . target_path
        endif
    endif
endfunction
Copy the code

The actual case

Redir

We can define a method to capture the output of vim’s internal or external commands and output the captured results to a new window

"`:Redir` followed by either shell or vim command
command! -nargs=+ -complete=command Redir silent call Redir(<q-args>)

" Redirect output to a single window
function! Redir(cmd)
    for win in range(1.winnr('$'))
        if getwinvar(win, 'scratch')
            execute win . 'windo close'
        endif
    endfor
    if a:cmd= ~'^! '
        let output = system(matchstr(a:cmd.'^! \zs.*'))
    else
        redir => output
        execute a:cmd
        redir END
    endif
    botright vnew
    let w:scratch = 1
    setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
    call setline(1.split(output, "\n"))
endfunction
Copy the code

GetOutput

Again, we can simply return the result, which is useful and more flexible for variable assignments in scripts, using let var1 = GetOutput(“! python –version”)

" Get output of a command
function! GetOutput(cmd)
    if a:cmd= ~'^! '
        let output = system(matchstr(a:cmd.'^! \zs.*'))
    else
        redir => output
        silent execute a:cmd
        redir END
    endif
    let output = substitute(output, '[\x0]'.' '.'g')
    return output
endfunction
Copy the code

Reference

  • Append output of an external command
  • get exit status from system() call