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,
helpers,
config,
pkgs,
...
}:
with lib;
let
cfg = config.plugins.conform-nvim;
inherit (lib) types;
inherit (lib.nixvim) defaultNullOpts mkRaw;
in
{
options.plugins.conform-nvim = helpers.neovim-plugin.extraOptionsOptions // {
enable = mkEnableOption "conform-nvim";
lib.nixvim.neovim-plugin.mkNeovimPlugin config {
name = "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
# Map of filetype to formatters
formattersByFt =
@ -26,8 +102,12 @@ in
lua = [ "stylua" ];
# Conform will run multiple formatters sequentially
python = [ "isort" "black" ];
# Use a sub-list to run only the first available formatter
javascript = [ [ "prettierd" "prettier" ] ];
# Use stop_after_first to run only the first available formatter
javascript = {
__unkeyed-1 = "prettierd";
__unkeyed-2 = "prettier";
stop_after_first = true;
};
# Use the "*" filetype to run formatters on all filetypes.
"*" = [ "codespell" ];
# 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' {
type =
with helpers.nixvimTypes;
either strLuaFn (submodule {
options = {
lspFallback = mkOption {
type = types.bool;
default = true;
description = "See :help conform.format for details.";
};
timeoutMs = mkOption {
type = types.int;
default = 500;
description = "See :help conform.format for details.";
};
settingsExample = lib.literalMD ''
```nix
{
formattersByFt = {
bash = [
"shellcheck"
"shellharden"
"shfmt"
];
cpp = [ "clang_format" ];
javascript = {
__unkeyed-1 = "prettierd";
__unkeyed-2 = "prettier";
timeout_ms = 2000;
stop_after_first = true;
};
});
# Unknown plugin default
description = ''
If this is set, Conform will run the formatter on save.
It will pass the table to conform.format().
This can also be a function that returns the table.
See :help conform.format for details.
'';
};
"_" = [
"squeeze_blanks"
"trim_whitespace"
"trim_newlines"
];
};
format_on_save = # Lua
'''
function(bufnr)
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
formatAfterSave = helpers.defaultNullOpts.mkNullable' {
type =
with helpers.nixvimTypes;
either strLuaFn (submodule {
options = {
lspFallback = mkOption {
type = types.bool;
default = true;
description = "See :help conform.format for details.";
};
if slow_format_filetypes[vim.bo[bufnr].filetype] then
return
end
local function on_format(err)
if err and err:match("timeout$") then
slow_format_filetypes[vim.bo[bufnr].filetype] = true
end
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;
};
});
# Unknown plugin default
description = ''
If this is set, Conform will run the formatter asynchronously after save.
It will pass the table to conform.format().
This can also be a function that returns the table.
'';
};
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})
'';
};
shfmt = {
command = lib.getExe pkgs.shfmt;
};
shellharden = {
command = lib.getExe pkgs.shellharden;
};
squeeze_blanks = {
command = lib.getExe' pkgs.coreutils "cat";
};
};
}
```
'';
}

View file

@ -1,3 +1,4 @@
{ lib, pkgs, ... }:
{
empty = {
plugins.conform-nvim.enable = true;
@ -7,69 +8,107 @@
plugins.conform-nvim = {
enable = true;
formattersByFt = {
lua = [ "stylua" ];
python = [
"isort"
"black"
];
javascript = [
[
"prettierd"
"prettier"
]
];
"*" = [ "codespell" ];
"_" = [ "trimWhitespace" ];
};
formatOnSave = {
lspFallback = true;
timeoutMs = 500;
};
formatAfterSave = {
lspFallback = true;
};
logLevel = "error";
notifyOnError = true;
formatters = {
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" ];
settings = {
formatters_by_ft = { };
format_on_save = {
lsp_format = "never";
timeout_ms = 1000;
quiet = false;
stop_after_first = false;
};
default_format_opts = {
lsp_format = "never";
timeout_ms = 1000;
quiet = false;
stop_after_first = false;
};
format_after_save = {
lsp_format = "never";
timeout_ms = 1000;
quiet = false;
stop_after_first = false;
};
log_level = "error";
notify_on_error = true;
notify_no_formatters = true;
formatters = { };
};
};
};
example = {
plugins.conform-nvim = {
enable = true;
settings = {
formatters_by_ft = {
lua = [ "stylua" ];
python = [
"isort"
"black"
];
javascript = {
__unkeyed-1 = "prettierd";
__unkeyed-2 = "prettier";
timeout_ms = 2000;
stop_after_first = true;
};
"*" = [ "codespell" ];
"_" = [ "trimWhitespace" ];
};
format_on_save = {
lsp_format = "fallback";
timeout_ms = 500;
};
format_after_save = {
lsp_format = "fallback";
};
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 = {
enable = true;
formattersByFt = {
lua = [ "stylua" ];
python = [
"isort"
"black"
];
javascript = [
[
"prettierd"
"prettier"
]
];
"*" = [ "codespell" ];
"_" = [ "trimWhitespace" ];
settings = {
format_on_save = ''
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
'';
};
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 = {
enable = true;
formattersByFt = {
lua = [ "stylua" ];
python = [
"isort"
"black"
];
javascript = [
[
"prettierd"
"prettier"
]
];
"*" = [ "codespell" ];
"_" = [ "trimWhitespace" ];
settings = {
format_after_save = ''
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
'';
};
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
'';
};
};
}