- 
                Notifications
    
You must be signed in to change notification settings  - Fork 116
 
Customize Runner
User-defined runners provide you the possibility to run commands in any way you want, which could be helpful when you want a command run in a tmux split, a new gnome-terminal window, or a floaterm window.
A runner is a function with one argument opts as a dictionary, from which stores the command string, working directory, and other parameters passed with :AsyncRun command. All the runners are required to register in g:asyncrun_runner so that AsyncRun can recognize them.
function! s:my_runner(opts)
    echo "run: " . a:opts.cmd
endfunction
let g:asyncrun_runner = get(g:, 'asyncrun_runner', {})
let g:asyncrun_runner.test = function('s:my_runner')Than use:
:AsyncRun -mode=term -pos=test ls -la $(VIM_FILEDIR)When -mode=term and -pos=test are provided, runner test will be called. In this example, runner function s:my_runner does nothing but display the command in the bottom of your vim.
There is a opts argument in the runner function, which contains necessary information:
| Field | Need | Description | Example | 
|---|---|---|---|
| cmd | (required) | Command string (macros have already been expanded here) | ls -la | 
| cwd | (optional) | Working directory (will be an empty string if not provided) | /home/yourname/github | 
| mode | (optional) | Running mode | 
async, terminal/term, or vim
 | 
| pos | (optional) | Runner name or terminal position | 
TAB, gnome, tmux, ... | 
| option | (optional) | Runner option passed by :AsyncRun -option=xxx ...
 | 
... | 
| close | (optional) | Close terminal after job finished | -close=1 | 
| post | (optional) | A vim script needs to be executed after finished | -post=echo\ "done"  ls -la | 
| program | (optional) | Command modifier | -program=grep | 
| focus | (optional) | if set to zero, the runner will not get focused | -focus=0 | 
| encoding | (optional) | Command encoding | -encoding=gbk | 
If -cwd=xxx is provided after :AsyncRun command, AsyncRun will temporarily change the
current working directory to the target position when calling runner function. So, you can
either pick the value in a:opts.cwd or use the return value from getcwd() .
When use the :AsyncRun command in the range mode, additional information can be use:
| Field | Description | Example | 
|---|---|---|
| range | > 0 for range mode enabled | 0 | 
| range_top | first line of the range, where range starts | 100 | 
| range_bot | last line of the range, where range ends | 105 | 
| range_buf | buffer id of the document | 1 | 
Range support is not compulsory for runners, but it would be nice to provide this feature.
It is very easy to make the command run in a tmux pane with vimux:
function! s:run_tmux(opts)
    " asyncrun has temporarily changed working directory for you
    " getcwd() in the runner function is the target directory defined in `-cwd=xxx`  
    let cwd = getcwd()   
    call VimuxRunCommand('cd ' . shellescape(cwd) . '; ' . a:opts.cmd)
endfunction
let g:asyncrun_runner = get(g:, 'asyncrun_runner', {})
let g:asyncrun_runner.tmux = function('s:run_tmux')And you are able to use:
:AsyncRun -mode=term -pos=tmux ls -lascreenshot:

You can specify pane position (vertical or horizontal) and size, just check vimux's doc.
Another way to create a runner is to create a separated .vim file in the folder:
autoload/asyncrun/runner/
In one of your runtimepath, it will be automatically loaded in need. The script is required to provide a run function with the full name:
asyncrun#runner#{name}#run(opts)
For example, see gnome.vim in the autoload/asyncrun/runner folder:
function! asyncrun#runner#gnome#run(opts)
    if !executable('gnome-terminal')
        return asyncrun#utils#errmsg('gnome-terminal executable not find !')
    endif
    let cmds = []
    let cmds += ['cd ' . shellescape(getcwd()) ]
    let cmds += [a:opts.cmd]
    let cmds += ['echo ""']
    let cmds += ['read -n1 -rsp "press any key to continue ..."']
    let text = shellescape(join(cmds, ";"))
    let command = 'gnome-terminal -- bash -c ' . text
    call system(command . ' &')
endfunctionTry it with:
:AsyncRun -mode=term -pos=gnome  ls -laScreenshot:

In the runner folder, some pre-included runner script can be found:
| Runner | Description | Requirement | Link | 
|---|---|---|---|
gnome | 
run in a new gnome terminal | GNOME | gnome.vim | 
gnome_tab | 
run in a new gnome terminal tab | GNOME | gnome_tab.vim | 
xterm | 
run in a xterm window | xterm | xterm.vim | 
tmux | 
run in a separated tmux pane | Vimux | tmux.vim | 
floaterm | 
run in a new floaterm window | floaterm | floaterm.vim | 
floaterm_reuse | 
run in a reusable floaterm window | floaterm | floaterm_reuse.vim | 
quickui | 
run in a quickui window | vim-quickui | quickui.vim | 
toggleterm | 
run in a toggleterm window | toggleterm.nvim | toggleterm.vim | 
xfce | 
run in a new xfce terminal | xfce4-terminal | xfce.vim | 
konsole | 
run in a new konsole terminal | KDE | konsole.vim | 
macos | 
run in a macOS system terminal | macos | macos.vim | 
iterm | 
run in a new iterm2 tab | macos + iTerm2 | iterm.vim | 
They can be a good reference if you want to create a new runner.