SkillAgentSearch skills...

Asynctasks.vim

:rocket: Modern Task System for Project Building, Testing and Deploying !!

Install / Use

/learn @skywind3000/Asynctasks.vim

README

asynctasks.vim - modern task system

The generic way to handle building/running/testing/deploying tasks by imitating vscode's task system.

GitHub license Maintenance Join the chat at https://gitter.im/skywind3000/asynctasks.vim

<!-- TOC --> <!-- /TOC -->

This readme is also available in:

Introduction

As vim 8.0 was released in 2017, we have got many wonderful plugins like LSP, DAP, and asynchronous linters. Even things like vimspector, which could only be imagined in emacs in the past, now become a reality in vim.

However, vim still lack an elegant task system to speed up your inner software development cycle (edit, compile, test). Many people are still dealing with those building, testing, and deploying tasks in such a primitive or flaky way. Therefore, I decided to create this plugin and introduce vscode's task-like mechanisms to vim.

Vscode creates a .vscode folder in your project root directory and uses a .vscode/tasks.json file to define project-specific tasks. Similar, asynctasks.vim uses a .tasks file in your project folders for local tasks and uses ~/.vim/tasks.ini to define global tasks for generic projects.

This is very simple, but most good designs always start from simple concepts. You will benefit a lot from the productivity and possibility of this task system.

Get Started

Installation

Install with vim-plug:

Plug 'skywind3000/asynctasks.vim'
Plug 'skywind3000/asyncrun.vim'

It requires asyncrun.vim 2.4.0 or above. Don't forget to setup:

let g:asyncrun_open = 6

And quickfix window can be opened automatically, otherwise you can't see the task output unless using :copen manually.

Build and run a single file

It's convenient for me to build and run a single file directly without creating a new project for that if I want to try some small and new ideas. In this circumstance, we can use :AsyncTaskEdit command to edit the .tasks configuration file in your current project root directory:

[file-build]
# macros in the "$(...)" form will be substituted, 
# shell command, use quotation for filenames containing spaces
command=gcc -O2 "$(VIM_FILEPATH)" -o "$(VIM_FILEDIR)/$(VIM_FILENOEXT)"
# working directory
cwd=$(VIM_FILEDIR)

[file-run]
command="$(VIM_FILEDIR)/$(VIM_FILENOEXT)"
cwd=$(VIM_FILEDIR)
# output mode: run in a terminal
output=terminal

There are two tasks file-build and file-run defined in this .tasks file. Then from the directory where this .tasks reside and its child directories, you can use:

:AsyncTask file-build
:AsyncTask file-run

To build and run the current file:

This is the result of :AsyncTask file-build, the command output displays in the quickfix window and errors are matched with errorformat. You can navigate the command output in the quickfix window or use :cnext/:cprev to jump between errors.

There are many macros can be used in the command field and will be expanded and replaced when task starts. Having a fast, low-friction Edit/Build/Test cycle is one of the best and easiest ways to increase developer productivity, so we will map them to F5 and F9:

noremap <silent><f5> :AsyncTask file-run<cr>
noremap <silent><f9> :AsyncTask file-build<cr>

Put the code above in your vimrc and you can have F9 to compile current file and F5 to run it. And you may ask, this is for C/C++ only, what if you want to run a python script, should you create a new task file-run-python ? Totally unnecessary, commands can match with file types:

[file-run]
command="$(VIM_FILEPATH)"
command:c,cpp="$(VIM_PATHNOEXT)"
command:go="$(VIM_PATHNOEXT)"
command:python=python "$(VIM_FILENAME)"
command:javascript=node "$(VIM_FILENAME)"
command:sh=sh "$(VIM_FILENAME)"
command:lua=lua "$(VIM_FILENAME)"
command:perl=perl "$(VIM_FILENAME)"
command:ruby=ruby "$(VIM_FILENAME)"
output=terminal
cwd=$(VIM_FILEDIR)
save=2

The command followed by a colon accepts file type list separated by comma. If the current file type cannot be matched, the default command will be used. The -save=2 represents to save all modified buffers before running the task.

At this point, you can have your F5 to run all type of files. And plugins like quickrun can be obsoleted immediately, they can't do better than this. Then we continue to polish file-build to support more file types:

[file-build]
command:c,cpp=gcc -O2 -Wall "$(VIM_FILEPATH)" -o "$(VIM_PATHNOEXT)" -lstdc++ -lm -msse3
command:go=go build -o "$(VIM_PATHNOEXT)" "$(VIM_FILEPATH)"
command:make=make -f "$(VIM_FILEPATH)"
output=quickfix
cwd=$(VIM_FILEDIR)
save=2

Again, F9 can be used to compile many file types, same keybind, different command. This two tasks can be defined in local .tasks and work for the project scope or in the ~/.vim/tasks.ini and work for all project. Much more elegant than using the old &makeprg or calling asyncrun/neomake with a lot if/else in your vimrc.

Tasks for running compilers or grep may set output=quickfix (default), because the output can use errorformat to match errors in the quickfix window, while tasks for running your file/project may set output=terminal.

When you set output to terminal, you can further specify what type of terminal do you want to use exactly, like: a simulated terminal in quickfix window (without matching the errorformat)? the triditional ! command in vim? the internal terminal ? an external terminal window ? or in a tmux split window ?? The detail will be discussed later.

Build and run a project

If you want to do something with a project, you must figure out where the project locates. asynctasks.vim and its backend asyncrun.vim choose a widely used method called root markers to indentify the project root directory. The project root is one of the nearest parent directory containing these markers:

let g:asyncrun_rootmarks = ['.git', '.svn', '.root', '.project', '.hg']

If none of the parent directories contains these root markers, the directory of the current file is used as the project root.

There is a corner case: if current buffer is not a normal file buffer (eg. a tool window) or is an unnamed new buffer, vim's current working directory (which :pwd returns) will be used as the project root.

Once we got the project location, the macro $(VIM_ROOT), or its alias <root>, can be used to represent the project root:

What if your current project is not in any git/subversion repository ? How to find out where is my project root ? The solution is very simple, just put an empty .root file in your project root, it ha

View on GitHub
GitHub Stars937
CategoryDevelopment
Updated11d ago
Forks31

Languages

Vim Script

Security Score

100/100

Audited on Mar 20, 2026

No findings