plugins/nonels: move to by-name

This commit is contained in:
Austin Horstman 2024-10-06 10:31:05 -05:00
parent 40cb7af2b9
commit fb677540e1
No known key found for this signature in database
9 changed files with 4 additions and 6 deletions

View file

@ -0,0 +1,91 @@
# mkSourcePlugin, returns a module
sourceType: sourceName:
{
config,
pkgs,
lib,
helpers,
...
}:
let
inherit (import ./packages.nix lib) packaged;
pkg = packaged.${sourceName};
loc = lib.toList pkg;
cfg = config.plugins.none-ls;
cfg' = config.plugins.none-ls.sources.${sourceType}.${sourceName};
in
{
options.plugins.none-ls.sources.${sourceType}.${sourceName} =
{
enable = lib.mkEnableOption "the ${sourceName} ${sourceType} source for none-ls";
# Support strLua for compatibility with the old withArgs option
settings = helpers.defaultNullOpts.mkStrLuaOr' {
type = with lib.types; attrsOf anything;
description = ''
Options provided to the `require('null-ls').builtins.${sourceType}.${sourceName}.with` function.
See upstream's [`BUILTIN_CONFIG`] documentation.
[`BUILTIN_CONFIG`]: https://github.com/nvimtools/none-ls.nvim/blob/main/doc/BUILTIN_CONFIG.md
'';
example = {
extra_filetypes = [ "toml" ];
disabled_filetypes = [ "lua" ];
extra_args = [
"-i"
"2"
"-ci"
];
};
};
}
# Only declare a package option if a package is required
// lib.optionalAttrs (packaged ? ${sourceName}) {
package = lib.mkOption (
{
type = lib.types.nullOr lib.types.package;
description =
"Package to use for ${sourceName}."
+ (lib.optionalString (pkg == null) (
"\n\n"
+ ''
Currently not packaged in nixpkgs.
Either set this to `null` and install ${sourceName} outside of nix,
or set this to a custom nix package.
''
));
}
// lib.optionalAttrs (pkg != null) {
default =
lib.attrByPath loc (lib.warn "${lib.concatStringsSep "." loc} cannot be found in pkgs!" null)
pkgs;
defaultText = lib.literalExpression "pkgs.${lib.concatStringsSep "." loc}";
}
);
};
# TODO: Added 2024-07-16; remove after 24.11
imports =
let
basePath = [
"plugins"
"none-ls"
"sources"
sourceType
sourceName
];
in
[ (lib.mkRenamedOptionModule (basePath ++ [ "withArgs" ]) (basePath ++ [ "settings" ])) ];
config = lib.mkIf (cfg.enable && cfg'.enable) {
plugins.none-ls.settings.sources = lib.mkDefault [
(
"require('null-ls').builtins.${sourceType}.${sourceName}"
+ lib.optionalString (cfg'.settings != null) ".with(${helpers.toLuaObject cfg'.settings})"
)
];
extraPackages = [ (cfg'.package or null) ];
};
}

View file

