DEV Community

Linwei
Linwei

Posted on

asyncrun.vim: run commands in iterm2, tmux, or gnome/kde terminal

asyncrun.vim was known as a shell command runner in the quickfix window. However, it first got released six years ago (2016), when the +job feature just became stable in vim 7.4.1829. During these years, numerous issues have been addressed, and valuable feedbacks got collected.

At the beginning of 2022, I'd like to share some recent changes which may be helpful to improve your productivity.

New runners

Both Vim and NeoVim got +terminal features for years, but some people still used to run new jobs in system terminals, like gnome-terminal, xfce-terminal, iterm2, or konsole.

With the power of user-defined runners, you can run commands anywhere you want instead of in the quickfix window. Some pre-included runners can be used to interact with those external system terminals:

Runner Description Requirement
gnome in a new gnome terminal GNOME
gnome_tab in a new gnome terminal tab GNOME
xterm in a xterm window xterm
tmux in another tmux split Vimux
xfce in a new xfce terminal xfce4-terminal
konsole in a new konsole terminal KDE
macos in a macOS system terminal macOS
iterm in a new iterm2 tab macOS + iTerm2
external in a new cmd.exe window Windows

When using asyncrun with -mode=term, you can provide an option -pos={runner} to specify runner name:

:AsyncRun -mode=term -pos=gnome      ls -la
:AsyncRun -mode=term -pos=floaterm   ls -la
:AsyncRun -mode=term -pos=tmux       ls -la 
Enter fullscreen mode Exit fullscreen mode

When using gnome, konsole, external, or xfce runner in GVim, you can get exactly the same experience like starting a command-line program from IDEs:

If you are using terminal vim, a new gnome-terminal tab, or iterm2 tab may be a good start:

or perhaps in a tmux split:

Besides the system terminal, there are also runners for some most famous internal terminal plugins:

Runner Description Requirement
floaterm in a new floaterm window floaterm
floaterm_reuse in a reusable floaterm window floaterm
quickui in a quickui window vim-quickui
toggleterm in a toggleterm window toggleterm.nvim
termhelp in terminal help vim-terminal-help

Screenshot for the floaterm runner:

Terminal-help:

All runners are customizable, you can modify or define your own runners, see the customize runner page.

Internal terminal

Another exciting feature is interacting with (neo)vim's internal terminal:

" run command in the internal-terminal in a new tab 
:AsyncRun -mode=term -pos=tab    ls -la
:AsyncRun -mode=term -pos=TAB    ls -la

" open on the left/right/top/bottom side
:AsyncRun -mode=term -pos=left   ls -la
:AsyncRun -mode=term -pos=right  ls -la
:AsyncRun -mode=term -pos=top    ls -la
:AsyncRun -mode=term -pos=bottom ls -la 
Enter fullscreen mode Exit fullscreen mode

You may ask that you can directly use the builtin :term xxx command to start the internal terminal, what is the difference to use :AsyncRun for this ?

The main reasons are convenience and flexibility:

  • Macros like $(VIM_FILENAME) or $(VIM_ROOT) can be expanded in the command:

    :AsyncRun -mode=term -pos=TAB  ls -la $(VIM_FILEDIR)
    
  • Working directory can be customized by -cwd= option:

    :AsyncRun -mode=term -pos=TAB -cwd=~/github  ls -la
    
  • Easier to specify the opening position and size:

    :AsyncRun -mode=term -pos=bottom -rows=8  ls -la
    :AsyncRun -mode=term -pos=right -cols=40  ls -la
    
  • No distraction and prevent focus changing by providing -focus=0 option:

    :AsyncRun -mode=term -pos=tab -focus=0  ls -la
    
  • Can close the terminal window automatically when job is finished if -close option presents.

    :AsyncRun -mode=term -pos=tab -focus=0 -close ls -la
    
  • Run a vim command when job finished by -post=xxx

    :AsyncRun -mode=term -post=echo\ 'notify'   ls -la
    

And there are some more benefits:

  • Environment variables like $VIM_FILENAME can be initialized correctly.
  • Prevent listing terminal buffer in the buffer-list by -listed=0.
  • Set bufhidden to hide for terminal buffer by -hidden=1.
  • Reuse the previous terminal window by -reuse.
  • Notify can be setup by -post=xxx option.
  • Corresponding experience in both vim and neovim.

The most important thing is that vim/neovim's :term command can't escape complex strings correctly in Windows or some rare shells when arguments contain white spaces or quotes and bars. AsyncRun can pass arguments precisely as what they are.

My favorite terminal position is -pos=TAB, different with lower case -pos=tab, it will open a new terminal tab on the left side of my current tabpage:

I use it a lot to execute the current file because when it is finished, the tab will close, and it will return to the previous tabpage where I was working.

Excluding macro variables substitution, some of the actions above can be achieved by original :term with one or more other commands. Still, asyncrun provides a unified interface for these trivial things in one command and eliminates the difference between vim and neovim.

Summary

asyncrun.vim provides you with all the possible ways to run commands in vim with no compromise. Feel free to choose the one you like, and don't forget to check the command specification for more.

Bonus: If you find mapping asyncrun commands for different projects or file-types challenging, you may be benefit from a sibling plugin asynctasks.vim, it uses asyncrun as the backend and introduces vscode like task system in vim.

.

Discussion (0)