Skip to main content
  1. Posts/

Running Command Asynchronously inside Neovim

··522 words·3 mins·
Table of Contents

Introduction
#

When I am writing some prototyping code inside Neovim, I want to run the script without going to the terminal and typing python toy_script.py. Of course, we can use :!python % in the command line to run the script (see :h :!). The problem is that running external command will block Nvim/Vim, and we can not move the cursor until the script finishes running.

Of course, on Linux and Mac, you can use !python % & to run the script in the background, but you can not get the output of the script.

Asynchronous command in Nvim/Vim
#

Fortunately, both Neovim and Vim provides the job feature to run external command asynchronously. However, to use those features, you have to write non-trivial amount of code. Thanks to plugins like vim-dispatch and asyncrun.vim, we can use this feature easily.

Asyncrun.vim
#

In this post, I would like to share how to set up asyncrun.vim and use it. First, you can install it with vim-plug:

Plug 'skywind3000/asyncrun.vim'

It provides the AsyncRun command to run external shell commands asynchronously. For example, to run the current Python script, you can use the following command:

" use quote to avoid spaces in file names
:AsyncRun python "%"

The above command will run current script in the background without blocking Neovim. You can still edit the source code as you will when the program is running..

Asyncrun.vim will put the output of the command in the quickfix list. To see the command output, use :copen to open the quickfix window. You can also set up a config to open the quickfix window automatically when you use AsyncRun. Just add the following setting to your init.vim or vimrc:

let g:asyncrun_open = 6

Then a quickfix window of 6 line tall will be opened automatically after asyncrun starts.

Python related issues#

Command output encoding
#

When you use asyncrun.vim on Windows, you may find that Chinese characters may not be displayed properly in the quickfix window. That is because the command output encoding on Windows may not be the same with the encoding you use (suppose you are using utf-8 encoding). You can set up the variable g:asyncrun_encs to gbk encoding to solve this issue:

if has('win32')
    " Command output encoding for Windows
    let g:asyncrun_encs = 'gbk'
endif

Then Chinese characters should display properly.

Display command output in real time
#

When python script is running in background, the output is buffered, i.e., you can not see the script output immediately after a print() statement is executed. You will only see the output after cache buffer is full or when the script finishes execution. There are two easy ways to fix this issue.

The first is to add PYTHONUNBUFFERED variable in your init.vim or vimrc:

let PYTHONUNBUFFERED=1

Or you need to run python command with -u option:

:AsyncRun python -u "%"

We can also create a shortcut to execute script quickly:

augroup python_file
    autocmd!
    autocmd FileType python nnoremap <F9> :AsyncRun python -u "%"<CR>
augroup END

References
#

Related

Creating Markdown Front Matter with Ultisnips
··567 words·3 mins
How to Create Proper Folding for Vim/Nvim Configuration
··1050 words·5 mins
Exclusive and Inclusive Motion in Neovim/Vim
··426 words·2 mins