diff --git a/doc/BUILTINS.md b/doc/BUILTINS.md index 6dac294ae..c6e80fffa 100644 --- a/doc/BUILTINS.md +++ b/doc/BUILTINS.md @@ -2097,6 +2097,24 @@ local sources = { null_ls.builtins.diagnostics.stylint } - Command: `stylint` - Args: `{ "$FILENAME" }` +### [swipl](https://www.swi-prolog.org/) + +SWI-Prolog is a versatile implementation of the Prolog language. + +#### Usage + +```lua +local sources = { null_ls.builtins.diagnostics.swipl } +``` + +#### Defaults + +- Filetypes: `{ "prolog" }` +- Method: `diagnostics` +- Command: `swipl` +- Args: `{ "-q", "-t", "halt(1)", "-s", "$FILENAME" }` + + ### [swiftlint](https://github.com/realm/SwiftLint) A tool to enforce Swift style and conventions. diff --git a/doc/MAIN.md b/doc/MAIN.md index 1343152a7..2df4c4d13 100644 --- a/doc/MAIN.md +++ b/doc/MAIN.md @@ -219,8 +219,8 @@ handle common conditional checks. - `utils.root_matches`: accepts a Lua string matcher pattern. Returns `true` if the root matches the specified pattern. -- `utils.root_has_file_matches`: accepts a Lua string matcher pattern. Returns `true` if - a file matches the specified pattern. +- `utils.root_has_file_matches`: accepts a Lua string matcher pattern. Returns + `true` if a file matches the specified pattern. On registration, null-ls will store conditional sources in state and check `condition` at the first opportunity (typically upon entering a named buffer). diff --git a/lua/null-ls/builtins/diagnostics/swipl.lua b/lua/null-ls/builtins/diagnostics/swipl.lua new file mode 100644 index 000000000..32ed99e35 --- /dev/null +++ b/lua/null-ls/builtins/diagnostics/swipl.lua @@ -0,0 +1,82 @@ +local h = require("null-ls.helpers") +local methods = require("null-ls.methods") +local DIAGNOSTICS_ON_SAVE = methods.internal.DIAGNOSTICS_ON_SAVE + +return h.make_builtin({ + method = DIAGNOSTICS_ON_SAVE, + filetypes = { "prolog" }, + generator_opts = { + command = "swipl", + args = { "-q", "-t", "halt(1)", "-s", "$FILENAME" }, + format = "raw", + check_exit_code = function(code) + return code <= 1 + end, + on_output = function(params, done) + local diagnostics = {} + local lines = vim.fn.split(params.err, "\r\n\\|\r\\|\n") + local err = false + local warning = false + local row = 0 + local col = 0 + local msg = "" + local i = 1 + if lines[1]:match("v:null") then + done(diagnostics) + return + end + while i <= #lines do + local line = lines[i] + if err then + local _, _, m = line:find("^ERROR: (.*)") + if m then + msg = msg .. m + i = i + 1 + else + err = false + table.insert(diagnostics, { + row = row, + col = col, + source = "swipl", + message = msg, + severity = 1, + }) + end + elseif warning then + local _, _, m = line:find("^Warning: (.*)") + if m then + msg = msg .. m + i = i + 1 + else + warning = false + table.insert(diagnostics, { + row = row, + col = col, + source = "swipl", + message = msg, + severity = 2, + }) + end + else + local _ + i = i + 1 + _, _, row, msg = line:find("^Warning:.-:(%d+):%s*(.*)") + warning = msg ~= nil + _, _, row, msg = line:find("^ERROR:.-:(%d+):%s*(.*)") + err = msg ~= nil + end + end + if err or warning then + table.insert(diagnostics, { + row = row, + col = col, + source = "swipl", + message = msg, + severity = err and 1 or 2, + }) + end + done(diagnostics) + end, + }, + factory = h.generator_factory, +})