plugins/neotest: init

This commit is contained in:
Gaetan Lepage 2023-11-22 09:38:52 +01:00 committed by Gaétan Lepage
parent 0ee062ed74
commit 975f1ca526
20 changed files with 916 additions and 2 deletions

View file

@ -30,6 +30,8 @@
./completion/lspkind.nix
./completion/cmp
./dap
./filetrees/chadtree.nix
./filetrees/neo-tree.nix
./filetrees/nvim-tree.nix
@ -90,9 +92,9 @@
./lsp/trouble.nix
./lsp/wtf.nix
./none-ls
./neotest
./dap
./none-ls
./pluginmanagers/packer.nix
./pluginmanagers/lazy.nix

View file

@ -0,0 +1,55 @@
# List of adapter names (without the `neotest-` prefix).
# The corresponding `pkgs.vimPlugins.neotest-NAME` package has to exist.
# When adding a new adapter, update the tests accordingly:
# - Add the adapter to `all-adapters` in `tests/test-sources/plugins/neotest/default.nix`
# - Add a more complete test case in `tests/test-sources/plugins/neotest/NAME.nix`
{
dart = {
treesitter-parser = "dart";
};
deno = {
treesitter-parser = "javascript";
};
dotnet = {
treesitter-parser = "c_sharp";
};
elixir = {
treesitter-parser = "elixir";
};
go = {
treesitter-parser = "go";
};
haskell = {
treesitter-parser = "haskell";
};
jest = {
treesitter-parser = "javascript";
};
pest = {
treesitter-parser = "php";
};
phpunit = {
treesitter-parser = "php";
};
plenary = {
treesitter-parser = "lua";
};
python = {
treesitter-parser = "python";
};
rspec = {
treesitter-parser = "ruby";
};
rust = {
treesitter-parser = "rust";
};
scala = {
treesitter-parser = "scala";
};
testthat = {
treesitter-parser = "r";
};
vitest = {
treesitter-parser = "javascript";
};
}

View file

@ -0,0 +1,46 @@
{
lib,
config,
helpers,
pkgs,
...
}:
with lib; let
supportedAdapters = import ./adapters-list.nix;
mkAdapter = name: props: {
options.plugins.neotest.adapters.${name} = {
enable = mkEnableOption name;
package = helpers.mkPackageOption name pkgs.vimPlugins."neotest-${name}";
settings = helpers.mkSettingsOption {
description = "settings for the `${name}` adapter.";
};
};
config = let
cfg = config.plugins.neotest.adapters.${name};
in
mkIf cfg.enable {
extraPlugins = [cfg.package];
warnings =
optional
(!config.plugins.treesitter.enable)
''
Nixvim (plugins.neotest.adapters.${name}): This adapter requires `treesitter` to be enabled.
You might want to set `plugins.treesitter.enable = true` and ensure that the `${props.treesitter-parser}` is enabled.
'';
plugins.neotest.enabledAdapters = [
{
inherit name;
inherit (cfg) settings;
}
];
};
};
in {
imports = mapAttrsToList mkAdapter supportedAdapters;
}

View file

@ -0,0 +1,75 @@
{
lib,
helpers,
config,
pkgs,
...
}:
with lib;
helpers.neovim-plugin.mkNeovimPlugin config {
name = "neotest";
defaultPackage = pkgs.vimPlugins.neotest;
maintainers = [maintainers.GaetanLepage];
imports = [
./adapters.nix
];
extraOptions = {
enabledAdapters = mkOption {
type = with types;
listOf
(submodule {
options = {
name = mkOption {
type = types.str;
};
settings = mkOption {
type = with types; attrsOf anything;
};
};
});
internal = true;
visible = false;
default = [];
};
};
settingsOptions =
(import ./options.nix {inherit lib helpers;})
// {
adapters = mkOption {
type = with helpers.nixvimTypes; listOf strLua;
default = [];
internal = true;
apply = map helpers.mkRaw;
};
};
settingsExample = {
quickfix.enabled = false;
output = {
enabled = true;
open_on_run = true;
};
output_panel = {
enabled = true;
open = "botright split | resize 15";
};
};
extraConfig = cfg: {
plugins.neotest.settings.adapters =
map
(
adapter: let
settingsString =
optionalString
(adapter.settings != {})
"(${helpers.toLuaObject adapter.settings})";
in "require('neotest-${adapter.name}')${settingsString}"
)
cfg.enabledAdapters;
};
}

233
plugins/neotest/options.nix Normal file
View file

