A Neovim plugin that provides a stateful task system focused on integration with build systems.
Tasks in this plugin are provided by modules that implement functionality for a specific build system. Modules can have custom parameters which user can set via :Task set_module_param
(like current target or build type). Tasks consists of one or more commands and have args
and env
parameters to set arguments and environment variable respectively. All this settings are serializable and will be stored in configuration file in your project directory.
- Necessary
- plenary.nvim for internal helpers.
- Optional
- nvim-dap - for debugging.
- Output directly into quickfix for fast navigation.
- Tasks provided by modules which can have custom parameters.
- Modules are lazy loaded.
- Module for a task name could be determined automatically based on its condition.
- Tasks can run through debugger.
- Tasks can be chained and react on the previous output.
- Task and module parameters are serializable and specific to the current working directly.
- Tasks arguments could be read from parameters and / or extended via additional temporary arguments passed to
:Task
command.
- CMake via cmake-file-api.
- Cargo.
- GNU Make
You can also write your own module.
Use the command :Task
with one of the following arguments:
Argument(s) | Description |
---|---|
start <module> <task> |
Starting a task from a module. |
set_module_param <module> <param> |
Set parameter for a module. All parameters are module-specific. |
set_task_param <module> <param> <task> |
Set parameter for a task from a module. The parameter can be arg or env . |
cancel |
Cancel currently running task. |
Modules and tasks will be autocompleted.
Module name can be auto
, in which case the first module that satisfies the condition will be used.
To configure the plugin, you can call require('tasks').setup(values)
, where values
is a dictionary with the parameters you want to override. Here are the defaults:
local Path = require('plenary.path')
require('tasks').setup({
default_params = { -- Default module parameters with which `neovim.json` will be created.
cmake = {
cmd = 'cmake', -- CMake executable to use, can be changed using `:Task set_module_param cmake cmd`.
build_dir = tostring(Path:new('{cwd}', 'build', '{os}-{build_type}')), -- Build directory. The expressions `{cwd}`, `{os}` and `{build_type}` will be expanded with the corresponding text values. Could be a function that return the path to the build directory.
build_type = 'Debug', -- Build type, can be changed using `:Task set_module_param cmake build_type`.
dap_name = 'lldb', -- DAP configuration name from `require('dap').configurations`. If there is no such configuration, a new one with this name as `type` will be created.
args = { -- Task default arguments.
configure = { '-D', 'CMAKE_EXPORT_COMPILE_COMMANDS=1', '-G', 'Ninja' },
},
},
},
save_before_run = true, -- If true, all files will be saved before executing a task.
params_file = 'neovim.json', -- JSON file to store module and task parameters.
quickfix = {
pos = 'botright', -- Default quickfix position.
height = 12, -- Default height.
},
dap_open_command = function() return require('dap').repl.open() end, -- Command to run after starting DAP session. You can set it to `false` if you don't want to open anything or `require('dapui').open` if you are using https://github.com/rcarriga/nvim-dap-ui
- Open a CMake project.
- Run
configuration
task using:Task start cmake configure
. - Select a target by specifying module parameter with
:Task set_module_param cmake target
. All module parameters are specific to modules. Since CMake can't run targets like Cargo, we introduced a parameter to select the same target for building (appropriate arguments will be passed to CMake automatically) and running. - Optionally set arguments using
:Task set_task_param cmake run
. - Build and run the project via
:Task start cmake run
or build and debug using:Task start cmake debug
. You can pass additional arguments to these commands, which will be temporarily added to the arguments from the previous step.
- Open a Cargo project.
- Optionally set arguments using
:Task set_task_param cargo run
. - Optionally set global cargo arguments using
:Task set_task_param cargo global_cargo_args
. - Build and run the project via
:Task start cargo run
or build and debug using:Task start cargo debug
.
Cargo module doesn't have a target
param which specific to CMake because cargo run
automatically pick the binary. If there is multiple binaries, you can set which one you want to run using --bin
or --project
in step 2 as you do in CLI.
- Open a Make project.
- Run a Make target
<target>
with:Task start make <target>
.
To override targets or add custom make
options, configure the appropriate task:
require('tasks').setup({
default_params = {
...
make = {
cmd = 'make',
args = {
all = { '-j10', 'all' }, -- :Task start make all → make -j10 all
build = {}, -- :Task start make build → make
nuke = { 'clean' }, -- :Task start make nuke → make clean
},
},
...
}
})
To create a module just put a lua file under lua/tasks/modules
in your configuration or submit your module as a PR. In this module you need to return a table with the following fields:
{
params = {
-- A table of parameter names. Possible values:
'parameter_name1', -- A string parameter, on setting user will be prompted with vim.ui.input.
parameter_name2 = { 'one', 'two' }, -- A table with possible values, on setting user will be prompted with vim.ui.select to pick one of these values.
parameter_name3 = func, -- A function that generates a string or a table.
}
condition = function() return Path:new('file'):exists() end -- A function that returns `true` if this module could be applied to this directory. Used when `auto` is used as module name.
tasks = {
-- A table of module tasks. Possible values:
task_name1 = {
-- Required parameters:
cmd = 'command' -- Command to execute.
-- Optional parameters:
cwd = 'directory' -- Command working directory. Default to current working directory.
after_success = callback -- A callback to execute on success.
dap_name = 'dap_name' -- A debug adapter name. If exists, the task will be launched through the adapter. Usually taken from a module parameter. Implies ignoring all streams below.
-- Disable a stream output to quickfix. If both are disabled, quickfix will not show up. If you want to capture output of a stream in a next task, you need to disable it.
ignore_stdout = true,
ignore_stderr = true,
},
task_name2 = func1, -- A function that returns a table as above. Accepts configuration for this module and previous job.
task_name3 = { func2, func3 }, -- A list of functions as above. Tasks will be executed in chain.
}
}
For a more complex example take a look at cargo.lua.
You can also edit existing modules in right in your config. Just import a module using require('tasks.modules.module_name')
and add/remove/modify any fields from the above.