@ -0,0 +1,154 @@
{
lib,
helpers,
config,
options,
...
}:
with lib;
helpers.neovim-plugin.mkNeovimPlugin {
name = "none-ls";
originalName = "none-ls.nvim";
luaName = "null-ls";
package = "none-ls-nvim";
maintainers = [ maintainers.MattSturgeon ];
# TODO: introduced 2024-06-18, remove after 24.11
deprecateExtraOptions = true;
optionsRenamedToSettings = [
"border"
"cmd"
"debounce"
"debug"
"defaultTimeout"
"diagnosticConfig"
"diagnosticsFormat"
"fallbackSeverity"
"logLevel"
"notifyFormat"
"onAttach"
"onInit"
"onExit"
"rootDir"
"shouldAttach"
"tempDir"
"updateInInsert"
];
imports =
let
namespace = "plugins";
oldPluginPath = [
namespace
"null-ls"
];
basePluginPath = [
namespace
"none-ls"
];
settingsPath = basePluginPath ++ [ "settings" ];
in
[
./sources.nix
(mkRenamedOptionModule oldPluginPath basePluginPath)
(mkRenamedOptionModule (basePluginPath ++ [ "sourcesItems" ]) (settingsPath ++ [ "sources" ]))
];
settingsExample = {
diagnostics_format = "[#{c}] #{m} (#{s})";
on_attach = ''
function(client, bufnr)
-- Integrate lsp-format with none-ls
require('lsp-format').on_attach(client, bufnr)
end
'';
on_exit = ''
function()
print("Goodbye, cruel world!")
end
'';
on_init = ''
function(client, initialize_result)
print("Hello, world!")
end
'';
root_dir = ''
function(fname)
return fname:match("my-project") and "my-project-root"
end
'';
root_dir_async = ''
function(fname, cb)
cb(fname:match("my-project") and "my-project-root")
end
'';
should_attach = ''
function(bufnr)
return not vim.api.nvim_buf_get_name(bufnr):match("^git://")
end
'';
temp_dir = "/tmp";
update_in_insert = false;
};
settingsOptions = import ./settings.nix lib;
extraOptions = {
enableLspFormat = mkOption {
type = types.bool;
# TODO: consider default = false and enabling lsp-format automatically instead?
default = config.plugins.lsp-format.enable;
defaultText = literalExpression "plugins.lsp-format.enable";
example = false;
description = ''
Automatically configure `none-ls` to use the `lsp-format` plugin.
Enabled automatically when `plugins.lsp-format` is enabled.
Set `false` to disable that behavior.
'';
};
};
callSetup = false;
extraConfig =
cfg:
let
# Set a custom on_attach when enableLspFormat is enabled
# FIXME: Using `mkIf (...) (mkDefault "...")` would be better,
# but that'd make it difficult to implement the "has no effect" warning.
setupOptions =
cfg.settings
// optionalAttrs (cfg.enableLspFormat && cfg.settings.on_attach == null) {
on_attach.__raw = ''
require('lsp-format').on_attach
'';
};
in
{
warnings = optional (cfg.enableLspFormat && cfg.settings.on_attach != null) ''
You have enabled the lsp-format integration with none-ls.
However, you have provided a custom value to `plugins.none-ls.settings.on_attach`.
This means the `enableLspFormat` option will have no effect.
Final value is:
${generators.toPretty { } cfg.settings.on_attach}
'';
assertions = [
{
assertion = cfg.enableLspFormat -> config.plugins.lsp-format.enable;
message = ''
Nixvim: You have enabled the lsp-format integration with none-ls.
However, you have not enabled `plugins.lsp-format` itself.
Note: `plugins.none-ls.enableLspFormat` is enabled by default when `plugins.lsp-format` is enabled.
`plugins.none-ls.enableLspFormat` definitions: ${lib.options.showDefs options.plugins.none-ls.enableLspFormat.definitionsWithLocations}
'';
}
];
# We only do this here because of enableLspFormat
plugins.none-ls.luaConfig.content = ''
require("null-ls").setup(${helpers.toLuaObject setupOptions})
'';
};
}

View file

