lua/stdlib: Introduce vim.shared

This is where "pure functions" can live, which can be shared by Nvim and
test logic which may not have a running Nvim instance available.

If in the future we use Nvim itself as the Lua engine for tests, then
these functions could be moved directly onto the `vim` Lua module.

closes #6580
This commit is contained in:
Justin M. Keyes 2019-01-18 00:44:35 +01:00
parent 2b87485c22
commit bba75eb184
5 changed files with 88 additions and 36 deletions

View File

@ -0,0 +1,39 @@
--- Shared functions
-- - Used by Nvim and tests
-- - Can run in vanilla Lua (do not require a running instance of Nvim)
--- Merge map-like tables.
--
--@see |extend()|
--
-- behavior: Decides what to do if a key is found in more than one map:
-- "error": raise an error
-- "keep": skip
-- "force": set the item again
local function tbl_extend(behavior, ...)
if (behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force') then
error('invalid "behavior": '..tostring(behavior))
end
local ret = {}
for i = 1, select('#', ...) do
local tbl = select(i, ...)
if tbl then
for k, v in pairs(tbl) do
if behavior ~= 'force' and ret[k] ~= nil then
if behavior == 'error' then
error('key found in more than one map: '..k)
end -- Else behavior is "keep".
else
ret[k] = v
end
end
end
end
return ret
end
local module = {
tbl_extend = tbl_extend,
}
return module

View File

@ -1,3 +1,39 @@
-- Nvim-Lua stdlib: the `vim` module (:help lua-stdlib)
--
-- Lua code lives in one of three places:
-- 1. The runtime (`runtime/lua/vim/`). For "nice to have" features, e.g.
-- the `inspect` and `lpeg` modules.
-- 2. The `vim.shared` module: code shared between Nvim and its test-suite.
-- 3. Compiled-into Nvim itself (`src/nvim/lua/`).
--
-- Guideline: "If in doubt, put it in the runtime".
--
-- Most functions should live directly on `vim.`, not sub-modules. The only
-- "forbidden" names are those claimed by legacy `if_lua`:
-- $ vim
-- :lua for k,v in pairs(vim) do print(k) end
-- buffer
-- open
-- window
-- lastline
-- firstline
-- type
-- line
-- eval
-- dict
-- beep
-- list
-- command
--
-- Reference (#6580):
-- - 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
-- Internal-only until comments in #8107 are addressed. -- Internal-only until comments in #8107 are addressed.
-- Returns: -- Returns:
-- {errcode}, {output} -- {errcode}, {output}
@ -187,10 +223,14 @@ deepcopy = function(orig)
return deepcopy_funcs[type(orig)](orig) return deepcopy_funcs[type(orig)](orig)
end end
local function __index(table, key) local function __index(t, key)
if key == "inspect" then if key == 'inspect' then
table.inspect = require("vim.inspect") t.inspect = require('vim.inspect')
return table.inspect return t.inspect
elseif require('vim.shared')[key] ~= nil then
-- Expose all `vim.shared` functions on the `vim` module.
t[key] = require('vim.shared')[key]
return t[key]
end end
end end

View File

@ -846,7 +846,7 @@ local module = {
window = window, window = window,
winmeths = winmeths, winmeths = winmeths,
} }
module = global_helpers.map_extend('error', module, global_helpers) module = global_helpers.tbl_extend('error', module, global_helpers)
return function(after_each) return function(after_each)
if after_each then if after_each then

View File

@ -1,4 +1,5 @@
require('vim.compat') require('vim.compat')
local shared = require('vim.shared')
local assert = require('luassert') local assert = require('luassert')
local luv = require('luv') local luv = require('luv')
local lfs = require('lfs') local lfs = require('lfs')
@ -435,34 +436,6 @@ local function concat_tables(...)
return ret return ret
end end
-- Concat map-like tables.
--
-- behavior: Decides what to do if a key is found in more than one map:
-- "error": raise an error
-- "keep": skip
-- "force": set the item again
local function map_extend(behavior, ...)
if (behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force') then
error('invalid "behavior": '..tostring(behavior))
end
local ret = {}
for i = 1, select('#', ...) do
local tbl = select(i, ...)
if tbl then
for k, v in pairs(tbl) do
if behavior ~= 'force' and ret[k] ~= nil then
if behavior == 'error' then
error('key found in more than one map: '..k)
end -- Else behavior is "keep".
else
ret[k] = v
end
end
end
end
return ret
end
local function dedent(str, leave_indent) local function dedent(str, leave_indent)
-- find minimum common indent across lines -- find minimum common indent across lines
local indent = nil local indent = nil
@ -801,7 +774,6 @@ local module = {
intchar2lua = intchar2lua, intchar2lua = intchar2lua,
isCI = isCI, isCI = isCI,
map = map, map = map,
map_extend = map_extend,
matches = matches, matches = matches,
mergedicts_copy = mergedicts_copy, mergedicts_copy = mergedicts_copy,
near = near, near = near,
@ -816,6 +788,7 @@ local module = {
shallowcopy = shallowcopy, shallowcopy = shallowcopy,
sleep = sleep, sleep = sleep,
table_contains = table_contains, table_contains = table_contains,
tbl_extend = shared.tbl_extend,
table_flatten = table_flatten, table_flatten = table_flatten,
tmpname = tmpname, tmpname = tmpname,
uname = uname, uname = uname,
@ -823,6 +796,6 @@ local module = {
which = which, which = which,
write_file = write_file, write_file = write_file,
} }
module = map_extend('error', module, Paths) module = shared.tbl_extend('error', module, Paths)
return module return module

View File

@ -865,7 +865,7 @@ local module = {
ptr2key = ptr2key, ptr2key = ptr2key,
debug_log = debug_log, debug_log = debug_log,
} }
module = global_helpers.map_extend('error', module, global_helpers) module = global_helpers.tbl_extend('error', module, global_helpers)
return function() return function()
return module return module
end end