@ -0,0 +1,233 @@
{
lib,
helpers,
}:
with lib; {
#################################################
# CoreConfig
discovery = {
enabled = helpers.defaultNullOpts.mkBool true "Enable discovery.";
concurrent = helpers.defaultNullOpts.mkUnsignedInt 0 ''
Number of workers to parse files concurrently.
0 automatically assigns number based on CPU.
Set to 1 if experiencing lag.
'';
filter_dir = helpers.mkNullOrLuaFn ''
`fun(name: string, rel_path: string, root: string): boolean`
A function to filter directories when searching for test files.
Receives the name, path relative to project root and project root path.
'';
};
running = {
concurrent = helpers.defaultNullOpts.mkBool true ''
Run tests concurrently when an adapter provides multiple commands to run.
'';
};
default_strategy = helpers.defaultNullOpts.mkStr "integrated" ''
The default strategy.
'';
#################################################
# Config
log_level = helpers.defaultNullOpts.mkLogLevel "warn" ''
Minimum log levels.
'';
consumers = helpers.defaultNullOpts.mkAttrsOf helpers.nixvimTypes.rawLua "{}" ''
key: string
value: lua function
'';
icons =
helpers.defaultNullOpts.mkAttrsOf (with types; either str (listOf str))
''
{
child_indent = "";
child_prefix = "";
collapsed = "";
expanded = "";
failed = "";
final_child_indent = " ";
final_child_prefix = "";
non_collapsible = "";
passed = "";
running = "";
running_animated = ["/" "|" "\\" "-" "/" "|" "\\" "-"];
skipped = "";
unknown = "";
watching = "";
}
''
"Icons used throughout the UI. Defaults use VSCode's codicons.";
highlights =
helpers.defaultNullOpts.mkAttrsOf types.str
''
{
adapter_name = "NeotestAdapterName";
border = "NeotestBorder";
dir = "NeotestDir";
expand_marker = "NeotestExpandMarker";
failed = "NeotestFailed";
file = "NeotestFile";
focused = "NeotestFocused";
indent = "NeotestIndent";
marked = "NeotestMarked";
namespace = "NeotestNamespace";
passed = "NeotestPassed";
running = "NeotestRunning";
select_win = "NeotestWinSelect";
skipped = "NeotestSkipped";
target = "NeotestTarget";
test = "NeotestTest";
unknown = "NeotestUnknown";
watching = "NeotestWatching";
}
''
"";
floating = {
border = helpers.defaultNullOpts.mkStr "rounded" "Border style.";
max_height = helpers.defaultNullOpts.mkNullable (types.numbers.between 0.0 1.0) "0.6" ''
Max height of window as proportion of NeoVim window.
'';
max_width = helpers.defaultNullOpts.mkNullable (types.numbers.between 0.0 1.0) "0.6" ''
Max width of window as proportion of NeoVim window.
'';
options = helpers.defaultNullOpts.mkAttrsOf types.anything "{}" ''
Window local options to set on floating windows (e.g. winblend).
'';
};
strategies = {
integrated = {
height = helpers.defaultNullOpts.mkUnsignedInt 40 ''
height to pass to the pty running commands.
'';
width = helpers.defaultNullOpts.mkUnsignedInt 120 ''
Width to pass to the pty running commands.
'';
};
};
summary = {
enabled = helpers.defaultNullOpts.mkBool true "Whether to enable summary.";
animated = helpers.defaultNullOpts.mkBool true "Enable/disable animation of icons.";
follow = helpers.defaultNullOpts.mkBool true "Expand user's current file.";
expandErrors = helpers.defaultNullOpts.mkBool true "Expand all failed positions.";
mappings =
helpers.defaultNullOpts.mkAttrsOf (with types; either str (listOf str))
''
{
attach = "a";
clear_marked = "M";
clear_target = "T";
debug = "d";
debug_marked = "D";
expand = ["<CR>" "<2-LeftMouse>"];
expand_all = "e";
jumpto = "i";
mark = "m";
next_failed = "J";
output = "o";
prev_failed = "K";
run = "r";
run_marked = "R";
short = "O";
stop = "u";
target = "t";
watch = "w";
}
''
"Buffer mappings for summary window.";
open = helpers.defaultNullOpts.mkStr "botright vsplit | vertical resize 50" ''
A command or function to open a window for the summary.
Either a string or a function that returns an integer.
'';
};
output = {
enabled = helpers.defaultNullOpts.mkBool true "Enable output.";
open_on_run = helpers.defaultNullOpts.mkNullable (with types; either str bool) "short" ''
Open nearest test result after running.
'';
};
output_panel = {
enabled = helpers.defaultNullOpts.mkBool true "Enable output panel.";
open = helpers.defaultNullOpts.mkStr "botright split | resize 15" ''
A command or function to open a window for the output panel.
Either a string or a function that returns an integer.
'';
};
quickfix = {
enabled = helpers.defaultNullOpts.mkBool true "Enable quickfix.";
open = helpers.defaultNullOpts.mkNullable (with types; either bool str) "`false`" ''
Set to true to open quickfix on startup, or a function to be called when the quickfix
results are set.
'';
};
status = {
enabled = helpers.defaultNullOpts.mkBool true "Enable status.";
virtual_text = helpers.defaultNullOpts.mkBool false "Display status using virtual text.";
signs = helpers.defaultNullOpts.mkBool true "Display status using signs.";
};
state = {
enabled = helpers.defaultNullOpts.mkBool true "Enable state.";
};
watch = {
enabled = helpers.defaultNullOpts.mkBool true "Enable watch.";
symbol_queries =
helpers.mkNullOrOption
(
with helpers.nixvimTypes;
attrsOf (maybeRaw str)
)
''
Treesitter queries or functions to capture symbols that are used for querying the LSP
server for definitions to link files.
If it is a function then the return value should be a list of node ranges.
'';
filter_path = helpers.mkNullOrLuaFn ''
`(fun(path: string, root: string): boolean)`
Returns whether the watcher should inspect a path for dependencies.
Default ignores paths not under root or common package manager directories.
'';
};
diagnostic = {
enabled = helpers.defaultNullOpts.mkBool true "Enable diagnostic.";
severity = helpers.defaultNullOpts.mkSeverity "error" ''
Diagnostic severity, one of `vim.diagnostic.severity`.
'';
};
}