@ -0,0 +1,279 @@
lib:
let
inherit (import ../../../lib/pkg-lists.nix lib) topLevel scoped nullAttrs;
in
{
# builtin sources that don't require a package
noPackage = [
"gitrebase"
# TODO: Requires the go tree-sitter parser
"gomodifytags"
# TODO: Requires the go tree-sitter parser
"impl"
"luasnip"
"printenv"
"refactoring"
"spell"
"tags"
"todo_comments"
"trail_space"
"ts_node_action"
"vsnip"
];
# nixpkgs packages for a given source
packaged =
# Top-level packages
topLevel [
"actionlint"
"alejandra"
"asmfmt"
"astyle"
"bibclean"
"biome"
"buf"
"cbfmt"
"checkmake"
"checkstyle"
"clazy"
"codespell"
"commitlint"
"cppcheck"
"csharpier"
"deadnix"
"dfmt"
"djhtml"
"djlint"
"erlfmt"
"fantomas"
"fish"
"fnlfmt"
"fprettify"
"gitlint"
"gofumpt"
"golines"
"hadolint"
"hclfmt"
"isort"
"joker"
"just"
"ktlint"
"leptosfmt"
"mdformat"
"mdl"
"mypy"
"pmd"
"prettierd"
"proselint"
"protolint"
"pylint"
"revive"
"rstcheck"
"rubocop"
"rubyfmt"
"rufo"
"rustywind"
"scalafmt"
"selene"
"semgrep"
"shellharden"
"shfmt"
"smlfmt"
"sqlfluff"
"statix"
"stylelint"
"stylua"
"tfsec"
"topiary"
"trivy"
"typstfmt"
"typstyle"
"uncrustify"
"usort"
"vale"
"verilator"
"yamlfix"
"yamlfmt"
"yamllint"
"yapf"
"zprint"
"zsh"
]
# Scoped packages
// scoped {
nodePackages = [
"alex"
"prettier"
];
phpPackages = [
"phpmd"
"phpstan"
];
rubyPackages = "htmlbeautifier";
ocamlPackages = "ocamlformat";
}
# Packages where the name is different
// {
ansiblelint = "ansible-lint";
bean_check = "beancount";
bean_format = "beancount";
black = [
"python3"
"pkgs"
"black"
];
blackd = "black";
buildifier = "bazel-buildtools";
cfn_lint = [
"python3"
"pkgs"
"cfn-lint"
];
clang_format = "clang-tools";
clj_kondo = "clj-kondo";
cmake_format = "cmake-format";
cmake_lint = "cmake-format";
credo = "elixir";
crystal_format = "crystal";
cue_fmt = "cue";
d2_fmt = "d2";
dart_format = "dart";
dictionary = "curl";
dotenv_linter = "dotenv-linter";
dxfmt = "dioxus-cli";
editorconfig_checker = "editorconfig-checker";
elm_format = [
"elmPackages"
"elm-format"
];
emacs_scheme_mode = "emacs";
emacs_vhdl_mode = "emacs";
erb_format = [
"rubyPackages"
"erb-formatter"
];
fish_indent = "fish";
format_r = "R";
# FIXME: Can't have transition fallbacks anymore
gdformat = "gdtoolkit_4";
gdlint = "gdtoolkit_4";
gitsigns = "git";
gleam_format = "gleam";
glslc = "shaderc";
gn_format = "gn";
gofmt = "go";
goimports = "gotools";
goimports_reviser = "goimports-reviser";
golangci_lint = "golangci-lint";
google_java_format = "google-java-format";
haml_lint = "mastodon";
haxe_formatter = "haxe";
isortd = "isort";
ltrs = "languagetool-rust";
markdownlint_cli2 = "markdownlint-cli2";
markdownlint = "markdownlint-cli";
mix = "elixir";
nimpretty = "nim";
nixfmt = "nixfmt-classic";
nixpkgs_fmt = "nixpkgs-fmt";
opacheck = "open-policy-agent";
opentofu_fmt = "opentofu";
pg_format = "pgformatter";
phpcbf = [
"phpPackages"
"php-codesniffer"
];
phpcsfixer = [
"phpPackages"
"php-cs-fixer"
];
phpcs = [
"phpPackages"
"php-codesniffer"
];
# FIXME: Can't have transition fallbacks anymore
# TODO: replace after flake.lock update
# prisma_format = "prisma";
prisma_format = [
"nodePackages"
"prisma"
];
ptop = "fpc";
puppet_lint = "puppet-lint";
qmlformat = [
"qt6"
"qtdeclarative"
];
qmllint = [
"qt6"
"qtdeclarative"
];
racket_fixw = "racket";
raco_fmt = "racket";
rego = "open-policy-agent";
rpmspec = "rpm";
sqlformat = [
"python3"
"pkgs"
"sqlparse"
];
staticcheck = "go-tools";
surface = "elixir";
swift_format = "swift-format";
teal = [
"luaPackages"
"tl"
];
terraform_fmt = "terraform";
terraform_validate = "terraform";
terragrunt_fmt = "terragrunt";
terragrunt_validate = "terragrunt";
tidy = "html-tidy";
treefmt = "treefmt2";
verible_verilog_format = "verible";
vint = "vim-vint";
write_good = "write-good";
xmllint = "libxml2";
}
# builtin sources that are not packaged in nixpkgs
// nullAttrs [
"blade_formatter"
"bsfmt"
"bslint"
"cljstyle"
"cueimports"
"erb_lint"
"findent"
"forge_fmt"
"gccdiag"
"gersemi"
"markuplint"
"mlint"
"nginx_beautifier"
"npm_groovy_lint"
"ocdc"
"packer"
"perlimports"
"pint"
"pretty_php"
"purs_tidy"
"pyink"
"reek"
"regal"
"remark"
"rescript"
"saltlint"
"solhint"
"spectral"
"sqlfmt"
"sql_formatter"
"styler"
"stylint"
"swiftformat"
"swiftlint"
"textidote"
"textlint"
"twigcs"
"vacuum"
];
}

