https://github.com/pewpewnor/pilot.nvim
✈️ Run your projects and files quickly with keybindings, and configure how to run them on the fly!
https://github.com/pewpewnor/pilot.nvim
Last synced: 10 days ago
JSON representation
✈️ Run your projects and files quickly with keybindings, and configure how to run them on the fly!
- Host: GitHub
- URL: https://github.com/pewpewnor/pilot.nvim
- Owner: pewpewnor
- License: apache-2.0
- Created: 2025-03-20T04:30:21.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2025-04-07T17:50:28.000Z (12 days ago)
- Last Synced: 2025-04-07T18:43:46.319Z (12 days ago)
- Language: Lua
- Homepage:
- Size: 65.4 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
- trackawesomelist - pewpewnor/pilot.nvim (⭐2) - Run your projects and files quickly with keybindings, and configure how to run them on the fly. (Recently Updated / [Apr 09, 2025](/content/2025/04/09/README.md))
- awesome-neovim-sorted - pewpewnor/pilot.nvim
- awesome-neovim-sorted - pewpewnor/pilot.nvim
README
# ✈️ pilot.nvim

A Neovim plugin that allows you to **run** your **project or file** based
on the **custom JSON run configuration file** that you wrote on the go. You can
have one JSON file for each file type and one (or instead use fallback) JSON
file for each project._Requirements: Neovim v0.11.0_

