diff --git a/docs/release-notes/rl-0.8.md b/docs/release-notes/rl-0.8.md index 0f6e2f31..29d05e5c 100644 --- a/docs/release-notes/rl-0.8.md +++ b/docs/release-notes/rl-0.8.md @@ -119,7 +119,6 @@ - Add tsx support in conform and lint - Moved code setting `additionalRuntimePaths` and `enableLuaLoader` out of `luaConfigPre`'s default to prevent being overridden -- Use conform over custom autocmds for LSP format on save [diniamo](https://github.com/diniamo): @@ -323,8 +322,6 @@ - Fix fzf-lua having a hard dependency on fzf. - Enable inlay hints support - `config.vim.lsp.inlayHints`. - Add `neo-tree`, `snacks.picker` extensions to `lualine`. -- Add support for `vim.lsp.formatOnSave` and - `vim.lsp.mappings.toggleFormatOnSave` [tebuevd](https://github.com/tebuevd): diff --git a/modules/plugins/formatter/conform-nvim/conform-nvim.nix b/modules/plugins/formatter/conform-nvim/conform-nvim.nix index cfe89bf3..727985a3 100644 --- a/modules/plugins/formatter/conform-nvim/conform-nvim.nix +++ b/modules/plugins/formatter/conform-nvim/conform-nvim.nix @@ -1,9 +1,12 @@ -{lib, ...}: let - inherit (lib.generators) mkLuaInline; - inherit (lib.options) mkOption mkEnableOption literalMD; - inherit (lib.types) attrs either nullOr; - inherit (lib.nvim.lua) toLuaObject; - inherit (lib.nvim.types) luaInline mkPluginSetupOption; +{ + pkgs, + lib, + ... +}: let + inherit (lib.options) mkOption mkEnableOption literalExpression; + inherit (lib.types) attrs enum nullOr; + inherit (lib.nvim.types) mkPluginSetupOption; + inherit (lib.nvim.lua) mkLuaInline; in { options.vim.formatter.conform-nvim = { enable = mkEnableOption "lightweight yet powerful formatter plugin for Neovim [conform-nvim]"; @@ -28,46 +31,26 @@ in { }; format_on_save = mkOption { - type = nullOr (either attrs luaInline); - default = mkLuaInline '' - function() - if not vim.g.formatsave or vim.b.disableFormatSave then - return - else - return {lsp_format = "fallback", timeout_ms = 500} - end - end - ''; - defaultText = literalMD '' - enabled by default, and respects {option}`vim.lsp.formatOnSave` and - {option}`vim.lsp.mappings.toggleFormatSave` - ''; + type = nullOr attrs; + default = { + lsp_format = "fallback"; + timeout_ms = 500; + }; description = '' - Attribute set or Lua function that will be passed to - `conform.format()`. If this is set, Conform will run the formatter - on save. + Table that will be passed to `conform.format()`. If this + is set, Conform will run the formatter on save. ''; }; - format_after_save = let - defaultFormatAfterSaveOpts = {lsp_format = "fallback";}; - in - mkOption { - type = nullOr (either attrs luaInline); - default = mkLuaInline '' - function() - if not vim.g.formatsave or vim.b.disableFormatSave then - return - else - return ${toLuaObject defaultFormatAfterSaveOpts} - end - end - ''; - description = '' - Table or function(luainline) that will be passed to `conform.format()`. If this - is set, Conform will run the formatter asynchronously after save. - ''; - }; + format_after_save = mkOption { + type = nullOr attrs; + default = {lsp_format = "fallback";}; + description = '' + Table that will be passed to `conform.format()`. If this + is set, Conform will run the formatter asynchronously after + save. + ''; + }; }; }; } diff --git a/modules/plugins/lsp/config.nix b/modules/plugins/lsp/config.nix index e7b67c8e..c2320aaf 100644 --- a/modules/plugins/lsp/config.nix +++ b/modules/plugins/lsp/config.nix @@ -6,7 +6,6 @@ }: let inherit (lib.generators) mkLuaInline; inherit (lib.modules) mkIf; - inherit (lib.lists) optional; inherit (lib.strings) optionalString; inherit (lib.trivial) boolToString; inherit (lib.nvim.binds) addDescriptionsToMappings; @@ -15,10 +14,7 @@ usingNvimCmp = config.vim.autocomplete.nvim-cmp.enable; usingBlinkCmp = config.vim.autocomplete.blink-cmp.enable; self = import ./module.nix {inherit config lib pkgs;}; - conformCfg = config.vim.formatter.conform-nvim; - conformFormatOnSave = conformCfg.enable && conformCfg.setupOpts.format_on_save != null; - augroup = "nvf_lsp"; mappingDefinitions = self.options.vim.lsp.mappings; mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions; mkBinding = binding: action: @@ -33,59 +29,24 @@ in { sourcePlugins = ["cmp-nvim-lsp"]; }; - augroups = [{name = augroup;}]; autocmds = - (optional cfg.inlayHints.enable { - group = augroup; - event = ["LspAttach"]; - desc = "LSP on-attach enable inlay hints autocmd"; - callback = mkLuaInline '' - function(event) - local bufnr = event.buf - local client = vim.lsp.get_client_by_id(event.data.client_id) - if client and client.supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then - vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = bufnr }), { bufnr = bufnr }) - end - end - ''; - }) - ++ (optional (!conformFormatOnSave) { - group = augroup; - event = ["BufWritePre"]; - desc = "LSP on-attach create format on save autocmd"; - callback = mkLuaInline '' - function(ev) - if vim.b.disableFormatSave or not vim.g.formatsave then - return - end - - local bufnr = ev.buf - - ${optionalString cfg.null-ls.enable '' - -- prefer null_ls formatter - do - local clients = vim.lsp.get_clients({ - bufnr = bufnr, - name = "null-ls", - method = "textDocument/formatting", - }) - if clients[1] then - vim.lsp.buf.format({ bufnr = bufnr, id = clients[1].id }) - return + if cfg.inlayHints.enable + then [ + { + callback = mkLuaInline '' + function(event) + local bufnr = event.buf + local client = vim.lsp.get_client_by_id(event.data.client_id) + if client and client.supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = bufnr }), { bufnr = bufnr }) end end - ''} - - local clients = vim.lsp.get_clients({ - bufnr = bufnr, - method = "textDocument/formatting", - }) - if clients[1] then - vim.lsp.buf.format({ bufnr = bufnr, id = clients[1].id }) - end - end - ''; - }); + ''; + desc = "LSP on-attach enable inlay hints autocmd"; + event = ["LspAttach"]; + } + ] + else []; pluginRC.lsp-setup = '' vim.g.formatsave = ${boolToString cfg.formatOnSave}; @@ -113,9 +74,60 @@ in { ${mkBinding mappings.toggleFormatOnSave "function() vim.b.disableFormatSave = not vim.b.disableFormatSave end"} end + -- Enable formatting + local augroup = vim.api.nvim_create_augroup("LspFormatting", {}) + + format_callback = function(client, bufnr) + if vim.g.formatsave then + vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr }) + vim.api.nvim_create_autocmd("BufWritePre", { + group = augroup, + buffer = bufnr, + callback = function() + if vim.b.disableFormatSave then + return + end + + ${ + if config.vim.lsp.null-ls.enable + then '' + local function is_null_ls_formatting_enabled(bufnr) + local file_type = vim.api.nvim_buf_get_option(bufnr, "filetype") + local generators = require("null-ls.generators").get_available( + file_type, + require("null-ls.methods").internal.FORMATTING + ) + return #generators > 0 + end + + if is_null_ls_formatting_enabled(bufnr) then + vim.lsp.buf.format({ + bufnr = bufnr, + filter = function(client) + return client.name == "null-ls" + end + }) + else + vim.lsp.buf.format({ + bufnr = bufnr, + }) + end + '' + else " + vim.lsp.buf.format({ + bufnr = bufnr, + }) + " + } + end, + }) + end + end + ${optionalString config.vim.ui.breadcrumbs.enable ''local navic = require("nvim-navic")''} default_on_attach = function(client, bufnr) attach_keymaps(client, bufnr) + format_callback(client, bufnr) ${optionalString config.vim.ui.breadcrumbs.enable '' -- let navic attach to buffers if client.server_capabilities.documentSymbolProvider then @@ -126,7 +138,6 @@ in { local capabilities = vim.lsp.protocol.make_client_capabilities() ${optionalString usingNvimCmp '' - -- TODO(horriblename): migrate to vim.lsp.config['*'] -- HACK: copied from cmp-nvim-lsp. If we ever lazy load lspconfig we -- should re-evaluate whether we can just use `default_capabilities` capabilities = {