102 lines
3.4 KiB
Lua
102 lines
3.4 KiB
Lua
-- nvim-lint: Linting support (replaces none-ls diagnostics)
|
|
-- none-ls removed ESLint and many linters, so we use nvim-lint instead
|
|
|
|
return {
|
|
"mfussenegger/nvim-lint",
|
|
event = { "BufReadPre", "BufNewFile" },
|
|
config = function()
|
|
local lint = require("lint")
|
|
|
|
-- Configure linters per filetype
|
|
lint.linters_by_ft = {
|
|
javascript = { "eslint_d" },
|
|
javascriptreact = { "eslint_d" },
|
|
typescript = { "eslint_d" },
|
|
typescriptreact = { "eslint_d" },
|
|
-- markdown linting: manual only (see keymap below)
|
|
php = { "phpcs" },
|
|
-- Python: ruff LSP handles linting
|
|
}
|
|
|
|
-- Helper: Find project-local executable, fallback to global
|
|
local function find_executable(names)
|
|
local cwd = vim.fn.getcwd()
|
|
local mason_bin = vim.fn.stdpath("data") .. "/mason/bin/"
|
|
|
|
local search_paths = {
|
|
cwd .. "/node_modules/.bin/",
|
|
cwd .. "/vendor/bin/",
|
|
mason_bin,
|
|
}
|
|
|
|
for _, name in ipairs(names) do
|
|
for _, path in ipairs(search_paths) do
|
|
local full_path = path .. name
|
|
if vim.fn.executable(full_path) == 1 then
|
|
return full_path
|
|
end
|
|
end
|
|
|
|
if vim.fn.executable(name) == 1 then
|
|
return name
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
-- Configure phpcs for WordPress standards
|
|
lint.linters.phpcs.cmd = find_executable({ "phpcs" }) or "phpcs"
|
|
|
|
-- Build args dynamically based on project ruleset presence
|
|
-- Note: This runs once at config load, checks cwd for phpcs.xml
|
|
local cwd = vim.fn.getcwd()
|
|
local has_project_ruleset =
|
|
vim.loop.fs_stat(cwd .. "/phpcs.xml")
|
|
or vim.loop.fs_stat(cwd .. "/phpcs.xml.dist")
|
|
|
|
local phpcs_args = { "-q", "--report=json" }
|
|
if not has_project_ruleset then
|
|
table.insert(phpcs_args, "--standard=WordPress")
|
|
end
|
|
table.insert(phpcs_args, "-") -- stdin
|
|
|
|
lint.linters.phpcs.args = phpcs_args
|
|
|
|
-- Configure eslint_d to use project-local first
|
|
lint.linters.eslint_d.cmd = find_executable({ "eslint_d", "eslint" }) or "eslint_d"
|
|
-- Note: ~/.eslintrc.json serves as global fallback when no project config exists
|
|
|
|
-- Configure markdownlint
|
|
lint.linters.markdownlint.cmd = find_executable({ "markdownlint" }) or "markdownlint"
|
|
|
|
-- Auto-lint on these events
|
|
local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true })
|
|
vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave" }, {
|
|
group = lint_augroup,
|
|
callback = function()
|
|
lint.try_lint()
|
|
end,
|
|
})
|
|
|
|
-- Commands to enable/disable automatic markdown linting
|
|
vim.api.nvim_create_user_command("MarkdownLintEnable", function()
|
|
lint.linters_by_ft.markdown = { "markdownlint" }
|
|
vim.notify("Markdown linting enabled (automatic)", vim.log.levels.INFO)
|
|
-- Lint immediately
|
|
if vim.bo.filetype == "markdown" then
|
|
lint.try_lint()
|
|
end
|
|
end, { desc = "Enable automatic markdown linting" })
|
|
|
|
vim.api.nvim_create_user_command("MarkdownLintDisable", function()
|
|
lint.linters_by_ft.markdown = nil
|
|
vim.notify("Markdown linting disabled", vim.log.levels.INFO)
|
|
-- Clear existing diagnostics for markdown buffers
|
|
if vim.bo.filetype == "markdown" then
|
|
vim.diagnostic.reset(lint.get_namespace("markdownlint"))
|
|
end
|
|
end, { desc = "Disable automatic markdown linting" })
|
|
end,
|
|
}
|