View file

@ -0,0 +1,43 @@
{ lib, config, ... }:
with lib;
let
cfg = config.plugins.none-ls.sources.formatting.prettier;
ts-ls-cfg = config.plugins.lsp.servers.ts-ls;
in
{
options.plugins.none-ls.sources.formatting.prettier = {
disableTsServerFormatter = mkOption {
type = with types; nullOr bool;
description = ''
Disables the formatting capability of the `ts-ls` language server if it is enabled.
'';
default = null;
example = true;
};
};
config = mkIf cfg.enable {
warnings = optional ((cfg.disableTsServerFormatter == null) && ts-ls-cfg.enable) ''
You have enabled the `prettier` formatter in none-ls.
You have also enabled the `ts-ls` language server which also brings a formatting feature.
- To disable the formatter built-in the `ts-ls` language server, set
`plugins.none-ls.sources.formatting.prettier.disableTsServerFormatter` to `true`.
- Else, to silence this warning, explicitly set the option to `false`.
'';
plugins.lsp.servers.ts-ls =
mkIf
(
cfg.enable
&& ts-ls-cfg.enable
&& (isBool cfg.disableTsServerFormatter)
&& cfg.disableTsServerFormatter
)
{
onAttach.function = ''
client.server_capabilities.documentFormattingProvider = false
'';
};
};
}

View file

