mirror of
https://github.com/neovim/neovim.git
synced 2025-10-26 12:27:24 +00:00
Merge branch 'master' into s-dash-stdin
This commit is contained in:
320
test/helpers.lua
320
test/helpers.lua
@@ -39,15 +39,28 @@ local check_logs_useless_lines = {
|
||||
['See README_MISSING_SYSCALL_OR_IOCTL for guidance']=3,
|
||||
}
|
||||
|
||||
local eq = function(exp, act)
|
||||
return assert.are.same(exp, act)
|
||||
local function eq(expected, actual)
|
||||
return assert.are.same(expected, actual)
|
||||
end
|
||||
local neq = function(exp, act)
|
||||
return assert.are_not.same(exp, act)
|
||||
local function neq(expected, actual)
|
||||
return assert.are_not.same(expected, actual)
|
||||
end
|
||||
local ok = function(res)
|
||||
local function ok(res)
|
||||
return assert.is_true(res)
|
||||
end
|
||||
local function matches(pat, actual)
|
||||
if nil ~= string.match(actual, pat) then
|
||||
return true
|
||||
end
|
||||
error(string.format('Pattern does not match.\nPattern:\n%s\nActual:\n%s', pat, actual))
|
||||
end
|
||||
-- Expect an error matching pattern `pat`.
|
||||
local function expect_err(pat, ...)
|
||||
local fn = select(1, ...)
|
||||
local fn_args = {...}
|
||||
table.remove(fn_args, 1)
|
||||
assert.error_matches(function() return fn(unpack(fn_args)) end, pat)
|
||||
end
|
||||
|
||||
-- initial_path: directory to recurse into
|
||||
-- re: include pattern (string)
|
||||
@@ -296,6 +309,9 @@ local function repeated_read_cmd(...)
|
||||
end
|
||||
|
||||
local function shallowcopy(orig)
|
||||
if type(orig) ~= 'table' then
|
||||
return orig
|
||||
end
|
||||
local copy = {}
|
||||
for orig_key, orig_value in pairs(orig) do
|
||||
copy[orig_key] = orig_value
|
||||
@@ -303,6 +319,92 @@ local function shallowcopy(orig)
|
||||
return copy
|
||||
end
|
||||
|
||||
local deepcopy
|
||||
|
||||
local function id(v)
|
||||
return v
|
||||
end
|
||||
|
||||
local deepcopy_funcs = {
|
||||
table = function(orig)
|
||||
local copy = {}
|
||||
for k, v in pairs(orig) do
|
||||
copy[deepcopy(k)] = deepcopy(v)
|
||||
end
|
||||
return copy
|
||||
end,
|
||||
number = id,
|
||||
string = id,
|
||||
['nil'] = id,
|
||||
boolean = id,
|
||||
}
|
||||
|
||||
deepcopy = function(orig)
|
||||
return deepcopy_funcs[type(orig)](orig)
|
||||
end
|
||||
|
||||
local REMOVE_THIS = {}
|
||||
|
||||
local function mergedicts_copy(d1, d2)
|
||||
local ret = shallowcopy(d1)
|
||||
for k, v in pairs(d2) do
|
||||
if d2[k] == REMOVE_THIS then
|
||||
ret[k] = nil
|
||||
elseif type(d1[k]) == 'table' and type(v) == 'table' then
|
||||
ret[k] = mergedicts_copy(d1[k], v)
|
||||
else
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
-- dictdiff: find a diff so that mergedicts_copy(d1, diff) is equal to d2
|
||||
--
|
||||
-- Note: does not do copies of d2 values used.
|
||||
local function dictdiff(d1, d2)
|
||||
local ret = {}
|
||||
local hasdiff = false
|
||||
for k, v in pairs(d1) do
|
||||
if d2[k] == nil then
|
||||
hasdiff = true
|
||||
ret[k] = REMOVE_THIS
|
||||
elseif type(v) == type(d2[k]) then
|
||||
if type(v) == 'table' then
|
||||
local subdiff = dictdiff(v, d2[k])
|
||||
if subdiff ~= nil then
|
||||
hasdiff = true
|
||||
ret[k] = subdiff
|
||||
end
|
||||
elseif v ~= d2[k] then
|
||||
ret[k] = d2[k]
|
||||
hasdiff = true
|
||||
end
|
||||
else
|
||||
ret[k] = d2[k]
|
||||
hasdiff = true
|
||||
end
|
||||
end
|
||||
for k, v in pairs(d2) do
|
||||
if d1[k] == nil then
|
||||
ret[k] = shallowcopy(v)
|
||||
hasdiff = true
|
||||
end
|
||||
end
|
||||
if hasdiff then
|
||||
return ret
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local function updated(d, d2)
|
||||
for k, v in pairs(d2) do
|
||||
d[k] = v
|
||||
end
|
||||
return d
|
||||
end
|
||||
|
||||
local function concat_tables(...)
|
||||
local ret = {}
|
||||
for i = 1, select('#', ...) do
|
||||
@@ -339,24 +441,208 @@ local function dedent(str, leave_indent)
|
||||
return str
|
||||
end
|
||||
|
||||
local function format_float(v)
|
||||
-- On windows exponent appears to have three digits and not two
|
||||
local ret = ('%.6e'):format(v)
|
||||
local l, f, es, e = ret:match('^(%-?%d)%.(%d+)e([+%-])0*(%d%d+)$')
|
||||
return l .. '.' .. f .. 'e' .. es .. e
|
||||
end
|
||||
|
||||
local SUBTBL = {
|
||||
'\\000', '\\001', '\\002', '\\003', '\\004',
|
||||
'\\005', '\\006', '\\007', '\\008', '\\t',
|
||||
'\\n', '\\011', '\\012', '\\r', '\\014',
|
||||
'\\015', '\\016', '\\017', '\\018', '\\019',
|
||||
'\\020', '\\021', '\\022', '\\023', '\\024',
|
||||
'\\025', '\\026', '\\027', '\\028', '\\029',
|
||||
'\\030', '\\031',
|
||||
}
|
||||
|
||||
local format_luav
|
||||
|
||||
format_luav = function(v, indent, opts)
|
||||
opts = opts or {}
|
||||
local linesep = '\n'
|
||||
local next_indent_arg = nil
|
||||
local indent_shift = opts.indent_shift or ' '
|
||||
local next_indent
|
||||
local nl = '\n'
|
||||
if indent == nil then
|
||||
indent = ''
|
||||
linesep = ''
|
||||
next_indent = ''
|
||||
nl = ' '
|
||||
else
|
||||
next_indent_arg = indent .. indent_shift
|
||||
next_indent = indent .. indent_shift
|
||||
end
|
||||
local ret = ''
|
||||
if type(v) == 'string' then
|
||||
if opts.literal_strings then
|
||||
ret = v
|
||||
else
|
||||
local quote = opts.dquote_strings and '"' or '\''
|
||||
ret = quote .. tostring(v):gsub(
|
||||
opts.dquote_strings and '["\\]' or '[\'\\]',
|
||||
'\\%0'):gsub(
|
||||
'[%z\1-\31]', function(match)
|
||||
return SUBTBL[match:byte() + 1]
|
||||
end) .. quote
|
||||
end
|
||||
elseif type(v) == 'table' then
|
||||
if v == REMOVE_THIS then
|
||||
ret = 'REMOVE_THIS'
|
||||
else
|
||||
local processed_keys = {}
|
||||
ret = '{' .. linesep
|
||||
local non_empty = false
|
||||
for i, subv in ipairs(v) do
|
||||
ret = ('%s%s%s,%s'):format(ret, next_indent,
|
||||
format_luav(subv, next_indent_arg, opts), nl)
|
||||
processed_keys[i] = true
|
||||
non_empty = true
|
||||
end
|
||||
for k, subv in pairs(v) do
|
||||
if not processed_keys[k] then
|
||||
if type(k) == 'string' and k:match('^[a-zA-Z_][a-zA-Z0-9_]*$') then
|
||||
ret = ret .. next_indent .. k .. ' = '
|
||||
else
|
||||
ret = ('%s%s[%s] = '):format(ret, next_indent,
|
||||
format_luav(k, nil, opts))
|
||||
end
|
||||
ret = ret .. format_luav(subv, next_indent_arg, opts) .. ',' .. nl
|
||||
non_empty = true
|
||||
end
|
||||
end
|
||||
if nl == ' ' and non_empty then
|
||||
ret = ret:sub(1, -3)
|
||||
end
|
||||
ret = ret .. indent .. '}'
|
||||
end
|
||||
elseif type(v) == 'number' then
|
||||
if v % 1 == 0 then
|
||||
ret = ('%d'):format(v)
|
||||
else
|
||||
ret = format_float(v)
|
||||
end
|
||||
elseif type(v) == 'nil' then
|
||||
ret = 'nil'
|
||||
elseif type(v) == 'boolean' then
|
||||
ret = (v and 'true' or 'false')
|
||||
else
|
||||
print(type(v))
|
||||
-- Not implemented yet
|
||||
assert(false)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function format_string(fmt, ...)
|
||||
local i = 0
|
||||
local args = {...}
|
||||
local function getarg()
|
||||
i = i + 1
|
||||
return args[i]
|
||||
end
|
||||
local ret = fmt:gsub('%%[0-9*]*%.?[0-9*]*[cdEefgGiouXxqsr%%]', function(match)
|
||||
local subfmt = match:gsub('%*', function()
|
||||
return tostring(getarg())
|
||||
end)
|
||||
local arg = nil
|
||||
if subfmt:sub(-1) ~= '%' then
|
||||
arg = getarg()
|
||||
end
|
||||
if subfmt:sub(-1) == 'r' or subfmt:sub(-1) == 'q' then
|
||||
-- %r is like built-in %q, but it is supposed to single-quote strings and
|
||||
-- not double-quote them, and also work not only for strings.
|
||||
-- Builtin %q is replaced here as it gives invalid and inconsistent with
|
||||
-- luajit results for e.g. "\e" on lua: luajit transforms that into `\27`,
|
||||
-- lua leaves as-is.
|
||||
arg = format_luav(arg, nil, {dquote_strings = (subfmt:sub(-1) == 'q')})
|
||||
subfmt = subfmt:sub(1, -2) .. 's'
|
||||
end
|
||||
if subfmt == '%e' then
|
||||
return format_float(arg)
|
||||
else
|
||||
return subfmt:format(arg)
|
||||
end
|
||||
end)
|
||||
return ret
|
||||
end
|
||||
|
||||
local function intchar2lua(ch)
|
||||
ch = tonumber(ch)
|
||||
return (20 <= ch and ch < 127) and ('%c'):format(ch) or ch
|
||||
end
|
||||
|
||||
local fixtbl_metatable = {
|
||||
__newindex = function()
|
||||
assert(false)
|
||||
end,
|
||||
}
|
||||
|
||||
local function fixtbl(tbl)
|
||||
return setmetatable(tbl, fixtbl_metatable)
|
||||
end
|
||||
|
||||
local function fixtbl_rec(tbl)
|
||||
for _, v in pairs(tbl) do
|
||||
if type(v) == 'table' then
|
||||
fixtbl_rec(v)
|
||||
end
|
||||
end
|
||||
return fixtbl(tbl)
|
||||
end
|
||||
|
||||
-- From https://github.com/premake/premake-core/blob/master/src/base/table.lua
|
||||
local function table_flatten(arr)
|
||||
local result = {}
|
||||
local function _table_flatten(_arr)
|
||||
local n = #_arr
|
||||
for i = 1, n do
|
||||
local v = _arr[i]
|
||||
if type(v) == "table" then
|
||||
_table_flatten(v)
|
||||
elseif v then
|
||||
table.insert(result, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
_table_flatten(arr)
|
||||
return result
|
||||
end
|
||||
|
||||
return {
|
||||
REMOVE_THIS = REMOVE_THIS,
|
||||
argss_to_cmd = argss_to_cmd,
|
||||
check_cores = check_cores,
|
||||
check_logs = check_logs,
|
||||
concat_tables = concat_tables,
|
||||
dedent = dedent,
|
||||
deepcopy = deepcopy,
|
||||
dictdiff = dictdiff,
|
||||
eq = eq,
|
||||
expect_err = expect_err,
|
||||
filter = filter,
|
||||
fixtbl = fixtbl,
|
||||
fixtbl_rec = fixtbl_rec,
|
||||
format_luav = format_luav,
|
||||
format_string = format_string,
|
||||
glob = glob,
|
||||
hasenv = hasenv,
|
||||
intchar2lua = intchar2lua,
|
||||
map = map,
|
||||
matches = matches,
|
||||
mergedicts_copy = mergedicts_copy,
|
||||
neq = neq,
|
||||
ok = ok,
|
||||
check_logs = check_logs,
|
||||
uname = uname,
|
||||
tmpname = tmpname,
|
||||
map = map,
|
||||
filter = filter,
|
||||
glob = glob,
|
||||
check_cores = check_cores,
|
||||
hasenv = hasenv,
|
||||
which = which,
|
||||
argss_to_cmd = argss_to_cmd,
|
||||
popen_r = popen_r,
|
||||
popen_w = popen_w,
|
||||
repeated_read_cmd = repeated_read_cmd,
|
||||
shallowcopy = shallowcopy,
|
||||
concat_tables = concat_tables,
|
||||
dedent = dedent,
|
||||
table_flatten = table_flatten,
|
||||
tmpname = tmpname,
|
||||
uname = uname,
|
||||
updated = updated,
|
||||
which = which,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user