plugins/conform-nvim: migrate to mkNeovimPlugin

This commit is contained in:
Austin Horstman 2024-08-23 14:40:44 -05:00
parent a1c7932bdb
commit 89b876dc0d
No known key found for this signature in database
2 changed files with 344 additions and 224 deletions

View file

@ -1,24 +1,100 @@
{ {
lib, lib,
helpers,
config, config,
pkgs, pkgs,
... ...
}: }:
with lib;
let let
cfg = config.plugins.conform-nvim; inherit (lib) types;
inherit (lib.nixvim) defaultNullOpts mkRaw;
in in
{ lib.nixvim.neovim-plugin.mkNeovimPlugin config {
options.plugins.conform-nvim = helpers.neovim-plugin.extraOptionsOptions // { name = "conform-nvim";
enable = mkEnableOption "conform-nvim"; luaName = "conform";
originalName = "conform.nvim";
defaultPackage = pkgs.vimPlugins.conform-nvim;
package = helpers.mkPluginPackageOption "conform-nvim" pkgs.vimPlugins.conform-nvim; maintainers = [ lib.maintainers.khaneliman ];
# TODO: added 2024-08-23 remove after 24.11
deprecateExtraOptions = true;
optionsRenamedToSettings = [
"formatters"
"formattersByFt"
"logLevel"
"notifyOnError"
];
imports =
map
(
optionName:
lib.mkRemovedOptionModule
[
"plugins"
"conform-nvim"
optionName
]
''
Please use `plugins.conform-nvim.settings.${lib.nixvim.toSnakeCase optionName}` instead.
Note that nested options will now be snake_case, as well, to match upstream plugin configuration.
''
)
[
"formatAfterSave"
"formatOnSave"
];
settingsOptions =
let
lsp_format =
defaultNullOpts.mkEnumFirstDefault
[
"never"
"fallback"
"prefer"
"first"
"last"
]
''
Option for choosing lsp formatting preference.
- `never`: never use the LSP for formatting.
- `fallback`: LSP formatting is used when no other formatters are available.
- `prefer`: Use only LSP formatting when available.
- `first`: LSP formatting is used when available and then other formatters.
- `last`: Other formatters are used then LSP formatting when available.
'';
timeout_ms = defaultNullOpts.mkUnsignedInt 1000 "Time in milliseconds to block for formatting.";
quiet = defaultNullOpts.mkBool false "Don't show any notifications for warnings or failures.";
stop_after_first = defaultNullOpts.mkBool false "Only run the first available formatter in the list.";
# NOTE: These are the available options for the `default_format_opts` opt.
# They are also included in the `format_opts` options available to `format_after_save` and `format_on_save`.
defaultFormatSubmodule =
with types;
(submodule {
freeformType = attrsOf anything;
options = {
inherit
lsp_format
timeout_ms
quiet
stop_after_first
;
};
});
in
{
formatters_by_ft = defaultNullOpts.mkAttrsOf types.anything { } ''
Creates a table mapping filetypes to formatters.
You can run multiple formatters in a row by adding them in a list.
If you'd like to stop after the first successful formatter, set `stop_after_first`.
formattersByFt = helpers.defaultNullOpts.mkAttrsOf' {
type = types.anything;
# Unknown plugin default
description = ''
```nix ```nix
# Map of filetype to formatters # Map of filetype to formatters
formattersByFt = formattersByFt =
@ -26,8 +102,12 @@ in
lua = [ "stylua" ]; lua = [ "stylua" ];
# Conform will run multiple formatters sequentially # Conform will run multiple formatters sequentially
python = [ "isort" "black" ]; python = [ "isort" "black" ];
# Use a sub-list to run only the first available formatter # Use stop_after_first to run only the first available formatter
javascript = [ [ "prettierd" "prettier" ] ]; javascript = {
__unkeyed-1 = "prettierd";
__unkeyed-2 = "prettier";
stop_after_first = true;
};
# Use the "*" filetype to run formatters on all filetypes. # Use the "*" filetype to run formatters on all filetypes.
"*" = [ "codespell" ]; "*" = [ "codespell" ];
# Use the "_" filetype to run formatters on filetypes that don't # Use the "_" filetype to run formatters on filetypes that don't
@ -36,97 +116,126 @@ in
}; };
``` ```
''; '';
format_on_save = defaultNullOpts.mkNullable' {
type = with types; either strLuaFn defaultFormatSubmodule;
pluginDefault = { };
description = ''
If this is set, Conform will run the formatter asynchronously on save.
Conform will pass the table from `format_on_save` to `conform.format()`.
This can also be a function that returns the table.
See `:help conform.format` for details.
'';
apply = v: if lib.isString v then mkRaw v else v;
};
default_format_opts = defaultNullOpts.mkNullable defaultFormatSubmodule { } ''
The default options to use when calling `conform.format()`.
'';
format_after_save = defaultNullOpts.mkNullable' {
type = with types; either strLuaFn defaultFormatSubmodule;
pluginDefault = { };
description = ''
If this is set, Conform will run the formatter asynchronously after save.
Conform will pass the table from `format_after_save` to `conform.format()`.
This can also be a function that returns the table.
See `:help conform.format` for details.
'';
apply = v: if lib.isString v then mkRaw v else v;
};
log_level = defaultNullOpts.mkLogLevel "error" ''
Set the log level. Use `:ConformInfo` to see the location of the log file.
'';
notify_on_error = defaultNullOpts.mkBool true "Conform will notify you when a formatter errors.";
notify_no_formatters = defaultNullOpts.mkBool true "Conform will notify you when no formatters are available for the buffer.";
formatters =
defaultNullOpts.mkAttrsOf types.anything { }
"Custom formatters and changes to built-in formatters.";
}; };
formatOnSave = helpers.defaultNullOpts.mkNullable' { settingsExample = lib.literalMD ''
type = ```nix
with helpers.nixvimTypes; {
either strLuaFn (submodule { formattersByFt = {
options = { bash = [
lspFallback = mkOption { "shellcheck"
type = types.bool; "shellharden"
default = true; "shfmt"
description = "See :help conform.format for details."; ];
}; cpp = [ "clang_format" ];
timeoutMs = mkOption { javascript = {
type = types.int; __unkeyed-1 = "prettierd";
default = 500; __unkeyed-2 = "prettier";
description = "See :help conform.format for details."; timeout_ms = 2000;
}; stop_after_first = true;
}; };
}); "_" = [
# Unknown plugin default "squeeze_blanks"
description = '' "trim_whitespace"
If this is set, Conform will run the formatter on save. "trim_newlines"
It will pass the table to conform.format(). ];
This can also be a function that returns the table. };
See :help conform.format for details. format_on_save = # Lua
''; '''
}; function(bufnr)
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
formatAfterSave = helpers.defaultNullOpts.mkNullable' { if slow_format_filetypes[vim.bo[bufnr].filetype] then
type = return
with helpers.nixvimTypes; end
either strLuaFn (submodule {
options = { local function on_format(err)
lspFallback = mkOption { if err and err:match("timeout$") then
type = types.bool; slow_format_filetypes[vim.bo[bufnr].filetype] = true
default = true; end
description = "See :help conform.format for details."; end
};
return { timeout_ms = 200, lsp_fallback = true }, on_format
end
''';
format_after_save = # Lua
'''
function(bufnr)
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
if not slow_format_filetypes[vim.bo[bufnr].filetype] then
return
end
return { lsp_fallback = true }
end
''';
log_level = "warn";
notify_on_error = false;
notify_no_formatters = false;
formatters = {
shellcheck = {
command = lib.getExe pkgs.shellcheck;
}; };
}); shfmt = {
# Unknown plugin default command = lib.getExe pkgs.shfmt;
description = '' };
If this is set, Conform will run the formatter asynchronously after save. shellharden = {
It will pass the table to conform.format(). command = lib.getExe pkgs.shellharden;
This can also be a function that returns the table. };
''; squeeze_blanks = {
}; command = lib.getExe' pkgs.coreutils "cat";
};
logLevel = helpers.defaultNullOpts.mkLogLevel "error" '' };
Set the log level. Use `:ConformInfo` to see the location of the log file. }
''; ```
'';
notifyOnError = helpers.defaultNullOpts.mkBool true "Conform will notify you when a formatter errors";
formatters = helpers.defaultNullOpts.mkAttrsOf' {
type = types.anything;
# Unknown plugin default
description = "Custom formatters and changes to built-in formatters";
};
};
config =
let
setupOptions =
with cfg;
{
formatters_by_ft = formattersByFt;
format_on_save =
if builtins.isAttrs formatOnSave then
{
lsp_fallback = formatOnSave.lspFallback;
timeout_ms = formatOnSave.timeoutMs;
}
else
helpers.mkRaw formatOnSave;
format_after_save =
if builtins.isAttrs formatAfterSave then
{ lsp_fallback = formatOnSave.lspFallback; }
else
helpers.mkRaw formatAfterSave;
log_level = logLevel;
notify_on_error = notifyOnError;
inherit formatters;
}
// cfg.extraOptions;
in
mkIf cfg.enable {
extraPlugins = [ cfg.package ];
extraConfigLua = ''
require("conform").setup(${helpers.toLuaObject setupOptions})
'';
};
} }

