Update generated neovim config
This commit is contained in:
@ -4,6 +4,8 @@ local notify = vim.notify_once or vim.notify
|
||||
local M = {}
|
||||
|
||||
|
||||
---@alias lint.parse fun(output:string, bufnr:number, linter_cwd:string):vim.Diagnostic[]
|
||||
|
||||
---@class lint.Parser
|
||||
---@field on_chunk fun(chunk: string)
|
||||
---@field on_done fun(publish: fun(diagnostics: vim.Diagnostic[]), bufnr: number, linter_cwd: string)
|
||||
@ -19,7 +21,7 @@ local M = {}
|
||||
---@field ignore_exitcode? boolean if exit code != 1 should be ignored or result in a warning. Defaults to false
|
||||
---@field env? table
|
||||
---@field cwd? string
|
||||
---@field parser lint.Parser|fun(output:string, bufnr:number, linter_cwd:string):vim.Diagnostic[]
|
||||
---@field parser lint.Parser|lint.parse
|
||||
|
||||
|
||||
---@class lint.LintProc
|
||||
@ -321,6 +323,10 @@ function M.lint(linter, opts)
|
||||
-- pop up shortly.
|
||||
detached = not iswin
|
||||
}
|
||||
-- prevents cmd.exe taking over the tab title
|
||||
if iswin then
|
||||
linter_opts.hide = true
|
||||
end
|
||||
local cmd = eval_fn_or_id(linter.cmd)
|
||||
assert(cmd, 'Linter definition must have a `cmd` set: ' .. vim.inspect(linter))
|
||||
handle, pid_or_err = uv.spawn(cmd, linter_opts, function(code)
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
local severities = {
|
||||
note = vim.diagnostic.severity.INFO,
|
||||
warning = vim.diagnostic.severity.WARN,
|
||||
help = vim.diagnostic.severity.HINT,
|
||||
}
|
||||
|
||||
local function parse(diagnostics, file_name, item)
|
||||
for _, span in ipairs(item.spans) do
|
||||
if span.file_name == file_name then
|
||||
local message = item.message
|
||||
if span.suggested_replacement ~= vim.NIL then
|
||||
message = message .. "\nSuggested replacement:\n\n" .. tostring(span.suggested_replacement)
|
||||
end
|
||||
|
||||
table.insert(diagnostics, {
|
||||
lnum = span.line_start - 1,
|
||||
end_lnum = span.line_end - 1,
|
||||
col = span.column_start - 1,
|
||||
end_col = span.column_end - 1,
|
||||
severity = severities[item.level],
|
||||
source = "clippy",
|
||||
message = message
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
for _, child in ipairs(item.children) do
|
||||
parse(diagnostics, file_name, child)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
cmd = "cargo",
|
||||
args = { "clippy", "--message-format=json" },
|
||||
stdin = false,
|
||||
append_fname = false,
|
||||
parser = function(output, bufnr)
|
||||
local diagnostics = {}
|
||||
local items = #output > 0 and vim.split(output, "\n") or {}
|
||||
local file_name = vim.api.nvim_buf_get_name(bufnr)
|
||||
file_name = vim.fn.fnamemodify(file_name, ":.")
|
||||
|
||||
for _, i in ipairs(items) do
|
||||
local item = i ~= "" and vim.json.decode(i) or {}
|
||||
-- cargo also outputs build artifacts messages in addition to diagnostics
|
||||
if item and item.reason == "compiler-message" then
|
||||
parse(diagnostics, file_name, item.message)
|
||||
end
|
||||
end
|
||||
return diagnostics
|
||||
end,
|
||||
}
|
||||
@ -1,15 +1,35 @@
|
||||
-- stdout output in the form "63: resourcs ==> resources, resource"
|
||||
local api = vim.api
|
||||
local pattern = "(%d+): (.*)"
|
||||
local groups = { "lnum", "message" }
|
||||
local severities = nil -- none provided
|
||||
|
||||
local parser = require('lint.parser').from_pattern(pattern, groups, severities, {
|
||||
source = 'codespell',
|
||||
severity = vim.diagnostic.severity.INFO,
|
||||
})
|
||||
return {
|
||||
cmd = 'codespell',
|
||||
args = { '--stdin-single-line', "-" },
|
||||
stdin = true,
|
||||
ignore_exitcode = true,
|
||||
parser = require('lint.parser').from_pattern(pattern, groups, severities, {
|
||||
source = 'codespell',
|
||||
severity = vim.diagnostic.severity.INFO,
|
||||
}),
|
||||
parser = function(output, bufnr, cwd)
|
||||
local result = parser(output, bufnr, cwd)
|
||||
for _, d in ipairs(result) do
|
||||
local start, _, capture = d.message:find("(.*) ==>")
|
||||
if start then
|
||||
-- lenient - lint is async and buffer can change between lint start and result parsing
|
||||
local ok, lines = pcall(api.nvim_buf_get_lines, bufnr, d.lnum, d.lnum + 1, true)
|
||||
if ok then
|
||||
local line = lines[1] or ""
|
||||
local end_
|
||||
start, end_ = line:find(vim.pesc(capture))
|
||||
if start then
|
||||
d.col = start - 1
|
||||
d.end_col = end_
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end,
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ return {
|
||||
local lnum = math.max(0, item.lnum - 1)
|
||||
local col = math.max(0, item.col - 1)
|
||||
local end_lnum = item.end_lnum > 0 and (item.end_lnum - 1) or lnum
|
||||
local end_col = col + word:len() - 2 or col
|
||||
local end_col = col + vim.fn.strdisplaywidth(word) - 2 or col
|
||||
local diagnostic = {
|
||||
lnum = lnum,
|
||||
col = col,
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
return {
|
||||
cmd = 'eugene',
|
||||
args = {
|
||||
'lint',
|
||||
'--format=json',
|
||||
},
|
||||
stdin = false,
|
||||
parser = function(output, _)
|
||||
local diagnostics = {}
|
||||
if #output > 0 then
|
||||
local decoded = vim.json.decode(output)
|
||||
for _, stmt in ipairs(decoded.statements) do
|
||||
for _, tr in ipairs(stmt.triggered_rules) do
|
||||
table.insert(diagnostics, {
|
||||
source = 'eugene',
|
||||
lnum = stmt.line_number,
|
||||
col = 0,
|
||||
severity = vim.diagnostic.severity.ERROR,
|
||||
message = string.format('%s: %s: %s', tr.id, tr.name, tr.url),
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
return diagnostics
|
||||
end,
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
return {
|
||||
cmd = "hledger",
|
||||
stdin = true,
|
||||
args = {"check", "-s", "-f", "-"},
|
||||
stream = "stderr",
|
||||
ignore_exitcode = true,
|
||||
parser = function(output)
|
||||
--- hledger currently outputs at most one error.
|
||||
---@type vim.Diagnostic[]
|
||||
local result = {}
|
||||
local pattern = "hledger: Error: %-:(%d+)(%-?(%d*)):(.*)"
|
||||
local lnum, _, end_lnum, msg = output:match(pattern)
|
||||
lnum = tonumber(lnum)
|
||||
end_lnum = tonumber(end_lnum)
|
||||
if (lnum or 0) > 0 then
|
||||
table.insert(result, {
|
||||
message = msg,
|
||||
col = 0,
|
||||
lnum = lnum - 1,
|
||||
end_lnum = end_lnum and (end_lnum - 1) or nil,
|
||||
severity = vim.diagnostic.severity.ERROR,
|
||||
source = "hledger"
|
||||
})
|
||||
end
|
||||
return result
|
||||
end
|
||||
}
|
||||
@ -19,6 +19,10 @@ return {
|
||||
'--no-color-output',
|
||||
'--no-error-summary',
|
||||
'--no-pretty',
|
||||
'--python-executable',
|
||||
function()
|
||||
return vim.fn.exepath 'python3' or vim.fn.exepath 'python'
|
||||
end
|
||||
},
|
||||
parser = require('lint.parser').from_pattern(
|
||||
pattern,
|
||||
|
||||
@ -9,11 +9,17 @@ local severities = {
|
||||
|
||||
return {
|
||||
cmd = 'pylint',
|
||||
stdin = false,
|
||||
stdin = true,
|
||||
args = {
|
||||
'-f', 'json'
|
||||
'-f',
|
||||
'json',
|
||||
'--from-stdin',
|
||||
function()
|
||||
return vim.api.nvim_buf_get_name(0)
|
||||
end,
|
||||
},
|
||||
ignore_exitcode = true,
|
||||
stream = 'stdout',
|
||||
parser = function(output, bufnr)
|
||||
if output == "" then return {} end
|
||||
local diagnostics = {}
|
||||
|
||||
@ -33,11 +33,15 @@ return {
|
||||
local diagnostics = {}
|
||||
for _, i_filepath in ipairs(per_filepath) do
|
||||
for _, violation in ipairs(i_filepath.violations) do
|
||||
local severity = vim.diagnostic.severity.WARN
|
||||
if violation.code == "PRS" then
|
||||
severity = vim.diagnostic.severity.ERROR
|
||||
end
|
||||
table.insert(diagnostics, {
|
||||
source = 'sqlfluff',
|
||||
lnum = (violation.line_no or violation.start_line_no) - 1,
|
||||
col = (violation.line_pos or violation.start_line_pos) - 1,
|
||||
severity = vim.diagnostic.severity.ERROR,
|
||||
severity = severity,
|
||||
message = violation.description,
|
||||
user_data = {lsp = {code = violation.code}},
|
||||
})
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
return {
|
||||
cmd = "systemd-analyze",
|
||||
args = {"verify"},
|
||||
ignore_exitcode = true,
|
||||
stdin = false,
|
||||
stream = "stderr",
|
||||
parser = require("lint.parser").from_errorformat("%f:%l:%m", {
|
||||
source = "systemd",
|
||||
severity = vim.diagnostic.severity.WARN
|
||||
})
|
||||
}
|
||||
@ -17,6 +17,7 @@ return {
|
||||
cmd = 'tidy',
|
||||
stdin = true,
|
||||
stream = 'stderr',
|
||||
ignore_exitcode = true,
|
||||
args = {
|
||||
'-quiet',
|
||||
'-errors',
|
||||
|
||||
@ -10,6 +10,9 @@ local severity_by_qftype = {
|
||||
|
||||
-- Return a parse function that uses an errorformat to parse the output.
|
||||
-- See `:help errorformat`
|
||||
---@param efm string
|
||||
---@param skeleton table<string, any> | vim.Diagnostic
|
||||
---@return lint.parse
|
||||
function M.from_errorformat(efm, skeleton)
|
||||
skeleton = skeleton or {}
|
||||
skeleton.severity = skeleton.severity or vd.severity.ERROR
|
||||
@ -17,7 +20,7 @@ function M.from_errorformat(efm, skeleton)
|
||||
local lines = vim.split(output, '\n')
|
||||
local qflist = vim.fn.getqflist({ efm = efm, lines = lines })
|
||||
local result = {}
|
||||
for _, item in pairs(qflist.items) do
|
||||
for _, item in ipairs(qflist.items) do
|
||||
if item.valid == 1 and (bufnr == nil or item.bufnr == 0 or item.bufnr == bufnr) then
|
||||
local lnum = math.max(0, item.lnum - 1)
|
||||
local col = math.max(0, item.col - 1)
|
||||
@ -46,19 +49,39 @@ local normalize = (vim.fs ~= nil and vim.fs.normalize ~= nil)
|
||||
|
||||
--- Parse a linter's output using a Lua pattern
|
||||
---
|
||||
---@param pattern string
|
||||
---@param pattern string|vim.lpeg.Pattern|fun(line: string):string[]
|
||||
---@param groups string[]
|
||||
---@param severity_map? table<string, vim.diagnostic.Severity>
|
||||
---@param defaults? table
|
||||
---@param opts? {col_offset?: integer, end_col_offset?: integer, lnum_offset?: integer, end_lnum_offset?: integer}
|
||||
---@return lint.parse
|
||||
function M.from_pattern(pattern, groups, severity_map, defaults, opts)
|
||||
defaults = defaults or {}
|
||||
severity_map = severity_map or {}
|
||||
opts = opts or {}
|
||||
|
||||
local type_ = type(pattern)
|
||||
local matchline
|
||||
if type_ == "string" then
|
||||
matchline = function(line)
|
||||
return { line:match(pattern) }
|
||||
end
|
||||
elseif type_ == "function" then
|
||||
matchline = pattern
|
||||
else
|
||||
matchline = function(line)
|
||||
return { pattern:match(line) }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Like vim.diagnostic.match but also checks if a `file` group matches the buffer path
|
||||
-- Some linters produce diagnostics for the full project and this should only produce buffer diagnostics
|
||||
local match = function(linter_cwd, buffer_path, line)
|
||||
local matches = { line:match(pattern) }
|
||||
local ok, matches = pcall(matchline, line)
|
||||
if not ok then
|
||||
error(string.format("pattern match failed on line: %s with error: %q", line, matches))
|
||||
end
|
||||
if not next(matches) then
|
||||
return nil
|
||||
end
|
||||
@ -112,7 +135,9 @@ function M.from_pattern(pattern, groups, severity_map, defaults, opts)
|
||||
end
|
||||
local result = {}
|
||||
local buffer_path = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":p")
|
||||
for _, line in ipairs(vim.fn.split(output, '\n')) do
|
||||
--- bwc for 0.6 requires boolean arg instead of table
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
for line in vim.gsplit(output, "\n", true) do
|
||||
local diagnostic = match(linter_cwd, buffer_path, line)
|
||||
if diagnostic then
|
||||
table.insert(result, diagnostic)
|
||||
@ -130,6 +155,11 @@ Output from linter:
|
||||
%s
|
||||
]]
|
||||
|
||||
|
||||
--- Turn a parse function into a parser table
|
||||
---
|
||||
---@param parse fun(output: string, bufnr: integer, cwd: string):vim.Diagnostic[]
|
||||
---@return lint.Parser
|
||||
function M.accumulate_chunks(parse)
|
||||
local chunks = {}
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user