View file

@ -0,0 +1,20 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.dart = {
enable = true;
settings = {
command = "flutter";
use_lsp = true;
custom_test_method_names = [];
};
};
};
};
};
}

View file

@ -0,0 +1,158 @@
{
empty = {
plugins.neotest.enable = true;
};
all-adapters = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters = {
dart.enable = true;
deno.enable = true;
dotnet.enable = true;
elixir.enable = true;
go.enable = true;
haskell.enable = true;
jest.enable = true;
pest.enable = true;
phpunit.enable = true;
plenary.enable = true;
python.enable = true;
rspec.enable = true;
rust.enable = true;
scala.enable = true;
testthat.enable = true;
vitest.enable = true;
};
};
};
};
defaults = {
plugins.neotest = {
enable = true;
adapters = {};
settings = {
discovery = {
enabled = true;
concurrent = 0;
filter_dir = null;
};
running = {
concurrent = true;
};
default_strategy = "integrated";
log_level = "warn";
consumers = {};
icons = {
child_indent = "";
child_prefix = "";
collapsed = "";
expanded = "";
failed = "";
final_child_indent = " ";
final_child_prefix = "";
non_collapsible = "";
passed = "";
running = "";
running_animated = ["/" "|" "\\" "-" "/" "|" "\\" "-"];
skipped = "";
unknown = "";
watching = "";
};
highlights = {
adapter_name = "NeotestAdapterName";
border = "NeotestBorder";
dir = "NeotestDir";
expand_marker = "NeotestExpandMarker";
failed = "NeotestFailed";
file = "NeotestFile";
focused = "NeotestFocused";
indent = "NeotestIndent";
marked = "NeotestMarked";
namespace = "NeotestNamespace";
passed = "NeotestPassed";
running = "NeotestRunning";
select_win = "NeotestWinSelect";
skipped = "NeotestSkipped";
target = "NeotestTarget";
test = "NeotestTest";
unknown = "NeotestUnknown";
watching = "NeotestWatching";
};
floating = {
border = "rounded";
max_height = 0.6;
max_width = 0.6;
options = {};
};
strategies = {
integrated = {
height = 40;
width = 120;
};
};
summary = {
enabled = true;
animated = true;
follow = true;
expandErrors = true;
mappings = {
attach = "a";
clear_marked = "M";
clear_target = "T";
debug = "d";
debug_marked = "D";
expand = ["<CR>" "<2-LeftMouse>"];
expand_all = "e";
jumpto = "i";
mark = "m";
next_failed = "J";
output = "o";
prev_failed = "K";
run = "r";
run_marked = "R";
short = "O";
stop = "u";
target = "t";
watch = "w";
};
open = "botright vsplit | vertical resize 50";
};
output = {
enabled = true;
open_on_run = "short";
};
output_panel = {
enabled = true;
open = "botright split | resize 15";
};
quickfix = {
enabled = true;
open = false;
};
status = {
enabled = true;
virtual_text = false;
signs = true;
};
state = {
enabled = true;
};
watch = {
enabled = true;
symbol_queries = null;
filter_path = null;
};
diagnostic = {
enabled = true;
severity = "error";
};
};
};
};
}