@ -0,0 +1,254 @@
lib:
let
inherit (lib) types;
inherit (lib.nixvim) defaultNullOpts;
applyListOfLua = x: map (v: if builtins.isString v then lib.nixvim.mkRaw v else v) x;
in
{
border = defaultNullOpts.mkNullable' {
type =
with types;
oneOf [
attrs
str
rawLua
];
pluginDefault = null;
description = ''
Defines the border to use for the `:NullLsInfo` UI window.
Uses `NullLsInfoBorder` highlight group (see [Highlight Groups]).
Accepts same border values as `nvim_open_win()`.
See `:help nvim_open_win()` for more info.
[Highlight Groups]: https://github.com/nvimtools/none-ls.nvim/blob/main/doc/CONFIG.md#highlight-groups
'';
};
cmd = defaultNullOpts.mkListOf types.str [ "nvim" ] ''
Defines the command used to start the null-ls server.
If you do not have an `nvim` binary available on your `$PATH`,
you should change this to an absolute path to the binary.
'';
debounce = defaultNullOpts.mkUnsignedInt 250 ''
The `debounce` setting controls the amount of time between the last change to a
buffer and the next `textDocument/didChange` notification. These notifications
cause null-ls to generate diagnostics, so this setting indirectly controls the
rate of diagnostic generation (affected by `update_in_insert`, described below).
Lowering `debounce` will result in quicker diagnostic refreshes at the cost of running
diagnostic sources more frequently, which can affect performance.
The default value should be enough to provide near-instantaneous feedback from most sources
without unnecessary resource usage.
'';
debug = defaultNullOpts.mkBool false ''
Displays all possible log messages and writes them to the null-ls log, which you
can view with the command `:NullLsLog`. This option can slow down Neovim, so
it's strongly recommended to disable it for normal use.
`debug = true` is the same as setting `log_level` to `"trace"`.
'';
default_timeout = defaultNullOpts.mkUnsignedInt 5000 ''
Sets the amount of time (in milliseconds) after which built-in sources will time out.
Note that built-in sources can define their own timeout period and that users can override the
timeout period on a per-source basis, too
(see [BUILTIN_CONFIG.md](https://github.com/nvimtools/none-ls.nvim/blob/main/doc/BUILTIN_CONFIG.md)).
Specifying a timeout with a value less than zero will prevent commands from timing out.
'';
diagnostic_config = defaultNullOpts.mkNullable' {
type =
with types;
oneOf [
attrs
str
rawLua
];
pluginDefault = { };
description = ''
Specifies diagnostic display options for null-ls sources, as described in
`:help vim.diagnostic.config()`.
(null-ls uses separate namespaces for each source,
so server-wide configuration will not work as expected.)
You can also configure `diagnostic_config` per built-in by using the `with` method, described
in [BUILTIN_CONFIG](https://github.com/nvimtools/none-ls.nvim/blob/main/doc/BUILTIN_CONFIG.md).
'';
};
diagnostics_format = defaultNullOpts.mkStr "#{m}" ''
Sets the default format used for diagnostics. The plugin will replace the following special
components with the relevant diagnostic information:
- `#{m}`: message
- `#{s}`: source name (defaults to `null-ls` if not specified)
- `#{c}`: code (if available)
For example, setting `diagnostics_format` to the following:
```lua
diagnostics_format = "[#{c}] #{m} (#{s})"
```
Formats diagnostics as follows:
```txt
[2148] Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive. (shellcheck)
```
You can also configure `diagnostics_format` per built-in by using the `with`
method, described in [BUILTIN_CONFIG](https://github.com/nvimtools/none-ls.nvim/blob/main/doc/BUILTIN_CONFIG.md).
'';
fallback_severity = defaultNullOpts.mkUnsignedInt { __raw = "vim.diagnostic.severity.ERROR"; } ''
Defines the severity used when a diagnostic source does not explicitly define a severity.
See `:help diagnostic-severity` for available values.
'';
log_level =
defaultNullOpts.mkEnum
[
"off"
"error"
"warn"
"info"
"debug"
"trace"
]
"warn"
''
Enables or disables logging to file.
Plugin logs messages on several logging levels to following destinations:
- file, can be inspected by `:NullLsLog`.
- neovim's notification area.
'';
notify_format = defaultNullOpts.mkStr "[null-ls] %s" ''
Sets the default format for `vim.notify()` messages.
Can be used to customize 3rd party notification plugins like
[nvim-notify](https://github.com/rcarriga/nvim-notify).
'';
on_attach = defaultNullOpts.mkLuaFn null ''
Defines an `on_attach` callback to run whenever null-ls attaches to a buffer.
If you have a common `on_attach` you're using for LSP servers, you can reuse that here,
use a custom callback for null-ls, or leave this undefined.
'';
on_init = defaultNullOpts.mkLuaFn null ''
Defines an `on_init` callback to run when null-ls initializes.
From here, you can make changes to the client (the first argument)
or `initialize_result` (the second argument, which as of now is not used).
'';
on_exit = defaultNullOpts.mkLuaFn null ''
Defines an `on_exit` callback to run when the null-ls client exits.
'';
root_dir = defaultNullOpts.mkLuaFn' {
pluginDefault = "require('null-ls.utils').root_pattern('.null-ls-root', 'Makefile', '.git')";
description = ''
Determines the root of the null-ls server. On startup, null-ls will call
`root_dir` with the full path to the first file that null-ls attaches to.
If `root_dir` returns `nil`, the root will resolve to the current working directory.
'';
example = ''
function(fname)
return fname:match("my-project") and "my-project-root"
end
'';
};
root_dir_async = defaultNullOpts.mkLuaFn' {
pluginDefault = null;
description = ''
Like `root_dir` but also accepts a callback parameter allowing it to be
asynchronous. Overwrites `root_dir` when present.
For a utility that asynchronously finds a matching file, see `utils.root_pattern_async`.
'';
example = ''
function(fname, cb)
cb(fname:match("my-project") and "my-project-root")
end
'';
};
should_attach = defaultNullOpts.mkLuaFn' {
pluginDefault = null;
description = ''
A user-defined function that controls whether to enable null-ls for a given
buffer. Receives `bufnr` as its first argument.
To cut down potentially expensive calls, null-ls will call `should_attach` after
its own internal checks pass, so it's not guaranteed to run on each new buffer.
'';
example = ''
function(bufnr)
return not vim.api.nvim_buf_get_name(bufnr):match("^git://")
end
'';
};
# Not using mkListOf because I want `strLua` instead of `rawLua`
sources = defaultNullOpts.mkNullable' {
# TODO: support custom & third-party sources.
# Need a "source" submodule type:
# https://github.com/nvimtools/none-ls.nvim/blob/main/doc/MAIN.md#sources
type = with types; listOf strLua;
apply = x: if x == null then null else applyListOfLua x;
pluginDefault = null;
description = ''
The list of sources to enable, should be strings of lua code. Don't use this directly.
You should use `plugins.none-ls.sources.*.enable` instead.
**Upstream's description:**
Defines a list of sources for null-ls to register.
Users can add built-in sources (see [BUILTINS]) or custom sources (see [MAIN]).
If you've installed an integration that provides its own sources and aren't
interested in built-in sources, you don't have to define any sources here. The
integration will register them independently.
[BUILTINS]: https://github.com/nvimtools/none-ls.nvim/blob/main/doc/BUILTINS.md
[MAIN]: https://github.com/nvimtools/none-ls.nvim/blob/main/doc/MAIN.md
'';
# Hide this option until we decide how to handle non-builtin sources:
visible = false;
};
temp_dir = defaultNullOpts.mkStr null ''
Defines the directory used to create temporary files for sources that rely on
them (a workaround used for command-based sources that do not support `stdio`).
To maximize compatibility, null-ls defaults to creating temp files in the same
directory as the parent file. If this is causing issues, you can set it to
`/tmp` (or another appropriate directory) here. Otherwise, there is no need to
change this setting.
**Note**: some null-ls built-in sources expect temp files to exist within a
project for context and so will not work if this option changes.
You can also configure `temp_dir` per built-in by using the `with` method,
described in [BUILTIN_CONFIG](https://github.com/nvimtools/none-ls.nvim/blob/main/doc/BUILTIN_CONFIG.md).
'';
update_in_insert = defaultNullOpts.mkBool false ''
Controls whether diagnostic sources run in insert mode. If set to `false`,
diagnostic sources will run upon exiting insert mode, which greatly improves
performance but can create a slight delay before diagnostics show up. Set this
to `true` if you don't experience performance issues with your sources.
Note that by default, Neovim will not display updated diagnostics in insert
mode. Together with the option above, you need to pass `update_in_insert = true`
to `vim.diagnostic.config` for diagnostics to work as expected. See
`:help vim.diagnostic.config` for more info.
'';
}

View file

@ -0,0 +1,22 @@
{ config, lib, ... }:
let
noneLsBuiltins = import ../../../generated/none-ls.nix;
mkSourcePlugin = import ./_mk-source-plugin.nix;
in
{
imports =
[ ./prettier.nix ]
++ (lib.flatten (
lib.mapAttrsToList (category: (lib.map (mkSourcePlugin category))) noneLsBuiltins
));
config =
let
cfg = config.plugins.none-ls;
gitsignsEnabled = cfg.sources.code_actions.gitsigns.enable;
in
lib.mkIf cfg.enable {
# Enable gitsigns if the gitsigns source is enabled
plugins.gitsigns.enable = lib.mkIf gitsignsEnabled true;
};
}