Closed Kamilcuk closed 3 weeks ago
After a bit of tinkering I was able to do the following design:
---@class LinterSpec
---@field [1] string
---@field pattern? string
---@field [2] string[]
---@field groups? string[]
---@field [3] table<string, vim.diagnostic.Severity>
---@field severity_map? table<string, vim.diagnostic.Severity>
---@field [4] table
---@field defaults? table
---@field [5] {col_offset?: integer, end_col_offset?: integer, lnum_offset?: integer, end_lnum_offset?: integer}
---@field opts? {col_offset?: integer, end_col_offset?: integer, lnum_offset?: integer, end_lnum_offset?: integer}
---@field col_offset? integer
---@field end_col_offset? integer
---@field lnum_offset? integer
---@field end_lnum_offset? integer
---@class LintersSpec
---@field defaults? table
---@param patterns LinterSpec[]|LintersSpec
local function from_patterns(patterns)
return function(output, bufnr)
local diagnostics = {}
for _, pattern in ipairs(patterns) do
local args = {
pattern.pattern or pattern[1],
pattern.groups or pattern[2],
pattern.severity_map or pattern[3],
pattern.defaults or pattern[4] or patterns.defaults,
pattern.opts or pattern[5] or {
col_offset = pattern.col_offset,
end_col_offset = pattern.end_col_offset,
lnum_offset = pattern.lnum_offset,
end_lnum_offset = pattern.end_lnum_offset,
},
}
local result = require("lint.parser").from_pattern(unpack(args))(output, bufnr)
for _, diagnostic in ipairs(result) do
table.insert(diagnostics, diagnostic)
end
end
return diagnostics
end
end
-- Add nomad as a linter for hcl files.
require("lint").linters.nomad = {
name = "nomad",
cmd = "nomad",
stdin = false,
append_fname = true,
args = { "job", "validate" },
stream = "both",
ignore_exitcode = false,
parser = from_patterns {
defaults = { severity = vim.diagnostic.severity.ERROR },
{
"[^:]+:(%d+): (.+)",
{ "lnum", "message" },
},
{
"[^:]+:(%d+),(%d+)-(%d+): (.+)",
{ "lnum", "col", "col_end", "message" },
},
},
}
require("lint").linters_by_ft = {
hcl = { "nomad" },
}
I'd rather not add yet another variant given that errorformat already supports multiple patterns and as far as I can tell it's rare for linters to output several patterns.
Can the output format of nomad be configured? What other linters would need this?
With https://github.com/mfussenegger/nvim-lint/pull/635 you should be able to use something like this instead:
local pattern = function(line)
local lnum, message = line:match("[^:]+:(%d+): (.+)")
if lnum then
return {lnum, 0, 0, message}
else
return {line:match("[^:]+:(%d+),(%d+)-(%d+): (.+)")}
end
end
local groups = {"lnum", "col", "end_col", "message"}
return {
cmd = "nomad",
args = {"job", "validate"},
ignore_exitcode = true,
stdin = false,
stream = "stderr",
parser = require("lint.parser").from_pattern(pattern, groups)
}
There are situations where tools output several patterns. This is internally handled separately:
https://github.com/mfussenegger/nvim-lint/blob/efc6fc83f0772283e064c53a8f9fb5645bde0bc0/lua/lint/linters/ruby.lua#L8
I propose to add a "from_patterns" function, that will take several patterns, and deprecated from_pattern to reduce API.
Thanks, nvim-lint is amazing, I am using it and it is great.