View file

@ -0,0 +1,30 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.dotnet = {
enable = true;
settings = {
dap = {
args = {justMyCode = false;};
adapter_name = "netcoredbg";
};
custom_attributes = {
xunit = ["MyCustomFactAttribute"];
nunit = ["MyCustomTestAttribute"];
mstest = ["MyCustomTestMethodAttribute"];
};
dotnet_additional_args = [
"--verbosity detailed"
];
discovery_root = "project";
};
};
};
};
};
}

View file

@ -0,0 +1,27 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.elixir = {
enable = true;
settings = {
mix_task = ["my_custom_task"];
extra_formatters = ["ExUnit.CLIFormatter" "ExUnitNotifier"];
extra_block_identifiers = ["test_with_mock"];
args = ["--trace"];
post_process_command.__raw = ''
function(cmd)
return vim.tbl_flatten({{"env", "FOO=bar"}, cmd})
end
'';
write_delay = 1000;
};
};
};
};
};
}

View file

@ -0,0 +1,21 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.go = {
enable = true;
settings = {
experimental = {
test_table = true;
};
args = ["-count=1" "-timeout=60s"];
};
};
};
};
};
}

View file

@ -0,0 +1,26 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.haskell = {
enable = true;
settings = {
build_tools = [
"stack"
"cabal"
];
frameworks = [
"tasty"
"hspec"
"sydtest"
];
};
};
};
};
};
}

View file

@ -0,0 +1,25 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.jest = {
enable = true;
settings = {
jestCommand = "npm test --";
jestConfigFile = "custom.jest.config.ts";
env = {CI = true;};
cwd.__raw = ''
function(path)
return vim.fn.getcwd()
end
'';
};
};
};
};
};
}

View file

@ -0,0 +1,26 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.pest = {
enable = true;
settings = {
ignore_dirs = ["vendor" "node_modules"];
root_ignore_files = ["phpunit-only.tests"];
test_file_suffixes = ["Test.php" "_test.php" "PestTest.php"];
sail_enabled.__raw = "function() return false end";
sail_executable = "vendor/bin/sail";
pest_cmd = "vendor/bin/pest";
parallel = 16;
compact = false;
results_path.__raw = "function() return '/some/accessible/path' end";
};
};
};
};
};
}

View file

@ -0,0 +1,26 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.phpunit = {
enable = true;
settings = {
phpunit_cmd.__raw = ''
function()
return "vendor/bin/phpunit"
end
'';
root_files = ["composer.json" "phpunit.xml" ".gitignore"];
filter_dirs = [".git" "node_modules"];
env = {XDEBUG_CONFIG = "idekey=neotest";};
dap = null;
};
};
};
};
};
}

View file

@ -0,0 +1,18 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.plenary = {
enable = true;
settings = {
min_init = "./path/to/test_init.lua";
};
};
};
};
};
}

View file

@ -0,0 +1,27 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.python = {
enable = true;
settings = {
dap.justMyCode = false;
args = ["--log-level" "DEBUG"];
runner = "pytest";
python = ".venv/bin/python";
is_test_file.__raw = ''
function(file_path)
return true
end
'';
pytest_discover_instances = true;
};
};
};
};
};
}

View file

@ -0,0 +1,38 @@
{
defaults = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.rspec = {
enable = true;
settings = {
rspec_cmd.__raw = ''
function()
return vim.tbl_flatten({
"bundle",
"exec",
"rspec",
})
end
'';
root_files = ["Gemfile" ".rspec" ".gitignore"];
filter_dirs = [".git" "node_modules"];
transform_spec_path.__raw = ''
function(path)
return path
end
'';
results_path.__raw = ''
function()
return async.fn.tempname()
end
'';
};
};
};
};
};
}

View file

@ -0,0 +1,19 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.rust = {
enable = true;
settings = {
args = ["--no-capture"];
dap_adapter = "lldb";
};
};
};
};
};
}

View file

@ -0,0 +1,20 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.scala = {
enable = true;
settings = {
args = ["--no-color"];
runner = "bloop";
framework = "utest";
};
};
};
};
};
}

View file

@ -0,0 +1,22 @@
{
example = {
plugins = {
treesitter.enable = true;
neotest = {
enable = true;
adapters.vitest = {
enable = true;
settings = {
filter_dir.__raw = ''
function(name, rel_path, root)
return name ~= "node_modules"
end
'';
};
};
};
};
};
}