Merge pull request #891 from horriblename/conform-format-on-save-fix-v2
Some checks are pending
Set up binary cache / cachix (default) (push) Waiting to run
Set up binary cache / cachix (maximal) (push) Waiting to run
Set up binary cache / cachix (nix) (push) Waiting to run
Treewide Checks / Validate flake (push) Waiting to run
Treewide Checks / Check formatting (push) Waiting to run
Treewide Checks / Check source tree for typos (push) Waiting to run
Treewide Checks / Validate documentation builds (push) Waiting to run
Treewide Checks / Validate hyperlinks in documentation sources (push) Waiting to run
Treewide Checks / Validate Editorconfig conformance (push) Waiting to run
Build and deploy documentation / Check latest commit (push) Waiting to run
Build and deploy documentation / publish (push) Blocked by required conditions

conform: respect vim.lsp.formatOnSave and vim.lsp.mappings.toggleFormatOnSave
This commit is contained in:
raf 2025-05-09 14:12:55 +00:00 committed by GitHub
commit 65e1fdd97b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 102 additions and 92 deletions

View file

@ -109,6 +109,7 @@
- Add tsx support in conform and lint - Add tsx support in conform and lint
- Moved code setting `additionalRuntimePaths` and `enableLuaLoader` out of - Moved code setting `additionalRuntimePaths` and `enableLuaLoader` out of
`luaConfigPre`'s default to prevent being overridden `luaConfigPre`'s default to prevent being overridden
- Use conform over custom autocmds for LSP format on save
[diniamo](https://github.com/diniamo): [diniamo](https://github.com/diniamo):
@ -312,6 +313,8 @@
- Fix fzf-lua having a hard dependency on fzf. - Fix fzf-lua having a hard dependency on fzf.
- Enable inlay hints support - `config.vim.lsp.inlayHints`. - Enable inlay hints support - `config.vim.lsp.inlayHints`.
- Add `neo-tree`, `snacks.picker` extensions to `lualine`. - Add `neo-tree`, `snacks.picker` extensions to `lualine`.
- Add support for `vim.lsp.formatOnSave` and
`vim.lsp.mappings.toggleFormatOnSave`
[tebuevd](https://github.com/tebuevd): [tebuevd](https://github.com/tebuevd):
@ -361,7 +364,8 @@
[Hardtime.nvim]: https://github.com/m4xshen/hardtime.nvim [Hardtime.nvim]: https://github.com/m4xshen/hardtime.nvim
- Add Plugin [Hardtime.nvim] under `vim.binds.hardtime-nvim` with `enable` and `setupOpts` options - Add Plugin [Hardtime.nvim] under `vim.binds.hardtime-nvim` with `enable` and
`setupOpts` options
[taylrfnt](https://github.com/taylrfnt): [taylrfnt](https://github.com/taylrfnt):

View file

@ -1,12 +1,9 @@
{ {lib, ...}: let
pkgs, inherit (lib.generators) mkLuaInline;
lib, inherit (lib.options) mkOption mkEnableOption literalMD;
... inherit (lib.types) attrs either nullOr;
}: let inherit (lib.nvim.lua) toLuaObject;
inherit (lib.options) mkOption mkEnableOption literalExpression; inherit (lib.nvim.types) luaInline mkPluginSetupOption;
inherit (lib.types) attrs enum nullOr;
inherit (lib.nvim.types) mkPluginSetupOption;
inherit (lib.nvim.lua) mkLuaInline;
in { in {
options.vim.formatter.conform-nvim = { options.vim.formatter.conform-nvim = {
enable = mkEnableOption "lightweight yet powerful formatter plugin for Neovim [conform-nvim]"; enable = mkEnableOption "lightweight yet powerful formatter plugin for Neovim [conform-nvim]";
@ -31,26 +28,46 @@ in {
}; };
format_on_save = mkOption { format_on_save = mkOption {
type = nullOr attrs; type = nullOr (either attrs luaInline);
default = { default = mkLuaInline ''
lsp_format = "fallback"; function()
timeout_ms = 500; 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`
'';
description = '' description = ''
Table that will be passed to `conform.format()`. If this Attribute set or Lua function that will be passed to
is set, Conform will run the formatter on save. `conform.format()`. If this is set, Conform will run the formatter
on save.
''; '';
}; };
format_after_save = mkOption { format_after_save = let
type = nullOr attrs; defaultFormatAfterSaveOpts = {lsp_format = "fallback";};
default = {lsp_format = "fallback";}; in
description = '' mkOption {
Table that will be passed to `conform.format()`. If this type = nullOr (either attrs luaInline);
is set, Conform will run the formatter asynchronously after default = mkLuaInline ''
save. 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.
'';
};
}; };
}; };
} }

View file

@ -6,6 +6,7 @@
}: let }: let
inherit (lib.generators) mkLuaInline; inherit (lib.generators) mkLuaInline;
inherit (lib.modules) mkIf; inherit (lib.modules) mkIf;
inherit (lib.lists) optional;
inherit (lib.strings) optionalString; inherit (lib.strings) optionalString;
inherit (lib.trivial) boolToString; inherit (lib.trivial) boolToString;
inherit (lib.nvim.binds) addDescriptionsToMappings; inherit (lib.nvim.binds) addDescriptionsToMappings;
@ -14,7 +15,10 @@
usingNvimCmp = config.vim.autocomplete.nvim-cmp.enable; usingNvimCmp = config.vim.autocomplete.nvim-cmp.enable;
usingBlinkCmp = config.vim.autocomplete.blink-cmp.enable; usingBlinkCmp = config.vim.autocomplete.blink-cmp.enable;
self = import ./module.nix {inherit config lib pkgs;}; 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; mappingDefinitions = self.options.vim.lsp.mappings;
mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions; mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions;
mkBinding = binding: action: mkBinding = binding: action:
@ -29,24 +33,59 @@ in {
sourcePlugins = ["cmp-nvim-lsp"]; sourcePlugins = ["cmp-nvim-lsp"];
}; };
augroups = [{name = augroup;}];
autocmds = autocmds =
if cfg.inlayHints.enable (optional cfg.inlayHints.enable {
then [ group = augroup;
{ event = ["LspAttach"];
callback = mkLuaInline '' desc = "LSP on-attach enable inlay hints autocmd";
function(event) callback = mkLuaInline ''
local bufnr = event.buf function(event)
local client = vim.lsp.get_client_by_id(event.data.client_id) local bufnr = event.buf
if client and client.supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then local client = vim.lsp.get_client_by_id(event.data.client_id)
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = bufnr }), { bufnr = bufnr }) 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
end end
end end
''; ''}
desc = "LSP on-attach enable inlay hints autocmd";
event = ["LspAttach"]; local clients = vim.lsp.get_clients({
} bufnr = bufnr,
] method = "textDocument/formatting",
else []; })
if clients[1] then
vim.lsp.buf.format({ bufnr = bufnr, id = clients[1].id })
end
end
'';
});
pluginRC.lsp-setup = '' pluginRC.lsp-setup = ''
vim.g.formatsave = ${boolToString cfg.formatOnSave}; vim.g.formatsave = ${boolToString cfg.formatOnSave};
@ -74,60 +113,9 @@ in {
${mkBinding mappings.toggleFormatOnSave "function() vim.b.disableFormatSave = not vim.b.disableFormatSave end"} ${mkBinding mappings.toggleFormatOnSave "function() vim.b.disableFormatSave = not vim.b.disableFormatSave end"}
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")''} ${optionalString config.vim.ui.breadcrumbs.enable ''local navic = require("nvim-navic")''}
default_on_attach = function(client, bufnr) default_on_attach = function(client, bufnr)
attach_keymaps(client, bufnr) attach_keymaps(client, bufnr)
format_callback(client, bufnr)
${optionalString config.vim.ui.breadcrumbs.enable '' ${optionalString config.vim.ui.breadcrumbs.enable ''
-- let navic attach to buffers -- let navic attach to buffers
if client.server_capabilities.documentSymbolProvider then if client.server_capabilities.documentSymbolProvider then
@ -138,6 +126,7 @@ in {
local capabilities = vim.lsp.protocol.make_client_capabilities() local capabilities = vim.lsp.protocol.make_client_capabilities()
${optionalString usingNvimCmp '' ${optionalString usingNvimCmp ''
-- TODO(horriblename): migrate to vim.lsp.config['*']
-- HACK: copied from cmp-nvim-lsp. If we ever lazy load lspconfig we -- HACK: copied from cmp-nvim-lsp. If we ever lazy load lspconfig we
-- should re-evaluate whether we can just use `default_capabilities` -- should re-evaluate whether we can just use `default_capabilities`
capabilities = { capabilities = {