View file

@ -1,3 +1,4 @@
{ lib, pkgs, ... }:
{ {
empty = { empty = {
plugins.conform-nvim.enable = true; plugins.conform-nvim.enable = true;
@ -7,69 +8,107 @@
plugins.conform-nvim = { plugins.conform-nvim = {
enable = true; enable = true;
formattersByFt = { settings = {
lua = [ "stylua" ]; formatters_by_ft = { };
python = [ format_on_save = {
"isort" lsp_format = "never";
"black" timeout_ms = 1000;
]; quiet = false;
javascript = [ stop_after_first = false;
[ };
"prettierd" default_format_opts = {
"prettier" lsp_format = "never";
] timeout_ms = 1000;
]; quiet = false;
"*" = [ "codespell" ]; stop_after_first = false;
"_" = [ "trimWhitespace" ]; };
}; format_after_save = {
formatOnSave = { lsp_format = "never";
lspFallback = true; timeout_ms = 1000;
timeoutMs = 500; quiet = false;
}; stop_after_first = false;
formatAfterSave = { };
lspFallback = true; log_level = "error";
}; notify_on_error = true;
logLevel = "error"; notify_no_formatters = true;
notifyOnError = true; formatters = { };
formatters = { };
myFormatter = { };
command = "myCmd"; };
args = [
"--stdin-from-filename" example = {
"$FILENAME" plugins.conform-nvim = {
]; enable = true;
rangeArgs = ''
function(ctx) settings = {
return { "--line-start", ctx.range.start[1], "--line-end", ctx.range["end"][1] } formatters_by_ft = {
end; lua = [ "stylua" ];
''; python = [
stdin = true; "isort"
cwd = '' "black"
require("conform.util").rootFile({ ".editorconfig", "package.json" }); ];
''; javascript = {
requireCwd = true; __unkeyed-1 = "prettierd";
condition = '' __unkeyed-2 = "prettier";
function(ctx) timeout_ms = 2000;
return vim.fs.basename(ctx.filename) ~= "README.md" stop_after_first = true;
end; };
''; "*" = [ "codespell" ];
exitCodes = [ "_" = [ "trimWhitespace" ];
0 };
1 format_on_save = {
]; lsp_format = "fallback";
env = { timeout_ms = 500;
VAR = "value"; };
}; format_after_save = {
"inherit" = true; lsp_format = "fallback";
prependArgs = [ "--use-tabs" ]; };
log_level = "error";
notify_on_error = false;
notify_no_formatters = false;
formatters = {
nixfmt = {
command = lib.getExe pkgs.nixfmt-rfc-style;
};
myFormatter = {
command = "myCmd";
args = [
"--stdin-from-filename"
"$FILENAME"
];
rangeArgs = ''
function(ctx)
return { "--line-start", ctx.range.start[1], "--line-end", ctx.range["end"][1] }
end;
'';
stdin = true;
cwd = ''
require("conform.util").rootFile({ ".editorconfig", "package.json" });
'';
requireCwd = true;
condition = ''
function(ctx)
return vim.fs.basename(ctx.filename) ~= "README.md"
end;
'';
exitCodes = [
0
1
];
env = {
VAR = "value";
};
"inherit" = true;
prependArgs = [ "--use-tabs" ];
};
otherFormatter = ''
function(bufnr)
return {
command = "myCmd";
}
end;
'';
}; };
otherFormatter = ''
function(bufnr)
return {
command = "myCmd";
}
end;
'';
}; };
}; };
}; };
@ -78,42 +117,28 @@
plugins.conform-nvim = { plugins.conform-nvim = {
enable = true; enable = true;
formattersByFt = { settings = {
lua = [ "stylua" ]; format_on_save = ''
python = [ function(bufnr)
"isort" local ignore_filetypes = { "helm" }
"black" if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then
]; return
javascript = [ end
[
"prettierd" -- Disable with a global or buffer-local variable
"prettier" if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
] return
]; end
"*" = [ "codespell" ];
"_" = [ "trimWhitespace" ]; -- Disable autoformat for files in a certain path
local bufname = vim.api.nvim_buf_get_name(bufnr)
if bufname:match("/node_modules/") then
return
end
return { timeout_ms = 500, lsp_fallback = true }
end
'';
}; };
formatOnSave = ''
function(bufnr)
local ignore_filetypes = { "helm" }
if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then
return
end
-- Disable with a global or buffer-local variable
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
-- Disable autoformat for files in a certain path
local bufname = vim.api.nvim_buf_get_name(bufnr)
if bufname:match("/node_modules/") then
return
end
return { timeout_ms = 500, lsp_fallback = true }
end
'';
}; };
}; };
@ -121,33 +146,19 @@
plugins.conform-nvim = { plugins.conform-nvim = {
enable = true; enable = true;
formattersByFt = { settings = {
lua = [ "stylua" ]; format_after_save = ''
python = [ function(bufnr)
"isort" if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
"black" return
]; end
javascript = [ if not _conform_slow_format_filetypes[vim.bo[bufnr].filetype] then
[ return
"prettierd" end
"prettier" return { lsp_fallback = true }
] end
]; '';
"*" = [ "codespell" ];
"_" = [ "trimWhitespace" ];
}; };
formatAfterSave = ''
function(bufnr)
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
if not _conform_slow_format_filetypes[vim.bo[bufnr].filetype] then
return
end
return { lsp_fallback = true }
end
'';
}; };
}; };
} }