Extensible code-runner/project-configurator.
Manage Tasks, Databases, Tests and Debug Configurations in One Place!
Projector is a tool which manages configuration objects (lua key-value tables - see here), which have a different meaning depening on the used output.
These configuration objects are loaded from different sources using loaders
(see here), preprocessed by output builders and later used as
outputs.
For example, configuration object is loaded from tasks.json file, task
output builder preprocessor finds it compatible with it's output, so the task is
visible in the UI. When the user selects to run this task, it is sent to task
output.
Here approximately how this looks like:
LOADERS OUTPUT BUILDERS
┌──────────────┐ ┌──────────┐
│ │ │ │
│ tasks.json ├── 1 ────┐ ┌── has ───► task ──┐
│ │ object │ │ command? │ │ │
└──────────────┘ │ │ └──────────┘ │
│ │ │
┌──────────────┐ │ │ ┌──────────┐ │
│ │ │ │ │ │ │
│ launch.json ├── 3 ────┼───┼── can ──►│ debug ──┼─► - ... (task)
│ │ objects │ │ debug? │ │ │ - ... (task|debug)
└──────────────┘ │ │ └──────────┘ │ - ... (database) ───► run
│ │ │ - ... (task) │
┌──────────────┐ │ │ ┌──────────┐ │ │
│ │ │ │ │ │ │ │
│ package.json ├── 2 ────┘ └── has ───► database ──┘ ▼
│ │ objects connection?│ │ open dadbod ui
└──────────────┘ └──────────┘
Click to expand
use {
"kndndrj/nvim-projector",
requires = {
-- required:
"MunifTanjim/nui.nvim",
-- optional extensions:
"kndndrj/projector-neotest",
-- dependencies of extensions:
"nvim-neotest/neotest",
},
config = function()
require("projector").setup(--[[optional config]])
end,
}Click to expand
{
"kndndrj/nvim-projector",
dependencies = {
-- required:
"MunifTanjim/nui.nvim",
-- optional extensions:
"kndndrj/projector-neotest",
-- dependencies of extensions:
"nvim-neotest/neotest",
},
config = function()
require("projector").setup(--[[optional config]])
end,
},You can pass an optional table parameter to setup() function.
Here are the defaults:
-
Call the
setup()function with an optional config parameter. -
Map these functions to keys of your choice:
require"projector".continue() require"projector".toggle() require"projector".next() require"projector".previous() require"projector".restart() require"projector".kill()
-
continuefunction is a direct replacement fornvim-dapand the main entrypoint to this plugin. So replace this:require"dap".continue()
With this:
require"projector".continue()
The configuration object is a base unit of projector and it is nothing more than a simple hashmap.
A few fields have a special or global meaning (see snippet below), other than
that, the meaning of fields is determined by the outputs.
For example: dadbod output doesn't care about command, port or env
fields, but dap output does. This means that a configuration object with just
the forementioned fields can be ran in dap output mode, but not in dadbod
output mode (additional ref with :h projector.ref.task).
{
-- These have special "global" meaning:
id = "specific.task.id" -- ID is optional, but can be useful for specifying dependencies
name = "Task", -- task's name
dependencies = { -- list of task ids to run before this one
"setup.some.stuff",
"setup.some.more.stuff"
},
after = "cleanup.task.id", -- task id to run after this one is finished
evaluate = "task", -- run this config in "task" mode immedialtely after loading
children = { -- nesting is also supported
{
name = "...",
-- ... other config fields
},
}
}Loaders provide configuration objects from various sources. You can control which sources to use using the setup function:
require("projector").setup {
loaders = {
require("projector.loaders").BuiltinLoader:new()
require("projector.loaders").DapLoader:new( ),
-- ...
},
}There are a few loaders that are built-in:
BuiltinLoader- loads configs fromprojector.json. The tasks can also be specifies in lua config.DapLoader- loadsdap.configurations
If you want to create your own loader, implement the Loader interface
(:h projector.ref.loaders).
Outputs are modules that recieve a configuration object and run it's commands (show the output on screen). Output Builders on the other hand provide a means to build those outputs. As a user, you only need to care about providing output builders in the config:
require("projector").setup {
outputs = {
require("projector.outputs").TaskOutputBuilder:new(),
require("projector.outputs").DadbodOutputBuilder:new(),
require("projector.outputs").DapOutputBuilder:new(),
},
}You can pick form a few built-ins...
TaskOutputBuilderbuilds a terminal output, which runs a shell commandDapOutputBuilderbuilds an output which runsnvim-dapDadbodOutputBuilderpicksdatabaseandqueryfields from all loaded configs and provieds a single task that opensvim-dadbod-ui
Or you can choose to implement your own (:h projector.ref.outputs)
Here is a list of available extensions, which provide different outputs and loaders:

