diff --git a/plugins/null-ls/default.nix b/plugins/null-ls/default.nix index e712fc3e..541ede80 100644 --- a/plugins/null-ls/default.nix +++ b/plugins/null-ls/default.nix @@ -12,38 +12,237 @@ in { ./servers.nix ]; - options.plugins.null-ls = { - enable = mkEnableOption "null-ls"; + options.plugins.null-ls = + helpers.extraOptionsOptions + // { + enable = mkEnableOption "null-ls"; - package = mkOption { - type = types.package; - default = pkgs.vimPlugins.null-ls-nvim; - description = "Plugin to use for null-ls"; + package = mkOption { + type = types.package; + default = pkgs.vimPlugins.null-ls-nvim; + description = "Plugin to use for null-ls"; + }; + + border = helpers.defaultNullOpts.mkStr "null" '' + Defines the border to use for the `:NullLsInfo` UI window. + Uses `NullLsInfoBorder` highlight group (see [Highlight Groups](#highlight-groups)). + Accepts same border values as `nvim_open_win()`. See `:help nvim_open_win()` for more info. + ''; + + cmd = helpers.defaultNullOpts.mkNullable (types.listOf 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 = helpers.defaultNullOpts.mkInt 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 = helpers.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 `logLevel` to `"trace"`. + ''; + + defaultTimeout = helpers.defaultNullOpts.mkInt 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](BUILTIN_CONFIG.md)). + + Specifying a timeout with a value less than zero will prevent commands from timing out. + ''; + + diagnosticConfig = helpers.defaultNullOpts.mkNullable (types.attrs) "null" '' + 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.md. + ''; + + diagnosticsFormat = helpers.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](BUILTIN_CONFIG.md). + ''; + + fallbackSeverity = + helpers.defaultNullOpts.mkNullable + (with types; either int (enum ["error" "warn" "info" "hint"])) + "error" + '' + Defines the severity used when a diagnostic source does not explicitly define a severity. + See `:help diagnostic-severity` for available values. + ''; + + logLevel = + helpers.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. + ''; + + notifyFormat = helpers.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). + ''; + + onAttach = helpers.defaultNullOpts.mkStr "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. + ''; + + onInit = helpers.defaultNullOpts.mkStr "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). + ''; + + onExit = helpers.defaultNullOpts.mkStr "null" '' + Defines an `on_exit` callback to run when the null-ls client exits. + ''; + + rootDir = helpers.defaultNullOpts.mkStr "null" '' + 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. + + ```lua + local root_dir = function(fname) + return fname:match("my-project") and "my-project-root" + end + ``` + + If `root_dir` returns `nil`, the root will resolve to the current working + directory. + ''; + + shouldAttach = helpers.defaultNullOpts.mkStr "null" '' + 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. + + ```lua + require("null-ls.nvim").setup({ + should_attach = function(bufnr) + return not vim.api.nvim_buf_get_name(bufnr):match("^git://") + end, + }) + ``` + ''; + + tempDir = helpers.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.md. + ''; + + updateInInsert = helpers.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. + ''; + + sourcesItems = + helpers.mkNullOrOption + (with types; listOf (attrsOf str)) + "The list of sources to enable, should be strings of lua code. Don't use this directly"; }; - debug = mkOption { - default = null; - type = with types; nullOr bool; - }; - - sourcesItems = mkOption { - default = null; - # type = with types; nullOr (either (listOf str) (listOf attrsOf str)); - type = with types; nullOr (listOf (attrsOf str)); - description = "The list of sources to enable, should be strings of lua code. Don't use this directly"; - }; - - # sources = mkOption { - # default = null; - # type = with types; nullOr attrs; - # }; - }; - config = let - options = { - debug = cfg.debug; - sources = cfg.sourcesItems; - }; + options = + { + inherit + (cfg) + border + cmd + debounce + debug + ; + default_timeout = cfg.defaultTimeout; + diagnostic_config = cfg.diagnosticConfig; + diagnostics_format = cfg.diagnosticsFormat; + fallback_severity = + if isString cfg.fallbackSeverity + then helpers.mkRaw "vim.diagnostic.severity.${strings.toUpper cfg.fallbackSeverity}" + else cfg.fallbackSeverity; + log_level = cfg.logLevel; + notify_format = cfg.notifyFormat; + on_attach = + helpers.ifNonNull' cfg.onAttach + (helpers.mkRaw cfg.onAttach); + on_init = + helpers.ifNonNull' cfg.onInit + (helpers.mkRaw cfg.onInit); + on_exit = + helpers.ifNonNull' cfg.onExit + (helpers.mkRaw cfg.onExit); + root_dir = + helpers.ifNonNull' cfg.rootDir + (helpers.mkRaw cfg.rootDir); + should_attach = + helpers.ifNonNull' cfg.shouldAttach + (helpers.mkRaw cfg.shouldAttach); + temp_dir = cfg.tempDir; + update_in_insert = cfg.updateInInsert; + + sources = cfg.sourcesItems; + } + // cfg.extraOptions; in mkIf cfg.enable { extraPlugins = [cfg.package]; diff --git a/tests/plugins/null-ls.nix b/tests/plugins/null-ls.nix new file mode 100644 index 00000000..865c1f59 --- /dev/null +++ b/tests/plugins/null-ls.nix @@ -0,0 +1,29 @@ +{ + # Empty configuration + empty = { + plugins.null-ls.enable = true; + }; + + default = { + plugins.null-ls = { + enable = true; + border = null; + cmd = ["nvim"]; + debounce = 250; + debug = false; + defaultTimeout = 5000; + diagnosticConfig = null; + diagnosticsFormat = "#{m}"; + fallbackSeverity = "error"; + logLevel = "warn"; + notifyFormat = "[null-ls] %s"; + onAttach = null; + onInit = null; + onExit = null; + rootDir = null; + shouldAttach = null; + tempDir = null; + updateInInsert = false; + }; + }; +}