From 86f406715912e918d2c089a8ef5fb0089c2e85af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=A9tan=20Lepage?= <33058747+GaetanLepage@users.noreply.github.com> Date: Wed, 15 Mar 2023 12:06:00 +0100 Subject: [PATCH] plugins/rust-tools: refactoring + tests (#258) --- plugins/languages/rust.nix | 353 ++++++++++++++++------------------- tests/plugins/rust-tools.nix | 52 ++++++ 2 files changed, 215 insertions(+), 190 deletions(-) create mode 100644 tests/plugins/rust-tools.nix diff --git a/plugins/languages/rust.nix b/plugins/languages/rust.nix index 2153de3d..cf2e967a 100644 --- a/plugins/languages/rust.nix +++ b/plugins/languages/rust.nix @@ -5,217 +5,190 @@ ... }: with lib; let + cfg = config.plugins.rust-tools; helpers = import ../helpers.nix {inherit lib;}; in { - options.plugins.rust-tools = let - mkNullableOptionWithDefault = { - type, - description, - default, - }: - mkOption { - type = types.nullOr type; - default = null; - description = '' - ${description} + options.plugins.rust-tools = + helpers.extraOptionsOptions + // { + enable = mkEnableOption "rust tools plugins"; + package = helpers.mkPackageOption "rust-tools" pkgs.vimPlugins.rust-tools-nvim; + serverPackage = mkOption { + type = types.package; + default = pkgs.rust-analyzer; + description = "Package to use for rust-analyzer"; + }; - default: `${default}` + executor = + helpers.defaultNullOpts.mkEnumFirstDefault ["termopen" "quickfix"] + "how to execute terminal commands"; + + onInitialized = + helpers.defaultNullOpts.mkStr "null" + '' + Callback to execute once rust-analyzer is done initializing the workspace + The callback receives one parameter indicating the `health` of the server: + "ok" | "warning" | "error" ''; - }; - mkNullableBoolDefault = default: description: - mkNullableOptionWithDefault { - inherit description; - type = types.bool; - default = toString default; - }; - - mkNullableStrDefault = default: description: - mkNullableOptionWithDefault { - inherit description; - type = types.str; - default = ''"${default}"''; - }; - - mkNullableIntDefault = default: description: - mkNullableOptionWithDefault { - inherit description; - type = types.int; - default = toString default; - }; - in { - enable = mkEnableOption "rust tools plugins"; - package = helpers.mkPackageOption "rust-tools" pkgs.vimPlugins.rust-tools-nvim; - serverPackage = mkOption { - type = types.package; - default = pkgs.rust-analyzer; - description = "Package to use for rust-analyzer"; - }; - - executor = mkNullableOptionWithDefault { - type = types.enum ["termopen" "quickfix"]; - default = ''"termopen"''; - description = "how to execute terminal commands"; - }; - - onIntialized = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Callback to execute once rust-analyzer is done initializing the workspace - The callback receives one parameter indicating the `health` of the server: - "ok" | "warning" | "error" - ''; - }; - - reloadWorkspaceFromCargoToml = mkNullableBoolDefault true '' - Automatically call RustReloadWorkspace when writing to a Cargo.toml file. - ''; - - inlayHints = { - auto = mkNullableBoolDefault true "automatically set inlay hints (type hints)"; - - onlyCurrentLine = mkNullableBoolDefault false "Only show for current line"; - - showParameterHints = - mkNullableBoolDefault true - "whether to show parameter hints with the inlay hints or not"; - - parameterHintsPrefix = mkNullableStrDefault "<- " "prefix for parameter hints"; - otherHintsPrefix = mkNullableStrDefault "=> " "prefix for all the other hints (type, chaining)"; - - maxLenAlign = - mkNullableBoolDefault false - "whether to align to the length of the longest line in the file"; - - maxLenAlignPadding = mkNullableIntDefault 1 "padding from the left if max_len_align is true"; - - rightAlign = mkNullableBoolDefault false "whether to align to the extreme right or not"; - rightAlignPadding = mkNullableIntDefault 7 "padding from the right if right_align is true"; - - highlight = mkNullableStrDefault "Comment" "The color of the hints"; - }; - - hoverActions = { - border = mkOption { - type = types.nullOr types.anything; - default = null; - description = '' - the border that is used for the hover window. see vim.api.nvim_open_win() - ''; - }; - - maxWidth = mkOption { - type = types.nullOr types.int; - default = null; - description = "Maximal width of the hover window. Nil means no max."; - }; - maxHeight = mkOption { - type = types.nullOr types.int; - default = null; - description = "Maximal height of the hover window. Nil means no max."; - }; - - autoFocus = mkNullableBoolDefault false "whether the hover action window gets automatically focused"; - }; - - crateGraph = { - backend = mkNullableStrDefault "x11" '' - Backend used for displaying the graph - see: https://graphviz.org/docs/outputs/ + reloadWorkspaceFromCargoToml = helpers.defaultNullOpts.mkBool true '' + Automatically call RustReloadWorkspace when writing to a Cargo.toml file. ''; - output = mkOption { - type = types.nullOr types.str; - default = null; - description = "where to store the output, nil for no output stored"; + inlayHints = helpers.mkCompositeOption "inlay hints" { + auto = helpers.defaultNullOpts.mkBool true "automatically set inlay hints (type hints)"; + + onlyCurrentLine = helpers.defaultNullOpts.mkBool false "Only show for current line"; + + showParameterHints = + helpers.defaultNullOpts.mkBool true + "whether to show parameter hints with the inlay hints or not"; + + parameterHintsPrefix = + helpers.defaultNullOpts.mkStr "<- " + "prefix for parameter hints"; + + otherHintsPrefix = + helpers.defaultNullOpts.mkStr "=> " + "prefix for all the other hints (type, chaining)"; + + maxLenAlign = + helpers.defaultNullOpts.mkBool false + "whether to align to the length of the longest line in the file"; + + maxLenAlignPadding = + helpers.defaultNullOpts.mkInt 1 + "padding from the left if max_len_align is true"; + + rightAlign = + helpers.defaultNullOpts.mkBool false + "whether to align to the extreme right or not"; + + rightAlignPadding = + helpers.defaultNullOpts.mkInt 7 + "padding from the right if right_align is true"; + + highlight = helpers.defaultNullOpts.mkStr "Comment" "The color of the hints"; }; - full = mkNullableBoolDefault true '' - true for all crates.io and external crates, false only the local crates - ''; + hoverActions = helpers.mkCompositeOption "hover actions" { + border = + helpers.defaultNullOpts.mkNullable (types.listOf (types.listOf types.str)) + '' + [ + [ "╭" "FloatBorder" ] + [ "─" "FloatBorder" ] + [ "╮" "FloatBorder" ] + [ "│" "FloatBorder" ] + [ "╯" "FloatBorder" ] + [ "─" "FloatBorder" ] + [ "╰" "FloatBorder" ] + [ "│" "FloatBorder" ] + ] + '' + "the border that is used for the hover window. see vim.api.nvim_open_win()"; - enabledGraphvizBackends = mkOption { - type = types.nullOr (types.listOf types.str); - default = null; - description = '' - List of backends found on: https://graphviz.org/docs/outputs/ - Is used for input validation and autocompletion + maxWidth = + helpers.defaultNullOpts.mkNullable types.int "null" + "Maximal width of the hover window. null means no max."; + + maxHeight = + helpers.defaultNullOpts.mkNullable types.int "null" + "Maximal height of the hover window. null means no max."; + + autoFocus = + helpers.defaultNullOpts.mkBool false + "whether the hover action window gets automatically focused"; + }; + + crateGraph = helpers.mkCompositeOption "create graph" { + backend = helpers.defaultNullOpts.mkStr "x11" '' + Backend used for displaying the graph + see: https://graphviz.org/docs/outputs/ ''; + + output = + helpers.defaultNullOpts.mkStr "null" + "where to store the output, nil for no output stored"; + + full = helpers.defaultNullOpts.mkBool true '' + true for all crates.io and external crates, false only the local crates + ''; + + enabledGraphvizBackends = + helpers.defaultNullOpts.mkNullable (types.listOf types.str) "null" + '' + List of backends found on: https://graphviz.org/docs/outputs/ + Is used for input validation and autocompletion + ''; }; + + server = + helpers.mkCompositeOption "server" + { + standalone = helpers.defaultNullOpts.mkBool true '' + standalone file support + setting it to false may improve startup time + ''; + } + // (import ../nvim-lsp/language-servers/rust-analyzer-config.nix lib); }; + config = mkIf cfg.enable { + extraPlugins = with pkgs.vimPlugins; [nvim-lspconfig cfg.package]; + extraPackages = [cfg.serverPackage]; - server = - { - standalone = mkNullableBoolDefault true '' - standalone file support - setting it to false may improve startup time - ''; - } - // (import ../nvim-lsp/language-servers/rust-analyzer-config.nix lib); - }; - config = let - cfg = config.plugins.rust-tools; - in - mkIf cfg.enable { - extraPlugins = with pkgs.vimPlugins; [nvim-lspconfig cfg.package]; - extraPackages = [cfg.serverPackage]; - - plugins.lsp.postConfig = let - setupOptions = { + plugins.lsp.postConfig = let + options = + { tools = { executor = - if cfg.executor != null - then {__raw = ''require("rust-tools.executors").${cfg.executor}'';} - else null; + helpers.ifNonNull' cfg.executor + (helpers.mkRaw "require(${rust-tools.executors}).${cfg.executor}"); on_initialized = - if cfg.onIntialized != null - then {__raw = cfg.onIntialized;} - else null; + helpers.ifNonNull' cfg.onInitialized + (helpers.mkRaw cfg.onInitialized); reload_workspace_from_cargo_toml = cfg.reloadWorkspaceFromCargoToml; - inlay_hints = let - cfgIH = cfg.inlayHints; - in { - auto = cfgIH.auto; - only_current_line = cfgIH.onlyCurrentLine; - show_parameter_hints = cfgIH.showParameterHints; - parameter_hints_prefix = cfgIH.parameterHintsPrefix; - other_hints_prefix = cfgIH.otherHintsPrefix; - max_len_align = cfgIH.maxLenAlign; - max_len_align_padding = cfgIH.maxLenAlignPadding; - right_align = cfgIH.rightAlign; - right_align_padding = cfgIH.rightAlignPadding; - highlight = cfgIH.highlight; - }; + inlay_hints = with cfg.inlayHints; + helpers.ifNonNull' cfg.inlayHints { + inherit auto; + only_current_line = onlyCurrentLine; + show_parameter_hints = showParameterHints; + parameter_hints_prefix = parameterHintsPrefix; + other_hints_prefix = otherHintsPrefix; + max_len_align = maxLenAlign; + max_len_align_padding = maxLenAlignPadding; + right_align = rightAlign; + right_align_padding = rightAlignPadding; + inherit highlight; + }; - hover_actions = let - cfgHA = cfg.hoverActions; - in { - border = cfgHA.border; - max_width = cfgHA.maxWidth; - max_height = cfgHA.maxHeight; - auto_focus = cfgHA.autoFocus; - }; + hover_actions = with cfg.hoverActions; + helpers.ifNonNull' cfg.hoverActions + { + inherit border; + max_width = maxWidth; + max_height = maxHeight; + auto_focus = autoFocus; + }; - crate_graph = let - cfgCG = cfg.crateGraph; - in { - backend = cfgCG.backend; - output = cfgCG.output; - full = cfgCG.full; - enabled_graphviz_backends = cfgCG.enabledGraphvizBackends; + crate_graph = with cfg.crateGraph; + helpers.ifNonNull' cfg.crateGraph { + inherit backend output full; + enabled_graphviz_backends = enabledGraphvizBackends; + }; + }; + server = with cfg.server; + helpers.ifNonNull' cfg.server { + inherit standalone; + settings.rust-analyzer = lib.filterAttrs (n: v: n != "standalone") cfg.server; + on_attach = helpers.mkRaw "__lspOnAttach"; }; - }; - server = { - standalone = cfg.server.standalone; - settings.rust-analyzer = lib.filterAttrs (n: v: n != "standalone") cfg.server; - on_attach = {__raw = "__lspOnAttach";}; - }; - }; - in '' - require('rust-tools').setup(${helpers.toLuaObject setupOptions}) - ''; - }; + } + // cfg.extraOptions; + in '' + require('rust-tools').setup(${helpers.toLuaObject options}) + ''; + }; } diff --git a/tests/plugins/rust-tools.nix b/tests/plugins/rust-tools.nix new file mode 100644 index 00000000..1552ec4c --- /dev/null +++ b/tests/plugins/rust-tools.nix @@ -0,0 +1,52 @@ +{ + # Empty configuration + empty = { + plugins.rust-tools.enable = true; + }; + + # All the upstream default options of rust-tools + defaults = { + plugins.rust-tools = { + enable = true; + executor = "termopen"; + onInitialized = null; + reloadWorkspaceFromCargoToml = true; + inlayHints = { + auto = true; + onlyCurrentLine = false; + showParameterHints = true; + parameterHintsPrefix = "<- "; + otherHintsPrefix = "=> "; + maxLenAlign = false; + maxLenAlignPadding = 1; + rightAlign = false; + rightAlignPadding = 7; + highlight = "Comment"; + }; + hoverActions = { + border = [ + ["╭" "FloatBorder"] + ["─" "FloatBorder"] + ["╮" "FloatBorder"] + ["│" "FloatBorder"] + ["╯" "FloatBorder"] + ["─" "FloatBorder"] + ["╰" "FloatBorder"] + ["│" "FloatBorder"] + ]; + maxWidth = null; + maxHeight = null; + autoFocus = false; + }; + crateGraph = { + backend = "x11"; + output = null; + full = true; + enabledGraphvizBackends = null; + }; + server = { + standalone = true; + }; + }; + }; +}