## Motivation
I wanted a code runner plugin with placeholder interpolation so that I can hit a
single key to compile/build and run my code with full control over the commands.## Features
- Run arbritrary command to run, test, and debug any file or project.
- Placeholders for current file path, file name, directory name, cwd name, etc.
- You can adjust it on the fly without needing to reload Neovim everytime.
- Supports fallback project run configuration so you don't have to create the
same JSON run configuration for each project
- It is possible to compile code and run the program afterwards.
- Customizable path/location for your project and file run configurations.
- Customizable location of command execution (presets are also provided).
- Bindable functions to run, edit, and remove your project and file type
run configuration.## Installation
Using [lazy.nvim](https://github.com/folke/lazy.nvim)
```lua
-- init.lua:
{ "pewpewnor/pilot.nvim", opts = {} }-- plugins/pilot.lua:
return {
"pewpewnor/pilot.nvim",
opts = {}
}
--or
return {
"pewpewnor/pilot.nvim",
config = function()
require("pilot").setup()
end
}
```Using [packer.nvim](https://github.com/wbthomason/packer.nvim)
```lua
use {
"pewpewnor/pilot.nvim",
config = function()
require("pilot").setup()
end
}
```### General terms
- Project run config -> the customizable JSON file containing your commands to
run the current project.
- File type run config -> the customizable JSON file containing your commands to
run the current file based on the file type.## Default configuration
There is no need to pass anything to the `setup` function if you don't want to
change any of the options.```lua
{
project_run_config_path = nil, -- string | nil -> by default equivalent to "{{pilot_data_path}}/projects/{{hash(cwd_path)}}.json"
file_type_run_config_path = nil, -- string | nil -> by default equivalent to "{{pilot_data_path}}/filetypes/{{file_type}}.json"
-- if there is only one command listed, should we immediately run the command?
automatically_run_single_command = {
project = true, -- boolean
file_type = true, -- boolean
},
fallback_project_run_config = nil, -- (function that returns a string) | nil
custom_locations = nil, -- (key/value table with the values being strings) | nil
}
```> [!NOTE]
> Check out the [configurations documentation section](docs/pilot.md#configuration-options)
> to see every possible configuration options for the setup function.## Example customization
```lua
local pilot = require("pilot")
pilot.setup({
-- grab the pilot configuration from the current working directory instead
-- of automatically generating one
project_run_config_path = "{{cwd_path}}/pilot.json",
-- will be used instead if there is no project run config file
-- at the path specified in the 'project_run_config_path' option
fallback_project_run_config = function()
-- you can customize this logic
-- e.g. if the project has 'package-lock.json', then use our
-- 'npm_project.json' as the project run config
if vim.fn.filereadable(vim.fn.getcwd() .. "/package-lock.json") == 1 then
return "{{pilot_data_path}}/npm_project.json"
-- e.g. if the project has CMakeLists.txt, then we will use our
-- 'cmake_project.json' as our project run config
elseif vim.fn.filereadable(vim.fn.getcwd() .. "/CMakeLists.txt") == 1 then
return "/home/user/templates/cmake_project.json"
end
end,
-- define custom locations that can be used in any pilot run config
custom_locations = {
-- custom location that executes the command in a new tmux window
tmux_new_window = function(command)
vim.fn.system("tmux new-window -d")
vim.fn.system("tmux send-keys -t +. '" .. command .. "' Enter")
end,
},
})-- customize these keybindings to your liking
vim.keymap.set("n", "xp", pilot.run_project)
vim.keymap.set("n", "xf", pilot.run_file_type)
vim.keymap.set("n", "xl", pilot.run_last_executed_task)
vim.keymap.set("n", "ep", pilot.edit_project_run_config)
vim.keymap.set("n", "ef", pilot.edit_file_type_run_config)-- example of creating vim user commands for pilot functions
vim.api.nvim_create_user_command("PilotDeleteProjectRunConfig",
pilot.delete_project_run_config, { nargs = 0, bar = false })
vim.api.nvim_create_user_command("PilotDeleteFileTypeRunConfig",
pilot.delete_file_type_run_config, { nargs = 0, bar = false })
```> [!NOTE]
> Check out the [functions documentation section](docs/pilot.md#functions) to
> see the details of every pilot functions.## Example project run config
As an example, if you set your `project_run_config_path` as
"{{cwd_path}}/pilot.json", then here is what the _pilot.json_'s file content may
look like.> [!TIP]
> Use the mustache syntax like `{{cword}}` to insert a placeholder that will
> automatically be replaced by pilot.nvim on the fly!```json
[
{
"name": "run specific test (cursor hover over the function name)",
"command": "go test -v --run {{cword}}"
},
{
"name": "build & run project",
"command": "make build && make run"
},
{
"command": "ls {{dir_path}}",
"location": "tmux_new_window"
}
]
```## Example file type run config
Let's say you want to write a file type run config for compiling and running any
file that has "c" as the vim file type (the c programming language).> [!TIP]
> For each entry, you don't have to specify a display name if you want it to be
> the same as the literal command. You can also instead use a string for
> defining an entry/command.```json
[
{
"name": "clang",
"command": "clang {{file_path_relative}} && ./a.out"
},
"gcc {{file_path}} -o {{file_name_no_extension}} ; ./{{file_name_no_extension}}"
]
```> [!NOTE]
> Check out the [run config documentation section](docs/pilot.md#run-config) to
> see the JSON format for project and file type run configs even further.> [!NOTE]
> The project run config and the file type run config use the exact same JSON
> format.## Placeholders
| Placeholder | Resolved value |
| ---------------------------- | ---------------------------------------------------------------------------- |
| `{{file_path}}` | Absolute file path of the current buffer |
| `{{file_path_relative}}` | Current buffer's file path that is relative to the current working directory |
| `{{file_name}}` | Current buffer's file name (file extension included) |
| `{{file_name_no_extension}}` | Current buffer's file name without the file extension |
| `{{file_type}}` | The filetype of the current buffer according to Neovim (`vim.bo.filetype`) |
| `{{file_extension}}` | Extension of the current file |
| `{{dir_path}}` | Absolute path of the directory that contains the current buffer |
| `{{dir_name}}` | Name of the directory that contains the current buffer |
| `{{cwd_path}}` | Absolute path of the current working directory (`vim.fn.getcwd()`) |
| `{{cwd_name}}` | The directory name of the current working directory |
| `{{pilot_data_path}}` | Absolute path to `vim.fn.stdpath("data") .. "/pilot"` |
| `{{cword}}` | Current word of which your cursor is hovering over |
| `{{cWORD}}` | Current complete word (between spaces) of which your cursor is hovering over |
| `{{hash(cwd_path)}}` | Hash of the current working directory absolute path using sha256 |
| `{{hash(file_path)}}` | Hash of the current buffer's absolute path using sha256 |## Preset executors
| Executor | Description |
| ------------------------------------------------ | ----------------------------------------------------------------------- |
| `pilot.nvim_terminal_new_tab_executor` (default) | Run the command in a new Neovim tab with Neovim's integrated terminal |
| `pilot.nvim_terminal_current_buffer_executor` | Run the command in the current buffer with Neovim's integrated terminal |
| `pilot.print_executor` | Run the command with the output shown using the print function |
| `pilot.background_executor` | Run the command with no output displayed |Simply set the `default_executor` option in your configuration to use one of the
above.
You can also create your own default executor like this:```lua
{
default_executor = function(command)
vim.fn.system(command)
end
}
```The example code above is actually the implementation of
`pilot.background_executor`.> [!NOTE]
> There is no need to escape the command, pilot.nvim already does it for you 😉### Got questions or have any ideas on how to improve this plugin?
Check out our [github discussions page](https://github.com/pewpewnor/pilot.nvim/discussions)
or simply create a new issue!