From a436aca603a0c95b9b085d05ce9593b9afd99c1b Mon Sep 17 00:00:00 2001 From: rice-cracker-dev Date: Sat, 12 Apr 2025 20:53:19 +0700 Subject: [PATCH 1/9] nvim-lint: added required files support --- docs/release-notes/rl-0.8.md | 1 + .../plugins/diagnostics/nvim-lint/config.nix | 25 ++++++++++- .../diagnostics/nvim-lint/nvim-lint.nix | 7 +++ modules/plugins/languages/astro.nix | 43 +++++++------------ modules/plugins/languages/svelte.nix | 23 ++++------ modules/plugins/languages/ts.nix | 40 +++++++---------- 6 files changed, 71 insertions(+), 68 deletions(-) diff --git a/docs/release-notes/rl-0.8.md b/docs/release-notes/rl-0.8.md index 710578eb..d5190855 100644 --- a/docs/release-notes/rl-0.8.md +++ b/docs/release-notes/rl-0.8.md @@ -290,6 +290,7 @@ - `eslint_d` now checks for configuration files to load. - Fixed an error where `eslint_d` fails to load. +- Added required files support for linters under `vim.diagnostics.nvim-lint.linters.*.required_files`. [Sc3l3t0n](https://github.com/Sc3l3t0n): diff --git a/modules/plugins/diagnostics/nvim-lint/config.nix b/modules/plugins/diagnostics/nvim-lint/config.nix index b284270b..c7326cff 100644 --- a/modules/plugins/diagnostics/nvim-lint/config.nix +++ b/modules/plugins/diagnostics/nvim-lint/config.nix @@ -38,8 +38,29 @@ in { { event = ["BufWritePost"]; callback = mkLuaInline '' - function() - require("lint").try_lint() + function(args) + local ft = vim.api.nvim_get_option_value("filetype", { buf = args.buf }) + local linters = require("lint").linters + local linters_from_ft = require("lint").linters_by_ft[ft] + + -- if no linter is configured for this filetype, stops linting + if linters_from_ft == nil then return end + + for _, name in ipairs(linters_from_ft) do + local cwd = linters[name].required_files + + -- if no configuration files are configured, lint + if cwd == nil then + require("lint").try_lint(name) + else + -- if configuration files are configured and present in the project, lint + for _, fn in ipairs(cwd) do + if vim.uv.fs_stat(fn) then + require("lint").try_lint(name) + end + end + end + end end ''; } diff --git a/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix b/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix index 20f14f0b..cb830975 100644 --- a/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix +++ b/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix @@ -69,6 +69,13 @@ default = null; description = "Parser function"; }; + + required_files = mkOption { + type = nullOr (listOf str); + default = null; + description = "Required files to lint"; + example = ["eslint.config.js"]; + }; }; }; in { diff --git a/modules/plugins/languages/astro.nix b/modules/plugins/languages/astro.nix index c12f6ada..2ecbbe47 100644 --- a/modules/plugins/languages/astro.nix +++ b/modules/plugins/languages/astro.nix @@ -53,24 +53,20 @@ # TODO: specify packages defaultDiagnosticsProvider = ["eslint_d"]; diagnosticsProviders = { - eslint_d = { - package = pkgs.eslint_d; + eslint_d = let + pkg = pkgs.eslint_d; + in { + package = pkg; config = { - # HACK: change if nvim-lint gets a dynamic enable thing - parser = mkLuaInline '' - function(output, bufnr, cwd) - local markers = { "eslint.config.js", "eslint.config.mjs", - ".eslintrc", ".eslintrc.json", ".eslintrc.js", ".eslintrc.yml", } - for _, filename in ipairs(markers) do - local path = vim.fs.joinpath(cwd, filename) - if vim.loop.fs_stat(path) then - return require("lint.linters.eslint_d").parser(output, bufnr, cwd) - end - end - - return {} - end - ''; + cmd = getExe pkg; + required_files = [ + "eslint.config.js" + "eslint.config.mjs" + ".eslintrc" + ".eslintrc.json" + ".eslintrc.js" + ".eslintrc.yml" + ]; }; }; }; @@ -153,16 +149,9 @@ in { vim.diagnostics.nvim-lint = { enable = true; linters_by_ft.astro = cfg.extraDiagnostics.types; - linters = mkMerge (map ( - name: { - ${name} = - diagnosticsProviders.${name}.config - // { - cmd = getExe diagnosticsProviders.${name}.package; - }; - } - ) - cfg.extraDiagnostics.types); + linters = + mkMerge (map (name: {${name} = diagnosticsProviders.${name}.config;}) + cfg.extraDiagnostics.types); }; }) ]); diff --git a/modules/plugins/languages/svelte.nix b/modules/plugins/languages/svelte.nix index e01ec427..536ff2c1 100644 --- a/modules/plugins/languages/svelte.nix +++ b/modules/plugins/languages/svelte.nix @@ -55,21 +55,14 @@ package = pkg; config = { cmd = getExe pkg; - # HACK: change if nvim-lint gets a dynamic enable thing - parser = mkLuaInline '' - function(output, bufnr, cwd) - local markers = { "eslint.config.js", "eslint.config.mjs", - ".eslintrc", ".eslintrc.json", ".eslintrc.js", ".eslintrc.yml", } - for _, filename in ipairs(markers) do - local path = vim.fs.joinpath(cwd, filename) - if vim.loop.fs_stat(path) then - return require("lint.linters.eslint_d").parser(output, bufnr, cwd) - end - end - - return {} - end - ''; + required_files = [ + "eslint.config.js" + "eslint.config.mjs" + ".eslintrc" + ".eslintrc.json" + ".eslintrc.js" + ".eslintrc.yml" + ]; }; }; }; diff --git a/modules/plugins/languages/ts.nix b/modules/plugins/languages/ts.nix index ffab265b..df1353ab 100644 --- a/modules/plugins/languages/ts.nix +++ b/modules/plugins/languages/ts.nix @@ -91,27 +91,20 @@ # TODO: specify packages defaultDiagnosticsProvider = ["eslint_d"]; diagnosticsProviders = { - eslint_d = { - package = pkgs.eslint_d; - config = let - pkg = pkgs.eslint_d; - in { + eslint_d = let + pkg = pkgs.eslint_d; + in { + package = pkg; + config = { cmd = getExe pkg; - # HACK: change if nvim-lint gets a dynamic enable thing - parser = mkLuaInline '' - function(output, bufnr, cwd) - local markers = { "eslint.config.js", "eslint.config.mjs", - ".eslintrc", ".eslintrc.json", ".eslintrc.js", ".eslintrc.yml", } - for _, filename in ipairs(markers) do - local path = vim.fs.joinpath(cwd, filename) - if vim.loop.fs_stat(path) then - return require("lint.linters.eslint_d").parser(output, bufnr, cwd) - end - end - - return {} - end - ''; + required_files = [ + "eslint.config.js" + "eslint.config.mjs" + ".eslintrc" + ".eslintrc.json" + ".eslintrc.js" + ".eslintrc.yml" + ]; }; }; }; @@ -221,10 +214,9 @@ in { linters_by_ft.typescript = cfg.extraDiagnostics.types; linters_by_ft.typescriptreact = cfg.extraDiagnostics.types; - linters = mkMerge (map (name: { - ${name}.cmd = getExe diagnosticsProviders.${name}.package; - }) - cfg.extraDiagnostics.types); + linters = + mkMerge (map (name: {${name} = diagnosticsProviders.${name}.config;}) + cfg.extraDiagnostics.types); }; }) From 5c3a90e3f661572ddcb23ccd52a9e7fb67d8ab32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phan=20=C4=90=C4=83ng=20Khoa?= Date: Sun, 13 Apr 2025 16:06:42 +0700 Subject: [PATCH 2/9] Update modules/plugins/diagnostics/nvim-lint/config.nix Co-authored-by: Ching Pei Yang <59727193+horriblename@users.noreply.github.com> --- modules/plugins/diagnostics/nvim-lint/config.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/plugins/diagnostics/nvim-lint/config.nix b/modules/plugins/diagnostics/nvim-lint/config.nix index c7326cff..69d9b35b 100644 --- a/modules/plugins/diagnostics/nvim-lint/config.nix +++ b/modules/plugins/diagnostics/nvim-lint/config.nix @@ -47,7 +47,13 @@ in { if linters_from_ft == nil then return end for _, name in ipairs(linters_from_ft) do - local cwd = linters[name].required_files + local linter = linters[name] + assert(linter, 'Linter with name `' .. name .. '` not available') + + if type(linter) == "function" then + linter = linter() + end + local cwd = linter.required_files -- if no configuration files are configured, lint if cwd == nil then From f4ee6a275f2cd4dc40c599c63c13e6cbab31256e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phan=20=C4=90=C4=83ng=20Khoa?= Date: Sun, 13 Apr 2025 16:06:58 +0700 Subject: [PATCH 3/9] Update modules/plugins/diagnostics/nvim-lint/config.nix Co-authored-by: Ching Pei Yang <59727193+horriblename@users.noreply.github.com> --- modules/plugins/diagnostics/nvim-lint/config.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/plugins/diagnostics/nvim-lint/config.nix b/modules/plugins/diagnostics/nvim-lint/config.nix index 69d9b35b..e1ef789a 100644 --- a/modules/plugins/diagnostics/nvim-lint/config.nix +++ b/modules/plugins/diagnostics/nvim-lint/config.nix @@ -57,7 +57,7 @@ in { -- if no configuration files are configured, lint if cwd == nil then - require("lint").try_lint(name) + require("lint").lint(linter) else -- if configuration files are configured and present in the project, lint for _, fn in ipairs(cwd) do From 2b62a441e9c0383451bc1796380e7ce8d76866dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phan=20=C4=90=C4=83ng=20Khoa?= Date: Sun, 13 Apr 2025 16:07:27 +0700 Subject: [PATCH 4/9] Update modules/plugins/diagnostics/nvim-lint/nvim-lint.nix Co-authored-by: Ching Pei Yang <59727193+horriblename@users.noreply.github.com> --- modules/plugins/diagnostics/nvim-lint/nvim-lint.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix b/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix index cb830975..6657be69 100644 --- a/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix +++ b/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix @@ -73,7 +73,7 @@ required_files = mkOption { type = nullOr (listOf str); default = null; - description = "Required files to lint"; + description = "Required files to lint. These files must exist relative to the cwd of the linter or else this linter will be skipped"; example = ["eslint.config.js"]; }; }; From 90d09ba05f1460214759241ce08c0dc686eb0b32 Mon Sep 17 00:00:00 2001 From: rice-cracker-dev Date: Sun, 13 Apr 2025 20:57:23 +0700 Subject: [PATCH 5/9] nvim-lint: switch to .lint() --- modules/plugins/diagnostics/nvim-lint/config.nix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/plugins/diagnostics/nvim-lint/config.nix b/modules/plugins/diagnostics/nvim-lint/config.nix index e1ef789a..f1c2f8c2 100644 --- a/modules/plugins/diagnostics/nvim-lint/config.nix +++ b/modules/plugins/diagnostics/nvim-lint/config.nix @@ -53,6 +53,8 @@ in { if type(linter) == "function" then linter = linter() end + -- for require("lint").lint() to work, linter.name must be set + linter.name = linter.name or name local cwd = linter.required_files -- if no configuration files are configured, lint @@ -61,8 +63,10 @@ in { else -- if configuration files are configured and present in the project, lint for _, fn in ipairs(cwd) do - if vim.uv.fs_stat(fn) then - require("lint").try_lint(name) + local path = vim.fs.joinpath(linter.cwd or vim.fn.getcwd(), fn); + if vim.uv.fs_stat(path) then + require("lint").lint(linter) + break end end end From acbeb26854300be3186ac6176e98f5f84c129f30 Mon Sep 17 00:00:00 2001 From: rice-cracker-dev Date: Mon, 14 Apr 2025 00:02:54 +0700 Subject: [PATCH 6/9] nvim-lint: moved linting into its own global function "nvf_lint(buf)" --- .../plugins/diagnostics/nvim-lint/config.nix | 68 ++++++++++--------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/modules/plugins/diagnostics/nvim-lint/config.nix b/modules/plugins/diagnostics/nvim-lint/config.nix index f1c2f8c2..fca38cfa 100644 --- a/modules/plugins/diagnostics/nvim-lint/config.nix +++ b/modules/plugins/diagnostics/nvim-lint/config.nix @@ -28,6 +28,41 @@ in { end end end + + function nvf_lint(buf) + local ft = vim.api.nvim_get_option_value("filetype", { buf = buf }) + local linters = require("lint").linters + local linters_from_ft = require("lint").linters_by_ft[ft] + + -- if no linter is configured for this filetype, stops linting + if linters_from_ft == nil then return end + + for _, name in ipairs(linters_from_ft) do + local linter = linters[name] + assert(linter, 'Linter with name `' .. name .. '` not available') + + if type(linter) == "function" then + linter = linter() + end + -- for require("lint").lint() to work, linter.name must be set + linter.name = linter.name or name + local cwd = linter.required_files + + -- if no configuration files are configured, lint + if cwd == nil then + require("lint").lint(linter) + else + -- if configuration files are configured and present in the project, lint + for _, fn in ipairs(cwd) do + local path = vim.fs.joinpath(linter.cwd or vim.fn.getcwd(), fn); + if vim.uv.fs_stat(path) then + require("lint").lint(linter) + break + end + end + end + end + end ''; }; }) @@ -39,38 +74,7 @@ in { event = ["BufWritePost"]; callback = mkLuaInline '' function(args) - local ft = vim.api.nvim_get_option_value("filetype", { buf = args.buf }) - local linters = require("lint").linters - local linters_from_ft = require("lint").linters_by_ft[ft] - - -- if no linter is configured for this filetype, stops linting - if linters_from_ft == nil then return end - - for _, name in ipairs(linters_from_ft) do - local linter = linters[name] - assert(linter, 'Linter with name `' .. name .. '` not available') - - if type(linter) == "function" then - linter = linter() - end - -- for require("lint").lint() to work, linter.name must be set - linter.name = linter.name or name - local cwd = linter.required_files - - -- if no configuration files are configured, lint - if cwd == nil then - require("lint").lint(linter) - else - -- if configuration files are configured and present in the project, lint - for _, fn in ipairs(cwd) do - local path = vim.fs.joinpath(linter.cwd or vim.fn.getcwd(), fn); - if vim.uv.fs_stat(path) then - require("lint").lint(linter) - break - end - end - end - end + nvf_lint(args.buf) end ''; } From a3051d49aa5f32d9ceab672bad52d591b8a78a8e Mon Sep 17 00:00:00 2001 From: rice-cracker-dev Date: Mon, 14 Apr 2025 00:03:22 +0700 Subject: [PATCH 7/9] format: formatted the project --- npins/sources.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/npins/sources.nix b/npins/sources.nix index 162f1d94..3ae0b99e 100644 --- a/npins/sources.nix +++ b/npins/sources.nix @@ -98,7 +98,9 @@ builtins.mapAttrs Channel = getZip; Tarball = getUrl; } - .${spec.type} + .${ + spec.type + } or (builtins.throw "Unknown source type ${spec.type}"); in spec // {outPath = mayOverride (func spec);} From f830553166bbf38963413c638d9240d71a0ea8bb Mon Sep 17 00:00:00 2001 From: rice-cracker-dev Date: Mon, 14 Apr 2025 18:01:52 +0700 Subject: [PATCH 8/9] nvim_lint: moved the function into a separate option "lint_function" --- docs/release-notes/rl-0.8.md | 5 +- .../plugins/diagnostics/nvim-lint/config.nix | 35 +----------- .../diagnostics/nvim-lint/nvim-lint.nix | 56 ++++++++++++++++++- 3 files changed, 58 insertions(+), 38 deletions(-) diff --git a/docs/release-notes/rl-0.8.md b/docs/release-notes/rl-0.8.md index d5190855..b8c51358 100644 --- a/docs/release-notes/rl-0.8.md +++ b/docs/release-notes/rl-0.8.md @@ -289,8 +289,9 @@ [rice-cracker-dev](https://github.com/rice-cracker-dev): - `eslint_d` now checks for configuration files to load. -- Fixed an error where `eslint_d` fails to load. -- Added required files support for linters under `vim.diagnostics.nvim-lint.linters.*.required_files`. +- Fix an error where `eslint_d` fails to load. +- Add required files support for linters under `vim.diagnostics.nvim-lint.linters.*.required_files`. +- Add global function `nvf_lint` under `vim.diagnostics.nvim-lint.lint_function`. [Sc3l3t0n](https://github.com/Sc3l3t0n): diff --git a/modules/plugins/diagnostics/nvim-lint/config.nix b/modules/plugins/diagnostics/nvim-lint/config.nix index fca38cfa..488bd70f 100644 --- a/modules/plugins/diagnostics/nvim-lint/config.nix +++ b/modules/plugins/diagnostics/nvim-lint/config.nix @@ -29,40 +29,7 @@ in { end end - function nvf_lint(buf) - local ft = vim.api.nvim_get_option_value("filetype", { buf = buf }) - local linters = require("lint").linters - local linters_from_ft = require("lint").linters_by_ft[ft] - - -- if no linter is configured for this filetype, stops linting - if linters_from_ft == nil then return end - - for _, name in ipairs(linters_from_ft) do - local linter = linters[name] - assert(linter, 'Linter with name `' .. name .. '` not available') - - if type(linter) == "function" then - linter = linter() - end - -- for require("lint").lint() to work, linter.name must be set - linter.name = linter.name or name - local cwd = linter.required_files - - -- if no configuration files are configured, lint - if cwd == nil then - require("lint").lint(linter) - else - -- if configuration files are configured and present in the project, lint - for _, fn in ipairs(cwd) do - local path = vim.fs.joinpath(linter.cwd or vim.fn.getcwd(), fn); - if vim.uv.fs_stat(path) then - require("lint").lint(linter) - break - end - end - end - end - end + nvf_lint = ${toLuaObject cfg.lint_function} ''; }; }) diff --git a/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix b/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix index 6657be69..59c50f1d 100644 --- a/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix +++ b/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix @@ -1,7 +1,8 @@ {lib, ...}: let - inherit (lib.options) mkOption mkEnableOption; + inherit (lib.options) mkOption mkEnableOption literalExpression; inherit (lib.types) nullOr attrsOf listOf str either submodule bool enum; inherit (lib.nvim.types) luaInline; + inherit (lib.generators) mkLuaInline; linterType = submodule { options = { @@ -73,8 +74,11 @@ required_files = mkOption { type = nullOr (listOf str); default = null; - description = "Required files to lint. These files must exist relative to the cwd of the linter or else this linter will be skipped"; example = ["eslint.config.js"]; + description = '' + Required files to lint. These files must exist relative to the cwd + of the linter or else this linter will be skipped + ''; }; }; }; @@ -124,5 +128,53 @@ in { }; lint_after_save = mkEnableOption "autocmd to lint after each save" // {default = true;}; + + lint_function = mkOption { + type = luaInline; + default = mkLuaInline '' + function(buf) + local ft = vim.api.nvim_get_option_value("filetype", { buf = buf }) + local linters = require("lint").linters + local linters_from_ft = require("lint").linters_by_ft[ft] + + -- if no linter is configured for this filetype, stops linting + if linters_from_ft == nil then return end + + for _, name in ipairs(linters_from_ft) do + local linter = linters[name] + assert(linter, 'Linter with name `' .. name .. '` not available') + + if type(linter) == "function" then + linter = linter() + end + -- for require("lint").lint() to work, linter.name must be set + linter.name = linter.name or name + local cwd = linter.required_files + + -- if no configuration files are configured, lint + if cwd == nil then + require("lint").lint(linter) + else + -- if configuration files are configured and present in the project, lint + for _, fn in ipairs(cwd) do + local path = vim.fs.joinpath(linter.cwd or vim.fn.getcwd(), fn); + if vim.uv.fs_stat(path) then + require("lint").lint(linter) + break + end + end + end + end + end + ''; + example = literalExpression '' + mkLuaInline ''' + function(buf) + require("lint").try_lint() + end + ''' + ''; + description = "Define the global function nvf_lint which is used by nvf to lint."; + }; }; } From 05954eec6d6bff2d0ed00f507aa0b50674d051c4 Mon Sep 17 00:00:00 2001 From: rice-cracker-dev Date: Fri, 18 Apr 2025 11:00:16 +0700 Subject: [PATCH 9/9] docs: update vim.diagnostics.nvim-lint.*.required_files description --- modules/plugins/diagnostics/nvim-lint/nvim-lint.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix b/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix index 59c50f1d..956bd76e 100644 --- a/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix +++ b/modules/plugins/diagnostics/nvim-lint/nvim-lint.nix @@ -78,6 +78,13 @@ description = '' Required files to lint. These files must exist relative to the cwd of the linter or else this linter will be skipped + + ::: {.note} + This option is an nvf extension that only takes effect if you + use the `nvf_lint()` lua function. + + See {option}`vim.diagnostics.nvim-lint.lint_function`. + ::: ''; }; };