20
doc/cmp.txt
20
doc/cmp.txt
@@ -204,6 +204,23 @@ NOTE: You can call these functions in mapping via `<Cmd>lua require('cmp').compl
|
||||
<
|
||||
NOTE: The `config` means a temporary setting, but the `config.mapping` remains permanent.
|
||||
|
||||
*cmp.complete_common_string* ()
|
||||
Complete common string as like as shell completion behavior.
|
||||
>
|
||||
cmp.setup {
|
||||
mapping = {
|
||||
['<C-n>'] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
if cmp.complete_common_string() then
|
||||
return
|
||||
end
|
||||
return cmp.select_next_item()
|
||||
end
|
||||
fallback()
|
||||
end, { 'i', 'c' }),
|
||||
}
|
||||
}
|
||||
<
|
||||
*cmp.confirm* (option: cmp.ConfirmOption, callback: function)
|
||||
Accept current selected completion item.
|
||||
If you didn't select any items and specified the `{ select = true }` for
|
||||
@@ -279,6 +296,9 @@ You can also use built-in mapping helpers.
|
||||
*cmp.mapping.complete* (option: cmp.CompleteParams)
|
||||
Same as |cmp.complete|
|
||||
|
||||
*cmp.mapping.complete_common_string* ()
|
||||
Same as |cmp.complete_common_string|
|
||||
|
||||
*cmp.mapping.confirm* (option: cmp.ConfirmOption)
|
||||
Same as |cmp.confirm|
|
||||
|
||||
|
||||
@@ -22,6 +22,15 @@ mapping.complete = function(option)
|
||||
end
|
||||
end
|
||||
|
||||
---Complete common string.
|
||||
mapping.complete_common_string = function()
|
||||
return function(fallback)
|
||||
if not require('cmp').complete_common_string() then
|
||||
fallback()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Close current completion menu if it displayed.
|
||||
mapping.close = function()
|
||||
return function(fallback)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local debug = require('cmp.utils.debug')
|
||||
local str = require('cmp.utils.str')
|
||||
local char = require('cmp.utils.char')
|
||||
local pattern = require('cmp.utils.pattern')
|
||||
local feedkeys = require('cmp.utils.feedkeys')
|
||||
@@ -217,6 +218,32 @@ core.autoindent = function(self, trigger_event, callback)
|
||||
callback()
|
||||
end
|
||||
|
||||
---Complete common string for current completed entries.
|
||||
core.complete_common_string = function(self)
|
||||
if not self.view:visible() then
|
||||
return false
|
||||
end
|
||||
|
||||
self.filter:sync(1000)
|
||||
|
||||
local cursor = api.get_cursor()
|
||||
local offset = self.view:get_offset()
|
||||
local common_string
|
||||
for _, e in ipairs(self.view:get_entries()) do
|
||||
local vim_item = e:get_vim_item(offset)
|
||||
if not common_string then
|
||||
common_string = vim_item.word
|
||||
else
|
||||
common_string = str.get_common_string(common_string, vim_item.word)
|
||||
end
|
||||
end
|
||||
if common_string and #common_string > (1 + cursor[2] - offset) then
|
||||
feedkeys.call(keymap.backspace(string.sub(api.get_current_line(), offset, cursor[2])) .. common_string, 'n')
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---Invoke completion
|
||||
---@param ctx cmp.Context
|
||||
core.complete = function(self, ctx)
|
||||
|
||||
@@ -75,6 +75,10 @@ cmp.complete = cmp.sync(function(option)
|
||||
return true
|
||||
end)
|
||||
|
||||
cmp.complete_common_string = cmp.sync(function()
|
||||
return cmp.core:complete_common_string()
|
||||
end)
|
||||
|
||||
---Return view is visible or not.
|
||||
cmp.visible = cmp.sync(function()
|
||||
return cmp.core.view:visible() or vim.fn.pumvisible() == 1
|
||||
|
||||
@@ -67,6 +67,9 @@ end
|
||||
---@param count number
|
||||
---@return string
|
||||
keymap.backspace = function(count)
|
||||
if type(count) == 'string' then
|
||||
count = vim.fn.strchars(count, true)
|
||||
end
|
||||
if count <= 0 then
|
||||
return ''
|
||||
end
|
||||
|
||||
@@ -43,6 +43,17 @@ str.has_prefix = function(text, prefix)
|
||||
return true
|
||||
end
|
||||
|
||||
---get_common_string
|
||||
str.get_common_string = function(text1, text2)
|
||||
local min = math.min(#text1, #text2)
|
||||
for i = 1, min do
|
||||
if not char.match(string.byte(text1, i), string.byte(text2, i)) then
|
||||
return string.sub(text1, 1, i - 1)
|
||||
end
|
||||
end
|
||||
return string.sub(text1, 1, min)
|
||||
end
|
||||
|
||||
---Remove suffix
|
||||
---@param text string
|
||||
---@param suffix string
|
||||
|
||||
@@ -161,6 +161,17 @@ view.select_prev_item = function(self, option)
|
||||
self:_get_entries_view():select_prev_item(option)
|
||||
end
|
||||
|
||||
---Get offset.
|
||||
view.get_offset = function(self)
|
||||
return self:_get_entries_view():get_offset()
|
||||
end
|
||||
|
||||
---Get entries.
|
||||
---@return cmp.Entry[]
|
||||
view.get_entries = function(self)
|
||||
return self:_get_entries_view():get_entries()
|
||||
end
|
||||
|
||||
---Get first entry
|
||||
---@param self cmp.Entry|nil
|
||||
view.get_first_entry = function(self)
|
||||
|
||||
@@ -257,6 +257,20 @@ custom_entries_view.select_prev_item = function(self, option)
|
||||
end
|
||||
end
|
||||
|
||||
custom_entries_view.get_offset = function(self)
|
||||
if self:visible() then
|
||||
return self.offset
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
custom_entries_view.get_entries = function(self)
|
||||
if self:visible() then
|
||||
return self.entries
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
custom_entries_view.get_first_entry = function(self)
|
||||
if self:visible() then
|
||||
return self.entries[1]
|
||||
@@ -301,8 +315,7 @@ custom_entries_view._insert = setmetatable({
|
||||
word = word or ''
|
||||
if api.is_cmdline_mode() then
|
||||
local cursor = api.get_cursor()
|
||||
local length = vim.fn.strchars(string.sub(api.get_current_line(), self.offset, cursor[2]), true)
|
||||
vim.api.nvim_feedkeys(keymap.backspace(length) .. word, 'int', true)
|
||||
vim.api.nvim_feedkeys(keymap.backspace(string.sub(api.get_current_line(), self.offset, cursor[2])) .. word, 'int', true)
|
||||
else
|
||||
if this.pending then
|
||||
return
|
||||
@@ -312,10 +325,9 @@ custom_entries_view._insert = setmetatable({
|
||||
local release = require('cmp').suspend()
|
||||
feedkeys.call('', '', function()
|
||||
local cursor = api.get_cursor()
|
||||
local length = vim.fn.strchars(string.sub(api.get_current_line(), self.offset, cursor[2]), true)
|
||||
local keys = {}
|
||||
table.insert(keys, keymap.indentkeys())
|
||||
table.insert(keys, keymap.backspace(length))
|
||||
table.insert(keys, keymap.backspace(string.sub(api.get_current_line(), self.offset, cursor[2])))
|
||||
table.insert(keys, word)
|
||||
table.insert(keys, keymap.indentkeys(vim.bo.indentkeys))
|
||||
feedkeys.call(
|
||||
|
||||
@@ -143,6 +143,20 @@ native_entries_view.select_prev_item = function(self, option)
|
||||
end
|
||||
end
|
||||
|
||||
native_entries_view.get_offset = function(self)
|
||||
if self:visible() then
|
||||
return self.offset
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
native_entries_view.get_entries = function(self)
|
||||
if self:visible() then
|
||||
return self.entries
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
native_entries_view.get_first_entry = function(self)
|
||||
if self:visible() then
|
||||
return self.entries[1]
|
||||
|
||||
@@ -14,16 +14,16 @@ local api = require('cmp.utils.api')
|
||||
---@field private active boolean
|
||||
---@field private entries cmp.Entry[]
|
||||
---@field public event cmp.Event
|
||||
local statusline_entries_view = {}
|
||||
local wildmenu_entries_view = {}
|
||||
|
||||
local function get_separator()
|
||||
local c = config.get()
|
||||
return (c and c.view and c.view.entries and c.view.entries.separator) or ' '
|
||||
end
|
||||
|
||||
statusline_entries_view.ns = vim.api.nvim_create_namespace('cmp.view.statusline_entries_view')
|
||||
wildmenu_entries_view.ns = vim.api.nvim_create_namespace('cmp.view.statusline_entries_view')
|
||||
|
||||
statusline_entries_view.init = function(self)
|
||||
wildmenu_entries_view.init = function(self)
|
||||
self.event = event.new()
|
||||
self.offset = -1
|
||||
self.active = false
|
||||
@@ -33,8 +33,8 @@ statusline_entries_view.init = function(self)
|
||||
self.moving_forwards = nil
|
||||
end
|
||||
|
||||
statusline_entries_view.new = function()
|
||||
local self = setmetatable({}, { __index = statusline_entries_view })
|
||||
wildmenu_entries_view.new = function()
|
||||
local self = setmetatable({}, { __index = wildmenu_entries_view })
|
||||
self:init()
|
||||
|
||||
self.entries_win = window.new()
|
||||
@@ -47,7 +47,7 @@ statusline_entries_view.new = function()
|
||||
self.entries_win:option('winhighlight', 'Normal:Pmenu,FloatBorder:Pmenu,CursorLine:PmenuSel,Search:None')
|
||||
self.entries_win:buffer_option('tabstop', 1)
|
||||
|
||||
vim.api.nvim_set_decoration_provider(statusline_entries_view.ns, {
|
||||
vim.api.nvim_set_decoration_provider(wildmenu_entries_view.ns, {
|
||||
on_win = function(_, win, buf, _, _)
|
||||
if win ~= self.entries_win.win or buf ~= self.entries_win:get_buffer() then
|
||||
return
|
||||
@@ -58,7 +58,7 @@ statusline_entries_view.new = function()
|
||||
local e = self.entries[i]
|
||||
if e then
|
||||
local view = e:get_view(self.offset, buf)
|
||||
vim.api.nvim_buf_set_extmark(buf, statusline_entries_view.ns, 0, location, {
|
||||
vim.api.nvim_buf_set_extmark(buf, wildmenu_entries_view.ns, 0, location, {
|
||||
end_line = 0,
|
||||
end_col = location + view['abbr'].bytes,
|
||||
hl_group = view['abbr'].hl_group,
|
||||
@@ -67,7 +67,7 @@ statusline_entries_view.new = function()
|
||||
})
|
||||
|
||||
if i == self.selected_index then
|
||||
vim.api.nvim_buf_set_extmark(buf, statusline_entries_view.ns, 0, location, {
|
||||
vim.api.nvim_buf_set_extmark(buf, wildmenu_entries_view.ns, 0, location, {
|
||||
end_line = 0,
|
||||
end_col = location + view['abbr'].bytes,
|
||||
hl_group = 'PmenuSel',
|
||||
@@ -77,7 +77,7 @@ statusline_entries_view.new = function()
|
||||
end
|
||||
|
||||
for _, m in ipairs(e.matches or {}) do
|
||||
vim.api.nvim_buf_set_extmark(buf, statusline_entries_view.ns, 0, location + m.word_match_start - 1, {
|
||||
vim.api.nvim_buf_set_extmark(buf, wildmenu_entries_view.ns, 0, location + m.word_match_start - 1, {
|
||||
end_line = 0,
|
||||
end_col = location + m.word_match_end,
|
||||
hl_group = m.fuzzy and 'CmpItemAbbrMatchFuzzy' or 'CmpItemAbbrMatch',
|
||||
@@ -103,20 +103,20 @@ statusline_entries_view.new = function()
|
||||
return self
|
||||
end
|
||||
|
||||
statusline_entries_view.close = function(self)
|
||||
wildmenu_entries_view.close = function(self)
|
||||
self.entries_win:close()
|
||||
self:init()
|
||||
end
|
||||
|
||||
statusline_entries_view.ready = function()
|
||||
wildmenu_entries_view.ready = function()
|
||||
return vim.fn.pumvisible() == 0
|
||||
end
|
||||
|
||||
statusline_entries_view.on_change = function(self)
|
||||
wildmenu_entries_view.on_change = function(self)
|
||||
self.active = false
|
||||
end
|
||||
|
||||
statusline_entries_view.open = function(self, offset, entries)
|
||||
wildmenu_entries_view.open = function(self, offset, entries)
|
||||
self.offset = offset
|
||||
self.entries = {}
|
||||
self.last_displayed_indices = {}
|
||||
@@ -159,13 +159,13 @@ statusline_entries_view.open = function(self, offset, entries)
|
||||
end
|
||||
end
|
||||
|
||||
statusline_entries_view.abort = function(self)
|
||||
wildmenu_entries_view.abort = function(self)
|
||||
feedkeys.call('', 'n', function()
|
||||
self:close()
|
||||
end)
|
||||
end
|
||||
|
||||
statusline_entries_view.draw = function(self)
|
||||
wildmenu_entries_view.draw = function(self)
|
||||
local entries_buf = self.entries_win:get_buffer()
|
||||
local texts = {}
|
||||
local lengths = {}
|
||||
@@ -235,15 +235,15 @@ statusline_entries_view.draw = function(self)
|
||||
end)
|
||||
end
|
||||
|
||||
statusline_entries_view.visible = function(self)
|
||||
wildmenu_entries_view.visible = function(self)
|
||||
return self.entries_win:visible()
|
||||
end
|
||||
|
||||
statusline_entries_view.info = function(self)
|
||||
wildmenu_entries_view.info = function(self)
|
||||
return self.entries_win:info()
|
||||
end
|
||||
|
||||
statusline_entries_view.select_next_item = function(self, option)
|
||||
wildmenu_entries_view.select_next_item = function(self, option)
|
||||
if self:visible() then
|
||||
self.moving_forwards = true
|
||||
if self.selected_index == nil or self.selected_index == #self.entries then
|
||||
@@ -254,7 +254,7 @@ statusline_entries_view.select_next_item = function(self, option)
|
||||
end
|
||||
end
|
||||
|
||||
statusline_entries_view.select_prev_item = function(self, option)
|
||||
wildmenu_entries_view.select_prev_item = function(self, option)
|
||||
if self:visible() then
|
||||
self.moving_forwards = false
|
||||
if self.selected_index == nil or self.selected_index <= 1 then
|
||||
@@ -265,33 +265,46 @@ statusline_entries_view.select_prev_item = function(self, option)
|
||||
end
|
||||
end
|
||||
|
||||
statusline_entries_view.get_first_entry = function(self)
|
||||
wildmenu_entries_view.get_offset = function(self)
|
||||
if self:visible() then
|
||||
return self.offset
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
wildmenu_entries_view.get_entries = function(self)
|
||||
if self:visible() then
|
||||
return self.entries
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
wildmenu_entries_view.get_first_entry = function(self)
|
||||
if self:visible() then
|
||||
return self.entries[1]
|
||||
end
|
||||
end
|
||||
|
||||
statusline_entries_view.get_selected_entry = function(self)
|
||||
wildmenu_entries_view.get_selected_entry = function(self)
|
||||
if self:visible() and self.active then
|
||||
return self.entries[self.selected_index]
|
||||
end
|
||||
end
|
||||
|
||||
statusline_entries_view.get_active_entry = function(self)
|
||||
wildmenu_entries_view.get_active_entry = function(self)
|
||||
if self:visible() and self.active then
|
||||
return self:get_selected_entry()
|
||||
end
|
||||
end
|
||||
|
||||
statusline_entries_view._select = function(self, selected_index, _)
|
||||
wildmenu_entries_view._select = function(self, selected_index, _)
|
||||
self.selected_index = selected_index
|
||||
self.active = (selected_index ~= nil)
|
||||
|
||||
if self.active then
|
||||
local cursor = api.get_cursor()
|
||||
local word = self:get_active_entry():get_vim_item(self.offset).word
|
||||
local length = vim.fn.strchars(string.sub(api.get_current_line(), self.offset, cursor[2]), true)
|
||||
vim.api.nvim_feedkeys(keymap.backspace(length) .. word, 'int', true)
|
||||
vim.api.nvim_feedkeys(keymap.backspace(string.sub(api.get_current_line(), self.offset, cursor[2])) .. word, 'int', true)
|
||||
end
|
||||
|
||||
self.entries_win:update()
|
||||
@@ -299,4 +312,4 @@ statusline_entries_view._select = function(self, selected_index, _)
|
||||
self.event:emit('change')
|
||||
end
|
||||
|
||||
return statusline_entries_view
|
||||
return wildmenu_entries_view
|
||||
|
||||
Reference in New Issue
Block a user