aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r--runtime/lua/vim/_meta.lua147
-rw-r--r--runtime/lua/vim/lsp/buf.lua2
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua6
-rw-r--r--runtime/lua/vim/lsp/handlers.lua4
-rw-r--r--runtime/lua/vim/lsp/rpc.lua13
-rw-r--r--runtime/lua/vim/lsp/util.lua21
6 files changed, 157 insertions, 36 deletions
diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua
index 02d1154df4..b1f935541c 100644
--- a/runtime/lua/vim/_meta.lua
+++ b/runtime/lua/vim/_meta.lua
@@ -209,12 +209,17 @@ local function get_scoped_option(k, set_type)
end
if is_window_option(info) then
- if vim.api.nvim_get_option_info(k).was_set then
- local was_set, value = pcall(a.nvim_win_get_option, 0, k)
- if was_set then return value end
+ local ok, value = pcall(a.nvim_win_get_option, 0, k)
+ if ok then
+ return value
end
- return a.nvim_get_option(k)
+ local global_ok, global_val = pcall(a.nvim_get_option, k)
+ if global_ok then
+ return global_val
+ end
+
+ error("win_get: This should never happen. File an issue and tag @tjdevries")
end
error("This fallback case should not be possible. " .. k)
@@ -262,7 +267,7 @@ local key_value_options = {
winhl = true,
}
----@class OptionType
+---@class OptionTypes
--- Option Type Enum
local OptionTypes = setmetatable({
BOOLEAN = 0,
@@ -306,6 +311,28 @@ local get_option_type = function(name, info)
end
+-- Check whether the OptionTypes is allowed for vim.opt
+-- If it does not match, throw an error which indicates which option causes the error.
+local function assert_valid_value(name, value, types)
+ local type_of_value = type(value)
+ for _, valid_type in ipairs(types) do
+ if valid_type == type_of_value then
+ return
+ end
+ end
+
+ error(string.format("Invalid option type '%s' for '%s', should be %s", type_of_value, name, table.concat(types, " or ")))
+end
+
+local valid_types = {
+ [OptionTypes.BOOLEAN] = { "boolean" },
+ [OptionTypes.NUMBER] = { "number" },
+ [OptionTypes.STRING] = { "string" },
+ [OptionTypes.SET] = { "string", "table" },
+ [OptionTypes.ARRAY] = { "string", "table" },
+ [OptionTypes.MAP] = { "string", "table" },
+}
+
--- Convert a lua value to a vimoption_T value
local convert_value_to_vim = (function()
-- Map of functions to take a Lua style value and convert to vimoption_T style value.
@@ -315,24 +342,41 @@ local convert_value_to_vim = (function()
[OptionTypes.NUMBER] = function(_, value) return value end,
[OptionTypes.STRING] = function(_, value) return value end,
- [OptionTypes.SET] = function(_, value)
+ [OptionTypes.SET] = function(info, value)
if type(value) == "string" then return value end
- local result = ''
- for k in pairs(value) do
- result = result .. k
- end
- return result
+ if info.flaglist and info.commalist then
+ local keys = {}
+ for k, v in pairs(value) do
+ if v then
+ table.insert(keys, k)
+ end
+ end
+
+ table.sort(keys)
+ return table.concat(keys, ",")
+ else
+ local result = ''
+ for k, v in pairs(value) do
+ if v then
+ result = result .. k
+ end
+ end
+
+ return result
+ end
end,
- [OptionTypes.ARRAY] = function(_, value)
+ [OptionTypes.ARRAY] = function(info, value)
if type(value) == "string" then return value end
- return table.concat(remove_duplicate_values(value), ",")
+ if not info.allows_duplicates then
+ value = remove_duplicate_values(value)
+ end
+ return table.concat(value, ",")
end,
[OptionTypes.MAP] = function(_, value)
if type(value) == "string" then return value end
- if type(value) == "function" then error(debug.traceback("asdf")) end
local result = {}
for opt_key, opt_value in pairs(value) do
@@ -345,7 +389,10 @@ local convert_value_to_vim = (function()
}
return function(name, info, value)
- return to_vim_value[get_option_type(name, info)](info, value)
+ local option_type = get_option_type(name, info)
+ assert_valid_value(name, value, valid_types[option_type])
+
+ return to_vim_value[option_type](info, value)
end
end)()
@@ -358,26 +405,82 @@ local convert_value_to_lua = (function()
[OptionTypes.NUMBER] = function(_, value) return value end,
[OptionTypes.STRING] = function(_, value) return value end,
- [OptionTypes.ARRAY] = function(_, value)
+ [OptionTypes.ARRAY] = function(info, value)
if type(value) == "table" then
- value = remove_duplicate_values(value)
+ if not info.allows_duplicates then
+ value = remove_duplicate_values(value)
+ end
+
return value
end
+ -- Empty strings mean that there is nothing there,
+ -- so empty table should be returned.
+ if value == '' then
+ return {}
+ end
+
+ -- Handles unescaped commas in a list.
+ if string.find(value, ",,,") then
+ local comma_split = vim.split(value, ",,,")
+ local left = comma_split[1]
+ local right = comma_split[2]
+
+ local result = {}
+ vim.list_extend(result, vim.split(left, ","))
+ table.insert(result, ",")
+ vim.list_extend(result, vim.split(right, ","))
+
+ table.sort(result)
+
+ return result
+ end
+
+ if string.find(value, ",^,,", 1, true) then
+ local comma_split = vim.split(value, ",^,,", true)
+ local left = comma_split[1]
+ local right = comma_split[2]
+
+ local result = {}
+ vim.list_extend(result, vim.split(left, ","))
+ table.insert(result, "^,")
+ vim.list_extend(result, vim.split(right, ","))
+
+ table.sort(result)
+
+ return result
+ end
+
return vim.split(value, ",")
end,
[OptionTypes.SET] = function(info, value)
if type(value) == "table" then return value end
+ -- Empty strings mean that there is nothing there,
+ -- so empty table should be returned.
+ if value == '' then
+ return {}
+ end
+
assert(info.flaglist, "That is the only one I know how to handle")
- local result = {}
- for i = 1, #value do
- result[value:sub(i, i)] = true
- end
+ if info.flaglist and info.commalist then
+ local split_value = vim.split(value, ",")
+ local result = {}
+ for _, v in ipairs(split_value) do
+ result[v] = true
+ end
- return result
+ return result
+ else
+ local result = {}
+ for i = 1, #value do
+ result[value:sub(i, i)] = true
+ end
+
+ return result
+ end
end,
[OptionTypes.MAP] = function(info, raw_value)
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index ad5a348d4c..b13d662ccb 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -339,7 +339,7 @@ end
--- Add the folder at path to the workspace folders. If {path} is
--- not provided, the user will be prompted for a path using |input()|.
function M.add_workspace_folder(workspace_folder)
- workspace_folder = workspace_folder or npcall(vfn.input, "Workspace Folder: ", vfn.expand('%:p:h'))
+ workspace_folder = workspace_folder or npcall(vfn.input, "Workspace Folder: ", vfn.expand('%:p:h'), 'dir')
vim.api.nvim_command("redraw")
if not (workspace_folder and #workspace_folder > 0) then return end
if vim.fn.isdirectory(workspace_folder) == 0 then
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index e4acfd0711..64dde78f17 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -1214,9 +1214,9 @@ function M.set_loclist(opts)
if severity then
return d.severity == severity
end
- severity = to_severity(opts.severity_limit)
- if severity then
- return d.severity == severity
+ local severity_limit = to_severity(opts.severity_limit)
+ if severity_limit then
+ return d.severity <= severity_limit
end
return true
end
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index 5d38150fc0..41852b9d88 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -196,7 +196,6 @@ M['textDocument/references'] = function(_, _, result)
if not result then return end
util.set_qflist(util.locations_to_items(result))
api.nvim_command("copen")
- api.nvim_command("wincmd p")
end
--@private
@@ -211,7 +210,6 @@ local symbol_handler = function(_, _, result, _, bufnr)
util.set_qflist(util.symbols_to_items(result, bufnr))
api.nvim_command("copen")
- api.nvim_command("wincmd p")
end
--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
M['textDocument/documentSymbol'] = symbol_handler
@@ -302,7 +300,6 @@ local function location_handler(_, method, result)
if #result > 1 then
util.set_qflist(util.locations_to_items(result))
api.nvim_command("copen")
- api.nvim_command("wincmd p")
end
else
util.jump_to_location(result)
@@ -383,7 +380,6 @@ local make_call_hierarchy_handler = function(direction)
end
util.set_qflist(items)
api.nvim_command("copen")
- api.nvim_command("wincmd p")
end
end
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 98835d6708..4c5f02af9d 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -50,8 +50,13 @@ recursive_convert_NIL = function(v, tbl_processed)
return nil
elseif not tbl_processed[v] and type(v) == 'table' then
tbl_processed[v] = true
+ local inside_list = vim.tbl_islist(v)
return vim.tbl_map(function(x)
- return recursive_convert_NIL(x, tbl_processed)
+ if not inside_list or (inside_list and type(x) == "table") then
+ return recursive_convert_NIL(x, tbl_processed)
+ else
+ return x
+ end
end, v)
end
@@ -444,7 +449,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
method = method;
params = params;
}
- if result then
+ if result and message_callbacks then
message_callbacks[message_id] = schedule_wrap(callback)
return result, message_id
else
@@ -543,14 +548,14 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
-- - The server will not send a result callback after this cancellation.
-- - If the server sent this cancellation ACK after sending the result, the user of this RPC
-- client will ignore the result themselves.
- if result_id then
+ if result_id and message_callbacks then
message_callbacks[result_id] = nil
end
return
end
end
- local callback = message_callbacks[result_id]
+ local callback = message_callbacks and message_callbacks[result_id]
if callback then
message_callbacks[result_id] = nil
validate {
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 7c0132822e..195e3a0e65 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -1056,6 +1056,21 @@ function M._trim(contents, opts)
return contents
end
+-- Generates a table mapping markdown code block lang to vim syntax,
+-- based on g:markdown_fenced_languages
+-- @return a table of lang -> syntax mappings
+-- @private
+local function get_markdown_fences()
+ local fences = {}
+ for _, fence in pairs(vim.g.markdown_fenced_languages or {}) do
+ local lang, syntax = fence:match("^(.*)=(.*)$")
+ if lang then
+ fences[lang] = syntax
+ end
+ end
+ return fences
+end
+
--- Converts markdown into syntax highlighted regions by stripping the code
--- blocks and converting them into highlighted code.
--- This will by default insert a blank line separator after those code block
@@ -1138,7 +1153,7 @@ function M.stylize_markdown(bufnr, contents, opts)
table.insert(highlights, {
ft = match.ft;
start = start + 1;
- finish = #stripped + 1 - 1;
+ finish = #stripped;
})
else
table.insert(stripped, line)
@@ -1187,11 +1202,13 @@ function M.stylize_markdown(bufnr, contents, opts)
-- keep track of syntaxes we already inlcuded.
-- no need to include the same syntax more than once
local langs = {}
+ local fences = get_markdown_fences()
local function apply_syntax_to_region(ft, start, finish)
if ft == "" then
vim.cmd(string.format("syntax region markdownCode start=+\\%%%dl+ end=+\\%%%dl+ keepend extend", start, finish + 1))
return
end
+ ft = fences[ft] or ft
local name = ft..idx
idx = idx + 1
local lang = "@"..ft:upper()
@@ -1220,7 +1237,7 @@ function M.stylize_markdown(bufnr, contents, opts)
apply_syntax_to_region(h.ft, h.start, h.finish)
last = h.finish + 1
end
- if last < #stripped then
+ if last <= #stripped then
apply_syntax_to_region("lsp_markdown", last, #stripped)
end
end)