diff --git a/configuration.nix b/configuration.nix index 01a99524..3b8e3d25 100644 --- a/configuration.nix +++ b/configuration.nix @@ -76,6 +76,7 @@ isMaximal: { csharp.enable = isMaximal; julia.enable = isMaximal; vala.enable = isMaximal; + nu.enable = false; }; visuals = { diff --git a/docs/release-notes/rl-0.7.md b/docs/release-notes/rl-0.7.md index 727065de..28e7c79c 100644 --- a/docs/release-notes/rl-0.7.md +++ b/docs/release-notes/rl-0.7.md @@ -297,6 +297,7 @@ To migrate to `nixfmt`, simply change `vim.languages.nix.format.type` to - Telescope: - Fixed `project-nvim` command and keybinding - Added default ikeybind/command for `Telescope resume` (`fr`) +- Add `hcl` lsp/formatter (not the same as `terraform`, which is not useful for e.g. `nomad` config files). [Soliprem](https://github.com/Soliprem): @@ -314,6 +315,7 @@ To migrate to `nixfmt`, simply change `vim.languages.nix.format.type` to the Typst language module. - Add LSP and Treesitter support for Assembly under `vim.languages.assembly` - Move [which-key](https://github.com/folke/which-key.nvim) to the new spec +- Add LSP and Treesitter support for Nushell under `vim.languages.nu` [Bloxx12](https://github.com/Bloxx12) diff --git a/flake.lock b/flake.lock index d9e6b477..5e201d89 100644 --- a/flake.lock +++ b/flake.lock @@ -98,11 +98,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1730958623, - "narHash": "sha256-JwQZIGSYnRNOgDDoIgqKITrPVil+RMWHsZH1eE1VGN0=", + "lastModified": 1732617236, + "narHash": "sha256-PYkz6U0bSEaEB1al7O1XsqVNeSNS+s3NVclJw7YC43w=", "owner": "nixos", "repo": "nixpkgs", - "rev": "85f7e662eda4fa3a995556527c87b2524b691933", + "rev": "af51545ec9a44eadf3fe3547610a5cdd882bc34e", "type": "github" }, "original": { @@ -1713,11 +1713,11 @@ "plugin-rustaceanvim": { "flake": false, "locked": { - "lastModified": 1731172933, - "narHash": "sha256-B2AdSgGPANCBbVN+Sd7gvJ16ODZZwv4WSOxnRs3SWnk=", + "lastModified": 1732565373, + "narHash": "sha256-WRaNW0trZYEUKd05Uc+5nP+G81HI14d6lM7/WWz61E0=", "owner": "mrcjkb", "repo": "rustaceanvim", - "rev": "244443311f1c4e34ec1ea7f219a4b682b6ec066e", + "rev": "fee0aa094b0c9f93fffe5a385b3d5d2386c2b072", "type": "github" }, "original": { diff --git a/modules/plugins/languages/default.nix b/modules/plugins/languages/default.nix index b3b019bc..58662354 100644 --- a/modules/plugins/languages/default.nix +++ b/modules/plugins/languages/default.nix @@ -9,6 +9,7 @@ in { ./css.nix ./elixir.nix ./go.nix + ./hcl.nix ./kotlin.nix ./html.nix ./java.nix @@ -32,6 +33,7 @@ in { ./zig.nix ./csharp.nix ./julia.nix + ./nu.nix ]; options.vim.languages = { diff --git a/modules/plugins/languages/hcl.nix b/modules/plugins/languages/hcl.nix new file mode 100644 index 00000000..e340e74d --- /dev/null +++ b/modules/plugins/languages/hcl.nix @@ -0,0 +1,117 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (builtins) attrNames; + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.types) package bool enum; + inherit (lib.nvim.types) mkGrammarOption; + + cfg = config.vim.languages.hcl; + + defaultServer = "terraform-ls"; + servers = { + terraform-ls = { + package = pkgs.terraform-ls; + lspConfig = '' + lspconfig.terraformls.setup { + capabilities = capabilities, + on_attach=default_on_attach, + cmd = {"${lib.getExe cfg.lsp.package}", "serve"}, + } + ''; + }; + }; + + defaultFormat = "hclfmt"; + formats = { + hclfmt = { + package = pkgs.hclfmt; + nullConfig = '' + table.insert( + ls_sources, + null_ls.builtins.formatting.hclfmt.with({ + command = "${lib.getExe cfg.format.package}", + }) + ) + ''; + }; + }; +in { + options.vim.languages.hcl = { + enable = mkEnableOption "HCL support"; + + treesitter = { + enable = mkEnableOption "HCL treesitter" // {default = config.vim.languages.enableTreesitter;}; + package = mkGrammarOption pkgs "hcl"; + }; + + lsp = { + enable = mkEnableOption "HCL LSP support (terraform-ls)" // {default = config.vim.languages.enableLSP;}; + # TODO: (maybe, is it better?) it would be cooler to use vscode-extensions.hashicorp.hcl probably, shouldn't be too hard + package = mkOption { + type = package; + default = servers.${defaultServer}.package; + description = "HCL language server package (terraform-ls)"; + }; + }; + + format = { + enable = mkOption { + type = bool; + default = config.vim.languages.enableFormat; + description = "Enable HCL formatting"; + }; + type = mkOption { + type = enum (attrNames formats); + default = defaultFormat; + description = "HCL formatter to use"; + }; + package = mkOption { + type = package; + default = formats.${cfg.format.type}.package; + description = "HCL formatter package"; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + # hcl style official: https://developer.hashicorp.com/terraform/language/style#code-formatting + vim.pluginRC.hcl = '' + vim.api.nvim_create_autocmd("FileType", { + pattern = "hcl", + callback = function(opts) + local bo = vim.bo[opts.buf] + bo.tabstop = 2 + bo.shiftwidth = 2 + bo.softtabstop = 2 + end + }) + + local ft = require('Comment.ft') + ft + .set('hcl', '#%s') + ''; + } + (mkIf cfg.treesitter.enable { + vim.treesitter.enable = true; + vim.treesitter.grammars = [cfg.treesitter.package]; + }) + + (mkIf cfg.lsp.enable { + vim.lsp.lspconfig.enable = true; + vim.lsp.lspconfig.sources = lib.optionalAttrs (! config.vim.languages.terraform.lsp.enable) { + terraform-ls = servers.${cfg.lsp.server}.lspConfig; + }; + }) + + (mkIf cfg.format.enable { + vim.lsp.null-ls.enable = true; + vim.lsp.null-ls.sources.hcl-format = formats.${cfg.format.type}.nullConfig; + }) + ]); +} diff --git a/modules/plugins/languages/nu.nix b/modules/plugins/languages/nu.nix new file mode 100644 index 00000000..eab0385c --- /dev/null +++ b/modules/plugins/languages/nu.nix @@ -0,0 +1,70 @@ +{ + lib, + pkgs, + config, + ... +}: let + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.types) str either package listOf; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.nvim.lua) expToLua; + inherit (lib.nvim.types) mkGrammarOption; + inherit (builtins) isList; + + defaultServer = "nushell"; + servers = { + nushell = { + package = pkgs.nushell; + lspConfig = '' + lspconfig.nushell.setup{ + capabilities = capabilities, + on_attach = default_on_attach, + cmd = ${ + if isList cfg.lsp.package + then expToLua cfg.lsp.package + else ''{"${cfg.lsp.package}/bin/nu", "--no-config-file", "--lsp"}'' + } + } + ''; + }; + }; + + cfg = config.vim.languages.nu; +in { + options.vim.languages.nu = { + enable = mkEnableOption "Nu language support"; + + treesitter = { + enable = mkEnableOption "Nu treesitter" // {default = config.vim.languages.enableTreesitter;}; + package = mkGrammarOption pkgs "nu"; + }; + + lsp = { + enable = mkEnableOption "Nu LSP support" // {default = config.vim.languages.enableLSP;}; + server = mkOption { + type = str; + default = defaultServer; + description = "Nu LSP server to use"; + }; + + package = mkOption { + type = either package (listOf str); + default = servers.${cfg.lsp.server}.package; + example = ''[(lib.getExe pkgs.nushell) "--lsp"]''; + description = "Nu LSP server package, or the command to run as a list of strings"; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + (mkIf cfg.treesitter.enable { + vim.treesitter.enable = true; + vim.treesitter.grammars = [cfg.treesitter.package]; + }) + + (mkIf cfg.lsp.enable { + vim.lsp.lspconfig.enable = true; + vim.lsp.lspconfig.sources.nu-lsp = servers.${cfg.lsp.server}.lspConfig; + }) + ]); +} diff --git a/modules/plugins/languages/typst.nix b/modules/plugins/languages/typst.nix index 45b6a70f..fbb090e8 100644 --- a/modules/plugins/languages/typst.nix +++ b/modules/plugins/languages/typst.nix @@ -21,7 +21,10 @@ lspConfig = '' lspconfig.typst_lsp.setup { capabilities = capabilities, - on_attach = default_on_attach, + on_attach = function(client, bufnr) + -- Disable semantic tokens as a workaround for a semantic token error when using non-english characters + client.server_capabilities.semanticTokensProvider = nil + end, cmd = ${ if isList cfg.lsp.package then expToLua cfg.lsp.package @@ -36,7 +39,10 @@ lspconfig.tinymist.setup { capabilities = capabilities, single_file_support = true, - on_attach = default_on_attach, + on_attach = function(client, bufnr) + -- Disable semantic tokens as a workaround for a semantic token error when using non-english characters + client.server_capabilities.semanticTokensProvider = nil + end, cmd = ${ if isList cfg.lsp.package then expToLua cfg.lsp.package diff --git a/modules/wrapper/lazy/config.nix b/modules/wrapper/lazy/config.nix index 4ac1632b..6a9a6ea2 100644 --- a/modules/wrapper/lazy/config.nix +++ b/modules/wrapper/lazy/config.nix @@ -3,7 +3,7 @@ config, ... }: let - inherit (builtins) toJSON typeOf head length filter concatLists concatStringsSep; + inherit (builtins) toJSON typeOf head length filter concatLists concatStringsSep tryEval; inherit (lib.attrsets) mapAttrsToList; inherit (lib.modules) mkIf mkMerge; inherit (lib.generators) mkLuaInline; @@ -21,10 +21,36 @@ else keySpec.action; }; - toLuaLznSpec = name: spec: + toLuaLznSpec = name: spec: let + packageName = + if typeOf spec.package == "string" + then spec.package + else if (spec.package ? pname && (tryEval spec.package.pname).success) + then spec.package.pname + else spec.package.name; + in (removeAttrs spec ["package" "setupModule" "setupOpts" "keys"]) // { - "@1" = name; + "@1" = + if spec.package != null && packageName != name && spec.load == null + then + abort '' + vim.lazy.plugins.${name} does not match the package name ${packageName}. + + Please either: + - rename it to vim.lazy.plugins.${packageName}, or + - if you intend to use a custom loader, specify a + vim.lazy.plugins.${name}.load function. + '' + else if spec.package == null && spec.load == null + then + abort '' + vim.lazy.plugins.${name} has null package but no load function given. + + Please either specify a package, or (if you know what you're doing) provide a + custom load function. + '' + else name; beforeAll = if spec.beforeAll != null then @@ -62,7 +88,7 @@ if spec.load != null then mkLuaInline '' - function() + function(name) ${spec.load} end '' @@ -76,7 +102,7 @@ }; lznSpecs = mapAttrsToList toLuaLznSpec cfg.plugins; - pluginPackages = mapAttrsToList (_: plugin: plugin.package) cfg.plugins; + pluginPackages = filter (x: x != null) (mapAttrsToList (_: plugin: plugin.package) cfg.plugins); specToNotLazyConfig = _: spec: '' do diff --git a/modules/wrapper/lazy/lazy.nix b/modules/wrapper/lazy/lazy.nix index 56ec0022..e0dbea85 100644 --- a/modules/wrapper/lazy/lazy.nix +++ b/modules/wrapper/lazy/lazy.nix @@ -66,8 +66,12 @@ lznPluginType = submodule { options = { package = mkOption { - type = pluginType; - description = "Plugin package"; + type = nullOr pluginType; + description = '' + Plugin package. + + If null, a custom load function must be provided + ''; }; setupModule = mkOption { @@ -173,7 +177,7 @@ description = '' Lua code to override the `vim.g.lz_n.load()` function for a single plugin. - This will be wrapped in a function. + This will be wrapped in a `function(name) ... end`. ''; }; };