mirror of
https://github.com/dense-analysis/ale.git
synced 2025-12-28 14:56:52 +08:00
Add basic Lua ALE functions and test coverage
Ensure that basic ALE functions `ale.var`, `ale.escape`, and `ale.env` are available in Lua. Cover all Lua code so far with busted tests, fixing bugs where ALE variables can be set with Boolean values instead of numbers. Document all functionality so far.
This commit is contained in:
@@ -1,96 +1,95 @@
|
||||
local ale = require("ale")
|
||||
|
||||
local module = {}
|
||||
|
||||
local ale_type_to_diagnostic_severity = {
|
||||
E = vim.diagnostic.severity.ERROR,
|
||||
W = vim.diagnostic.severity.WARN,
|
||||
I = vim.diagnostic.severity.INFO
|
||||
local diagnostic_severity_map = {
|
||||
E = vim.diagnostic.severity.ERROR,
|
||||
W = vim.diagnostic.severity.WARN,
|
||||
I = vim.diagnostic.severity.INFO
|
||||
}
|
||||
|
||||
-- Equivalent to ale#Var, only we can't error on missing global keys.
|
||||
module.aleVar = function(buffer, key)
|
||||
key = "ale_" .. key
|
||||
local exists, value = pcall(vim.api.nvim_buf_get_var, buffer, key)
|
||||
|
||||
if exists then
|
||||
return value
|
||||
end
|
||||
|
||||
return vim.g[key]
|
||||
end
|
||||
|
||||
module.sendAleResultsToDiagnostics = function(buffer, loclist)
|
||||
local diagnostics = {}
|
||||
|
||||
-- Convert all the ALE loclist items to the shape that Neovim's diagnostic
|
||||
-- API is expecting.
|
||||
for _, location in ipairs(loclist) do
|
||||
if location.bufnr == buffer then
|
||||
table.insert(
|
||||
diagnostics,
|
||||
-- All line numbers from ALE are 1-indexed, but all line numbers
|
||||
-- in the diagnostics API are 0-indexed, so we have to subtract 1
|
||||
-- to make this work.
|
||||
{
|
||||
lnum = location.lnum - 1,
|
||||
-- Ending line number, or if we don't have one, just make it the same
|
||||
-- as the starting line number
|
||||
end_lnum = (location.end_lnum or location.lnum) - 1,
|
||||
-- Which column does the error start on?
|
||||
col = math.max((location.col or 1) - 1, 0),
|
||||
-- end_col does *not* appear to need 1 subtracted, so we don't.
|
||||
end_col = location.end_col,
|
||||
-- Which severity: error, warning, or info?
|
||||
severity = ale_type_to_diagnostic_severity[location.type] or "E",
|
||||
-- An error code
|
||||
code = location.code,
|
||||
-- The error message
|
||||
message = location.text,
|
||||
-- e.g. "rubocop"
|
||||
source = location.linter_name,
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local virtualtext_enabled_set = {
|
||||
['all'] = true,
|
||||
['2'] = true,
|
||||
-- A map of all possible values that we can consider virtualtext enabled for
|
||||
-- from ALE's setting.
|
||||
local virtualtext_enabled_set = {
|
||||
["all"] = true,
|
||||
["2"] = true,
|
||||
[2] = true,
|
||||
['current'] = true,
|
||||
['1'] = true,
|
||||
["current"] = true,
|
||||
["1"] = true,
|
||||
[1] = true,
|
||||
}
|
||||
[true] = true,
|
||||
}
|
||||
|
||||
local set_signs = module.aleVar(buffer, 'set_signs')
|
||||
local sign_priority = module.aleVar(buffer, 'sign_priority')
|
||||
local signs
|
||||
---Send diagnostics to the Neovim diagnostics API
|
||||
---@param buffer number The buffer number to retreive the variable for.
|
||||
---@param loclist table The loclist array to report as diagnostics.
|
||||
---@return nil
|
||||
module.send = function(buffer, loclist)
|
||||
local diagnostics = {}
|
||||
|
||||
if set_signs == 1 and sign_priority then
|
||||
-- If signs are enabled, set the priority for them.
|
||||
local local_cfg = { priority = sign_priority }
|
||||
local global_cfg = vim.diagnostic.config().signs
|
||||
|
||||
if type(global_cfg) == 'boolean' then
|
||||
signs = local_cfg
|
||||
elseif type(global_cfg) == 'table' then
|
||||
signs = vim.tbl_extend('force', global_cfg, local_cfg)
|
||||
else
|
||||
signs = function(...)
|
||||
local calculated = global_cfg(...)
|
||||
return vim.tbl_extend('force', calculated, local_cfg)
|
||||
end
|
||||
-- Convert all the ALE loclist items to the shape that Neovim's diagnostic
|
||||
-- API is expecting.
|
||||
for _, location in ipairs(loclist) do
|
||||
if location.bufnr == buffer then
|
||||
table.insert(
|
||||
diagnostics,
|
||||
-- All line numbers from ALE are 1-indexed, but all line
|
||||
-- numbers in the diagnostics API are 0-indexed, so we have to
|
||||
-- subtract 1 to make this work.
|
||||
{
|
||||
lnum = location.lnum - 1,
|
||||
-- Ending line number, or if we don't have one, just make
|
||||
-- it the same as the starting line number
|
||||
end_lnum = (location.end_lnum or location.lnum) - 1,
|
||||
-- Which column does the error start on?
|
||||
col = math.max((location.col or 1) - 1, 0),
|
||||
-- end_col does not appear to need 1 subtracted.
|
||||
end_col = location.end_col,
|
||||
-- Which severity: error, warning, or info?
|
||||
severity = diagnostic_severity_map[location.type] or "E",
|
||||
-- An error code
|
||||
code = location.code,
|
||||
-- The error message
|
||||
message = location.text,
|
||||
-- e.g. "rubocop"
|
||||
source = location.linter_name,
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vim.diagnostic.set(
|
||||
vim.api.nvim_create_namespace('ale'),
|
||||
buffer,
|
||||
diagnostics,
|
||||
{
|
||||
virtual_text = virtualtext_enabled_set[vim.g.ale_virtualtext_cursor] ~= nil,
|
||||
signs = signs,
|
||||
}
|
||||
)
|
||||
local set_signs = ale.var(buffer, "set_signs")
|
||||
local sign_priority = ale.var(buffer, "sign_priority")
|
||||
local signs
|
||||
|
||||
if (set_signs == 1 or set_signs == true) and sign_priority then
|
||||
-- If signs are enabled, set the priority for them.
|
||||
local local_cfg = { priority = sign_priority }
|
||||
local global_cfg = vim.diagnostic.config().signs
|
||||
|
||||
if type(global_cfg) == "boolean" then
|
||||
signs = local_cfg
|
||||
elseif type(global_cfg) == "table" then
|
||||
signs = vim.tbl_extend("force", global_cfg, local_cfg)
|
||||
else
|
||||
-- If a global function is defined, then define a function
|
||||
-- that calls that function when Neovim calls our function.
|
||||
signs = function(...)
|
||||
return vim.tbl_extend("force", global_cfg(...), local_cfg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vim.diagnostic.set(
|
||||
vim.api.nvim_create_namespace("ale"),
|
||||
buffer,
|
||||
diagnostics,
|
||||
{
|
||||
virtual_text =
|
||||
virtualtext_enabled_set[vim.g.ale_virtualtext_cursor] ~= nil,
|
||||
signs = signs,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
return module
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
local ale = {}
|
||||
|
||||
local global_settings = setmetatable({}, {
|
||||
__index = function (_, key)
|
||||
__index = function(_, key)
|
||||
return vim.g['ale_' .. key]
|
||||
end,
|
||||
__newindex = function (_, key, value)
|
||||
__newindex = function(_, key, value)
|
||||
vim.g['ale_' .. key] = value
|
||||
end
|
||||
})
|
||||
|
||||
local buffer_settings = setmetatable({}, {
|
||||
__index = function (_, key)
|
||||
__index = function(_, key)
|
||||
return vim.b['ale_' .. key]
|
||||
end,
|
||||
__newindex = function (_, key, value)
|
||||
__newindex = function(_, key, value)
|
||||
vim.b['ale_' .. key] = value
|
||||
end
|
||||
})
|
||||
@@ -30,17 +30,79 @@ ale.set_buffer = function(c)
|
||||
end
|
||||
end
|
||||
|
||||
---(when called) Set global ALE settings, just like ale.setup.global.
|
||||
---@class ALESetup
|
||||
---@field global fun(c: table): nil -- Set global ALE settings.
|
||||
---@field buffer fun(c: table): nil -- Set buffer-local ALE settings.
|
||||
---@overload fun(c: table): nil
|
||||
---@type ALESetup
|
||||
ale.setup = setmetatable({
|
||||
global = function(c)
|
||||
ale.set_global(c)
|
||||
end,
|
||||
buffer = function(c)
|
||||
ale.set_buffer(c)
|
||||
end,
|
||||
---Set global ALE settings.
|
||||
---@param c table The table of ALE settings to set.
|
||||
---@return nil
|
||||
global = function(c)
|
||||
ale.set_global(c)
|
||||
end,
|
||||
---Set buffer-local ALE settings.
|
||||
---@param c table The table of ALE settings to set.
|
||||
---@return nil
|
||||
buffer = function(c)
|
||||
ale.set_buffer(c)
|
||||
end,
|
||||
}, {
|
||||
__call = function(self, c)
|
||||
self.global(c)
|
||||
end,
|
||||
__call = function(self, c)
|
||||
self.global(c)
|
||||
end,
|
||||
})
|
||||
|
||||
---Get an ALE variable for a buffer (first) or globally (second)
|
||||
---@param buffer number The buffer number to retreive the variable for.
|
||||
---@param variable_name string The variable to retrieve.
|
||||
---@return any value The value for the ALE variable
|
||||
ale.var = function(buffer, variable_name)
|
||||
variable_name = "ale_" .. variable_name
|
||||
local exists, value = pcall(vim.api.nvim_buf_get_var, buffer, variable_name)
|
||||
|
||||
if exists then
|
||||
return value
|
||||
end
|
||||
|
||||
return vim.g[variable_name]
|
||||
end
|
||||
|
||||
---Escape a string for use in a shell command
|
||||
---@param str string The string to escape.
|
||||
---@return string escaped The escaped string.
|
||||
ale.escape = function(str)
|
||||
local shell = vim.fn.fnamemodify(vim.o.shell, ":t")
|
||||
|
||||
if shell:lower() == "cmd.exe" then
|
||||
local step1
|
||||
|
||||
if str:find(" ") then
|
||||
step1 = '"' .. str:gsub('"', '""') .. '"'
|
||||
else
|
||||
step1 = str:gsub("([&|<>^])", "^%1")
|
||||
end
|
||||
|
||||
local percent_subbed = step1:gsub("%%", "%%%%")
|
||||
|
||||
return percent_subbed
|
||||
end
|
||||
|
||||
return vim.fn.shellescape(str)
|
||||
end
|
||||
|
||||
---Create a prefix for a shell command for adding environment variables.
|
||||
---@param variable_name string The environment variable name.
|
||||
---@param value string The value to set for the environment variable.
|
||||
---@return string prefix The shell code for prefixing a command.
|
||||
ale.env = function(variable_name, value)
|
||||
if vim.fn.has("win32") then
|
||||
return "set " .. ale.escape(variable_name .. "=" .. value) .. " && "
|
||||
end
|
||||
|
||||
return variable_name .. "=" .. ale.escape(value) .. " "
|
||||
end
|
||||
|
||||
return ale
|
||||
|
||||
@@ -2,7 +2,9 @@ local module = {}
|
||||
|
||||
module.start = function(config)
|
||||
-- Neovim's luaeval sometimes adds a Boolean key to table we need to remove.
|
||||
if config.init_options[true] ~= nil then
|
||||
if type(config.init_options) == "table"
|
||||
and config.init_options[true] ~= nil
|
||||
then
|
||||
config.init_options[true] = nil
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user