1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-04 09:40:03 +08:00
SpaceVim/bundle/cmp-dictionary/lua/cmp_dictionary/kit/init.lua
2023-06-11 21:41:39 +08:00

214 lines
4.4 KiB
Lua
Vendored

local kit = {}
local is_thread = vim.is_thread()
---Create gabage collection detector.
---@param callback fun(...: any): any
---@return userdata
function kit.gc(callback)
local gc = newproxy(true)
if vim.is_thread() or os.getenv('NODE_ENV') == 'test' then
getmetatable(gc).__gc = callback
else
getmetatable(gc).__gc = vim.schedule_wrap(callback)
end
return gc
end
---Bind arguments for function.
---@param fn fun(...: any): any
---@vararg any
---@return fun(...: any): any
function kit.bind(fn, ...)
local args = { ... }
return function(...)
return fn(unpack(args), ...)
end
end
---Safe version of vim.schedule.
---@param fn fun(...: any): any
function kit.safe_schedule(fn)
if is_thread then
fn()
else
vim.schedule(fn)
end
end
---Safe version of vim.schedule_wrap.
---@param fn fun(...: any): any
function kit.safe_schedule_wrap(fn)
if is_thread then
return fn
else
return vim.schedule_wrap(fn)
end
end
---Create unique id.
---@return integer
kit.unique_id = setmetatable({
unique_id = 0,
}, {
__call = function(self)
self.unique_id = self.unique_id + 1
return self.unique_id
end,
})
---Merge two tables.
---@generic T
---NOTE: This doesn't merge array-like table.
---@param tbl1 T
---@param tbl2 T
---@return T
function kit.merge(tbl1, tbl2)
local is_dict1 = kit.is_dict(tbl1)
local is_dict2 = kit.is_dict(tbl2)
if is_dict1 and is_dict2 then
local new_tbl = {}
for k, v in pairs(tbl2) do
if tbl1[k] ~= vim.NIL then
new_tbl[k] = kit.merge(tbl1[k], v)
end
end
for k, v in pairs(tbl1) do
if tbl2[k] == nil then
if v ~= vim.NIL then
new_tbl[k] = v
else
new_tbl[k] = nil
end
end
end
return new_tbl
elseif is_dict1 and not is_dict2 then
return kit.merge(tbl1, {})
elseif not is_dict1 and is_dict2 then
return kit.merge(tbl2, {})
end
if tbl1 == vim.NIL then
return nil
elseif tbl1 == nil then
return tbl2
else
return tbl1
end
end
---Recursive convert value via callback function.
---@param tbl table
---@param callback fun(value: any): any
---@return table
function kit.convert(tbl, callback)
if kit.is_dict(tbl) then
local new_tbl = {}
for k, v in pairs(tbl) do
new_tbl[k] = kit.convert(v, callback)
end
return new_tbl
end
return callback(tbl)
end
---Map array.
---@param array table
---@param fn fun(item: unknown, index: integer): unknown
---@return unknown[]
function kit.map(array, fn)
local new_array = {}
for i, item in ipairs(array) do
table.insert(new_array, fn(item, i))
end
return new_array
end
---Concatenate two tables.
---NOTE: This doesn't concatenate dict-like table.
---@param tbl1 table
---@param tbl2 table
---@return table
function kit.concat(tbl1, tbl2)
local new_tbl = {}
for _, item in ipairs(tbl1) do
table.insert(new_tbl, item)
end
for _, item in ipairs(tbl2) do
table.insert(new_tbl, item)
end
return new_tbl
end
---The value to array.
---@param value any
---@return table
function kit.to_array(value)
if type(value) == 'table' then
if vim.tbl_islist(value) or vim.tbl_isempty(value) then
return value
end
end
return { value }
end
---Check the value is array.
---@param value any
---@return boolean
function kit.is_array(value)
return not not (type(value) == 'table' and (vim.tbl_islist(value) or vim.tbl_isempty(value)))
end
---Check the value is dict.
---@param value any
---@return boolean
function kit.is_dict(value)
return type(value) == 'table' and (not vim.tbl_islist(value) or vim.tbl_isempty(value))
end
---Reverse the array.
---@param array table
---@return table
function kit.reverse(array)
if not kit.is_array(array) then
error('[kit] specified value is not an array.')
end
local new_array = {}
for i = #array, 1, -1 do
table.insert(new_array, array[i])
end
return new_array
end
---@generic T
---@param value T?
---@param default T
function kit.default(value, default)
if value == nil then
return default
end
return value
end
---Get object path with default value.
---@generic T
---@param value table
---@param path integer|string|(string|integer)[]
---@param default? T
---@return T
function kit.get(value, path, default)
local result = value
for _, key in ipairs(kit.to_array(path)) do
if type(result) == 'table' then
result = result[key]
else
return default
end
end
return result or default
end
return kit