mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 02:34:59 -07:00
Merge 6fb4d0050a
into 7121983c45
This commit is contained in:
commit
0cd2931f67
@ -909,8 +909,11 @@ formatexpr({opts}) *vim.lsp.formatexpr()*
|
||||
|
||||
Currently only supports a single client. This can be set via
|
||||
`setlocal formatexpr=v:lua.vim.lsp.formatexpr()` or (more typically) in
|
||||
`on_attach` via
|
||||
`vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`.
|
||||
`on_attach` via: >lua
|
||||
vim.bo[bufnr].formatexpr = function()
|
||||
return vim.lsp.formatexpr({ timeout_ms = 250 })
|
||||
end
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {opts} (`table?`) A table with the following fields:
|
||||
|
@ -1293,6 +1293,14 @@ window-scoped options. Note that this must NOT be confused with
|
||||
|local-options| and |:setlocal|. There is also |vim.go| that only accesses the
|
||||
global value of a |global-local| option, see |:setglobal|.
|
||||
|
||||
Unlike |nvim_set_option_value()|, |vim.o|, |vim.go|, |vim.bo|
|
||||
and |vim.wo| can be assigned function values.
|
||||
|
||||
Example: >lua
|
||||
vim.bo.tagfunc = vim.lsp.tagfunc
|
||||
vim.wo[1000].foldexpr = vim.treesitter.foldexpr
|
||||
<
|
||||
|
||||
|
||||
*vim.opt_local*
|
||||
*vim.opt_global*
|
||||
|
@ -134,6 +134,145 @@ local function get_options_info(name)
|
||||
return info
|
||||
end
|
||||
|
||||
local func_opts = {
|
||||
-- Options that can be set as a function
|
||||
func = {
|
||||
completefunc = true,
|
||||
findfunc = true,
|
||||
omnifunc = true,
|
||||
operatorfunc = true,
|
||||
quickfixtextfunc = true,
|
||||
tagfunc = true,
|
||||
thesaurusfunc = true,
|
||||
},
|
||||
|
||||
-- Options that can be set as an expression
|
||||
expr = {
|
||||
diffexpr = true,
|
||||
foldexpr = true,
|
||||
formatexpr = true,
|
||||
includeexpr = true,
|
||||
indentexpr = true,
|
||||
modelineexpr = true,
|
||||
patchexpr = true,
|
||||
},
|
||||
|
||||
-- Options that can be set as an expression with a prefix of '%!'
|
||||
pct_bang_expr = {
|
||||
statuscolumn = true,
|
||||
statusline = true,
|
||||
tabline = true,
|
||||
winbar = true,
|
||||
},
|
||||
|
||||
-- Options that can be set as an ex command if prefixed with ':'
|
||||
ex_cmd_expr = {
|
||||
keywordprg = true,
|
||||
},
|
||||
}
|
||||
|
||||
--- @param v integer?
|
||||
--- @return integer
|
||||
local function resolve_win(v)
|
||||
return assert((not v or v == 0) and api.nvim_get_current_win() or v)
|
||||
end
|
||||
|
||||
--- @type table<string,boolean>
|
||||
local all_func_opts = {}
|
||||
for _, v in pairs(func_opts) do
|
||||
for k in pairs(v) do
|
||||
all_func_opts[k] = true
|
||||
end
|
||||
end
|
||||
|
||||
--- @type table<string,function?>
|
||||
vim._func_opts = setmetatable({}, { __mode = 'v' })
|
||||
|
||||
--- If the option name is a function option convert it to a string
|
||||
--- format and store the function value.
|
||||
--- @param name string
|
||||
--- @param value any
|
||||
--- @param info vim.api.keyset.get_option_info
|
||||
--- @param opts vim.api.keyset.option
|
||||
local function apply_func_opt(name, value, info, opts)
|
||||
local idxs --- @type any[]
|
||||
|
||||
-- Find a table keep a references to the function value for an option.
|
||||
-- We store a strong reference to the function in vim.g/b/w so it can be correctly garbage
|
||||
-- collected when the buffer/window is closed. However because `v:lua` does not support
|
||||
-- indexing with [], we need to store a weak reference to the function in another table under a
|
||||
-- single string key.
|
||||
if info.scope == 'global' or info.global_local and opts.scope == 'global' then
|
||||
idxs = { 'g', '_func_opts' }
|
||||
elseif info.scope == 'buf' then
|
||||
idxs = { 'b', vim._resolve_bufnr(opts.buf), '_func_opts' }
|
||||
else
|
||||
assert(info.scope == 'win')
|
||||
idxs = { 'w', resolve_win(opts.win), '_func_opts' }
|
||||
if opts.scope == 'local' then
|
||||
idxs[#idxs + 1] = vim._resolve_bufnr(opts.buf)
|
||||
end
|
||||
end
|
||||
|
||||
local fvalue = type(value) == 'function' and value or nil
|
||||
|
||||
-- If we have a function value, ensure the table for the strong references exists
|
||||
if fvalue then
|
||||
local t = vim --- @type table<string,any>
|
||||
for _, k in ipairs(idxs) do
|
||||
t[k] = t[k] or {}
|
||||
t = t[k]
|
||||
end
|
||||
end
|
||||
|
||||
--- @type table<string,function?>
|
||||
local t = vim.tbl_get(vim, unpack(idxs))
|
||||
if t then
|
||||
-- Note fvalue as nil is used to GC
|
||||
t[name] = fvalue
|
||||
end
|
||||
|
||||
if not fvalue then
|
||||
return value
|
||||
end
|
||||
|
||||
local vlua_key_parts = {} --- @type string[]
|
||||
for _, k in ipairs(idxs) do
|
||||
vlua_key_parts[#vlua_key_parts + 1] = k ~= '_func_opts' and k or nil
|
||||
end
|
||||
vlua_key_parts[#vlua_key_parts + 1] = name
|
||||
|
||||
local vlua_key = table.concat(vlua_key_parts, '_')
|
||||
|
||||
vim._func_opts[vlua_key] = fvalue
|
||||
|
||||
local expr_pfx = (
|
||||
func_opts.pct_bang_expr[name] and '%!'
|
||||
or func_opts.ex_cmd_expr[name] and ':call '
|
||||
or ''
|
||||
)
|
||||
|
||||
local call_sfx = func_opts.func[name] and '' or '()'
|
||||
|
||||
return ('%sv:lua.vim._func_opts.%s%s'):format(expr_pfx, vlua_key, call_sfx)
|
||||
end
|
||||
|
||||
--- @param name string
|
||||
--- @param value any
|
||||
--- @param opts vim.api.keyset.option
|
||||
local function set_option_value(name, value, opts)
|
||||
local info = api.nvim_get_option_info2(name, {})
|
||||
|
||||
-- Resolve name if it is a short name
|
||||
name = info.name
|
||||
|
||||
if all_func_opts[name] then
|
||||
value = apply_func_opt(name, value, info, opts)
|
||||
end
|
||||
|
||||
api.nvim_set_option_value(name, value, opts)
|
||||
end
|
||||
|
||||
--- Environment variables defined in the editor session.
|
||||
--- See |expand-env| and |:let-environment| for the Vimscript behavior.
|
||||
--- Invalid or unset key returns `nil`.
|
||||
@ -158,6 +297,7 @@ vim.env = setmetatable({}, {
|
||||
end,
|
||||
})
|
||||
|
||||
--- @param bufnr? integer
|
||||
local function new_buf_opt_accessor(bufnr)
|
||||
return setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
@ -167,8 +307,10 @@ local function new_buf_opt_accessor(bufnr)
|
||||
return api.nvim_get_option_value(k, { buf = bufnr or 0 })
|
||||
end,
|
||||
|
||||
--- @param k string
|
||||
--- @param v any
|
||||
__newindex = function(_, k, v)
|
||||
return api.nvim_set_option_value(k, v, { buf = bufnr or 0 })
|
||||
return set_option_value(k, v, { buf = bufnr or 0 })
|
||||
end,
|
||||
})
|
||||
end
|
||||
@ -196,7 +338,7 @@ local function new_win_opt_accessor(winid, bufnr)
|
||||
end,
|
||||
|
||||
__newindex = function(_, k, v)
|
||||
return api.nvim_set_option_value(k, v, {
|
||||
return set_option_value(k, v, {
|
||||
scope = bufnr and 'local' or nil,
|
||||
win = winid or 0,
|
||||
})
|
||||
@ -227,6 +369,14 @@ end
|
||||
--- window-scoped options. Note that this must NOT be confused with
|
||||
--- |local-options| and |:setlocal|. There is also |vim.go| that only accesses the
|
||||
--- global value of a |global-local| option, see |:setglobal|.
|
||||
---
|
||||
--- Unlike |nvim_set_option_value()|, |vim.o|, |vim.go|, |vim.bo|
|
||||
--- and |vim.wo| can be assigned function values.
|
||||
---
|
||||
--- Example: >lua
|
||||
--- vim.bo.tagfunc = vim.lsp.tagfunc
|
||||
--- vim.wo[1000].foldexpr = vim.treesitter.foldexpr
|
||||
--- <
|
||||
--- </pre>
|
||||
|
||||
--- Get or set |options|. Like `:set`. Invalid key is an error.
|
||||
@ -245,8 +395,10 @@ vim.o = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
return api.nvim_get_option_value(k, {})
|
||||
end,
|
||||
--- @param k string
|
||||
--- @param v any
|
||||
__newindex = function(_, k, v)
|
||||
return api.nvim_set_option_value(k, v, {})
|
||||
return set_option_value(k, v, {})
|
||||
end,
|
||||
})
|
||||
|
||||
@ -268,8 +420,10 @@ vim.go = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
return api.nvim_get_option_value(k, { scope = 'global' })
|
||||
end,
|
||||
--- @param k string
|
||||
--- @param v any
|
||||
__newindex = function(_, k, v)
|
||||
return api.nvim_set_option_value(k, v, { scope = 'global' })
|
||||
return set_option_value(k, v, { scope = 'global' })
|
||||
end,
|
||||
})
|
||||
|
||||
|
@ -1309,8 +1309,13 @@ end
|
||||
---
|
||||
--- Currently only supports a single client. This can be set via
|
||||
--- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` or (more typically) in `on_attach`
|
||||
--- via `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`.
|
||||
--- via:
|
||||
---
|
||||
--- ```lua
|
||||
--- vim.bo[bufnr].formatexpr = function()
|
||||
--- return vim.lsp.formatexpr({ timeout_ms = 250 })
|
||||
--- end
|
||||
--- ```
|
||||
---@param opts? vim.lsp.formatexpr.Opts
|
||||
function lsp.formatexpr(opts)
|
||||
opts = opts or {}
|
||||
|
1251
test/functional/lua/option_spec.lua
Normal file
1251
test/functional/lua/option_spec.lua
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -86,7 +86,7 @@ function M.handler(bytecode, upvalues, ...)
|
||||
set_upvalues(f, upvalues)
|
||||
|
||||
-- Run in pcall so we can return any print messages
|
||||
local ret = { pcall(f, ...) } --- @type any[]
|
||||
local ret = { xpcall(f, debug.traceback, ...) } --- @type any[]
|
||||
|
||||
_G.print = orig_print
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user