1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 05:20:04 +08:00
SpaceVim/bundle/cmp-cmdline/lua/cmp_cmdline/init.lua
2022-01-01 22:13:13 +08:00

136 lines
3.5 KiB
Lua

local cmp = require('cmp')
local definitions = {
{
ctype = 'customlist',
regex = [=[[^[:blank:]]*$]=],
kind = cmp.lsp.CompletionItemKind.Variable,
fallback = true,
isIncomplete = false,
exec = function(arglead, cmdline, curpos)
local name = cmdline:match([=[^[ <'>]*(%a*)]=])
if not name then
return {}
end
for name_, option in pairs(vim.api.nvim_get_commands({ builtin = false })) do
if name_ == name then
if vim.tbl_contains({ 'customlist', 'custom' }, option.complete) then
local ok, items = pcall(function()
local func = string.gsub(option.complete_arg, 's:', ('<SNR>%d_'):format(option.script_id))
return vim.fn.eval(('%s("%s", "%s", "%s")'):format(
func,
vim.fn.escape(arglead, '"'),
vim.fn.escape(cmdline, '"'),
vim.fn.escape(curpos, '"')
))
end)
if not ok then
return {}
end
if type(items) == 'string' then
return vim.split(items, '\n')
elseif type(items) == 'table' then
return items
end
return {}
end
end
end
return {}
end
},
{
ctype = 'cmdline',
regex = [=[^[^!].*]=],
kind = cmp.lsp.CompletionItemKind.Variable,
isIncomplete = true,
exec = function(_, cmdline, _)
return vim.fn.getcompletion(cmdline, 'cmdline')
end
},
}
local source = {}
source.new = function()
return setmetatable({
before_line = '',
offset = -1,
ctype = '',
items = {},
}, { __index = source })
end
source.get_keyword_pattern = function()
return [=[[[:keyword:]-]*]=]
end
source.get_trigger_characters = function()
return { ' ', '.' }
end
source.is_available = function()
return vim.api.nvim_get_mode().mode == 'c'
end
source.complete = function(self, params, callback)
local offset = 0
local ctype = ''
local items = {}
local kind = ''
local isIncomplete = false
for _, def in ipairs(definitions) do
local s, e = vim.regex(def.regex):match_str(params.context.cursor_before_line)
if s and e then
offset = s
ctype = def.type
items = def.exec(
string.sub(params.context.cursor_before_line, s + 1),
params.context.cursor_before_line,
params.context.cursor.col
)
kind = def.kind
isIncomplete = def.isIncomplete
if not (#items == 0 and def.fallback) then
break
end
end
end
local labels = {}
items = vim.tbl_map(function(item)
if type(item) == 'string' then
labels[item] = true
return { label = item, kind = kind }
end
labels[item.word] = true
return { label = item.word, kind = kind }
end, items)
local match_prefix = false
if #params.context.cursor_before_line > #self.before_line then
match_prefix = string.find(params.context.cursor_before_line, self.before_line, 1, true) == 1
elseif #params.context.cursor_before_line < #self.before_line then
match_prefix = string.find(self.before_line, params.context.cursor_before_line, 1, true) == 1
end
if match_prefix and self.offset == offset and self.ctype == ctype then
for _, item in ipairs(self.items) do
if not labels[item.label] then
table.insert(items, item)
end
end
end
self.before_line = params.context.cursor_before_line
self.offset = offset
self.ctype = ctype
self.items = items
callback({
isIncomplete = isIncomplete,
items = items,
})
end
return source