diff options
Diffstat (limited to 'runtime/lua/vim/_editor.lua')
-rw-r--r-- | runtime/lua/vim/_editor.lua | 106 |
1 files changed, 85 insertions, 21 deletions
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 5e9be509c8..2e829578a7 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1,17 +1,19 @@ -- Nvim-Lua stdlib: the `vim` module (:help lua-stdlib) -- --- Lua code lives in one of three places: --- 1. runtime/lua/vim/ (the runtime): For "nice to have" features, e.g. the --- `inspect` and `lpeg` modules. --- 2. runtime/lua/vim/shared.lua: pure Lua functions which always --- are available. Used in the test runner, as well as worker threads --- and processes launched from Nvim. --- 3. runtime/lua/vim/_editor.lua: Code which directly interacts with --- the Nvim editor state. Only available in the main thread. +-- Lua code lives in one of four places: +-- 1. Plugins! Not everything needs to live on "vim.*". Plugins are the correct model for +-- non-essential features which the user may want to disable or replace with a third-party +-- plugin. Examples: "editorconfig", "comment". +-- - "opt-out": runtime/plugin/*.lua +-- - "opt-in": runtime/pack/dist/opt/ +-- 2. runtime/lua/vim/ (the runtime): Lazy-loaded modules. Examples: `inspect`, `lpeg`. +-- 3. runtime/lua/vim/shared.lua: pure Lua functions which always are available. Used in the test +-- runner, as well as worker threads and processes launched from Nvim. +-- 4. runtime/lua/vim/_editor.lua: Eager-loaded code which directly interacts with the Nvim +-- editor state. Only available in the main thread. -- --- Guideline: "If in doubt, put it in the runtime". --- --- Most functions should live directly in `vim.`, not in submodules. +-- The top level "vim.*" namespace is for fundamental Lua and editor features. Use submodules for +-- everything else (but avoid excessive "nesting"), or plugins (see above). -- -- Compatibility with Vim's `if_lua` is explicitly a non-goal. -- @@ -19,9 +21,7 @@ -- - https://github.com/luafun/luafun -- - https://github.com/rxi/lume -- - http://leafo.net/lapis/reference/utilities.html --- - https://github.com/torch/paths -- - https://github.com/bakpakin/Fennel (pretty print, repl) --- - https://github.com/howl-editor/howl/tree/master/lib/howl/util -- These are for loading runtime modules lazily since they aren't available in -- the nvim binary as specified in executor.c @@ -208,8 +208,10 @@ vim.inspect = vim.inspect do local tdots, tick, got_line1, undo_started, trailing_nl = 0, 0, false, false, false - --- Paste handler, invoked by |nvim_paste()| when a conforming UI - --- (such as the |TUI|) pastes text into the editor. + --- Paste handler, invoked by |nvim_paste()|. + --- + --- Note: This is provided only as a "hook", don't call it directly; call |nvim_paste()| instead, + --- which arranges redo (dot-repeat) and invokes `vim.paste`. --- --- Example: To remove ANSI color codes when pasting: --- @@ -220,7 +222,7 @@ do --- -- Scrub ANSI color codes from paste input. --- lines[i] = line:gsub('\27%[[0-9;mK]+', '') --- end - --- overridden(lines, phase) + --- return overridden(lines, phase) --- end --- end)(vim.paste) --- ``` @@ -494,6 +496,7 @@ do vim.t = make_dict_accessor('t') end +--- @deprecated --- Gets a dict of line segment ("chunk") positions for the region from `pos1` to `pos2`. --- --- Input and output positions are byte positions, (0,0)-indexed. "End of line" column @@ -507,6 +510,8 @@ end ---@return table region Dict of the form `{linenr = {startcol,endcol}}`. `endcol` is exclusive, and ---whole lines are returned as `{startcol,endcol} = {0,-1}`. function vim.region(bufnr, pos1, pos2, regtype, inclusive) + vim.deprecate('vim.region', 'vim.fn.getregionpos()', '0.13') + if not vim.api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end @@ -605,10 +610,9 @@ end --- Displays a notification to the user. --- ---- This function can be overridden by plugins to display notifications using a ---- custom provider (such as the system notification provider). By default, +--- This function can be overridden by plugins to display notifications using +--- a custom provider (such as the system notification provider). By default, --- writes to |:messages|. ---- ---@param msg string Content of the notification to show to the user. ---@param level integer|nil One of the values from |vim.log.levels|. ---@param opts table|nil Optional parameters. Unused by default. @@ -783,7 +787,7 @@ function vim._expand_pat(pat, env) if mt and type(mt.__index) == 'table' then field = rawget(mt.__index, key) elseif final_env == vim and (vim._submodules[key] or vim._extra[key]) then - field = vim[key] + field = vim[key] --- @type any end end final_env = field @@ -794,14 +798,24 @@ function vim._expand_pat(pat, env) end local keys = {} --- @type table<string,true> + --- @param obj table<any,any> local function insert_keys(obj) for k, _ in pairs(obj) do - if type(k) == 'string' and string.sub(k, 1, string.len(match_part)) == match_part then + if + type(k) == 'string' + and string.sub(k, 1, string.len(match_part)) == match_part + and k:match('^[_%w]+$') ~= nil -- filter out invalid identifiers for field, e.g. 'foo#bar' + then keys[k] = true end end end + ---@param acc table<string,any> + local function _fold_to_map(acc, k, v) + acc[k] = (v or true) + return acc + end if type(final_env) == 'table' then insert_keys(final_env) @@ -810,11 +824,61 @@ function vim._expand_pat(pat, env) if mt and type(mt.__index) == 'table' then insert_keys(mt.__index) end + if final_env == vim then insert_keys(vim._submodules) insert_keys(vim._extra) end + -- Completion for dict accessors (special vim variables and vim.fn) + if mt and vim.tbl_contains({ vim.g, vim.t, vim.w, vim.b, vim.v, vim.fn }, final_env) then + local prefix, type = unpack( + vim.fn == final_env and { '', 'function' } + or vim.g == final_env and { 'g:', 'var' } + or vim.t == final_env and { 't:', 'var' } + or vim.w == final_env and { 'w:', 'var' } + or vim.b == final_env and { 'b:', 'var' } + or vim.v == final_env and { 'v:', 'var' } + or { nil, nil } + ) + assert(prefix, "Can't resolve final_env") + local vars = vim.fn.getcompletion(prefix .. match_part, type) --- @type string[] + insert_keys(vim + .iter(vars) + :map(function(s) ---@param s string + s = s:gsub('[()]+$', '') -- strip '(' and ')' for function completions + return s:sub(#prefix + 1) -- strip the prefix, e.g., 'g:foo' => 'foo' + end) + :fold({}, _fold_to_map)) + end + + -- Completion for option accessors (full names only) + if + mt + and vim.tbl_contains( + { vim.o, vim.go, vim.bo, vim.wo, vim.opt, vim.opt_local, vim.opt_global }, + final_env + ) + then + --- @type fun(option_name: string, option: vim.api.keyset.get_option_info): boolean + local filter = function(_, _) + return true + end + if vim.bo == final_env then + filter = function(_, option) + return option.scope == 'buf' + end + elseif vim.wo == final_env then + filter = function(_, option) + return option.scope == 'win' + end + end + + --- @type table<string, vim.api.keyset.get_option_info> + local options = vim.api.nvim_get_all_options_info() + insert_keys(vim.iter(options):filter(filter):fold({}, _fold_to_map)) + end + keys = vim.tbl_keys(keys) table.sort(keys) |