RFC: cmdline completion (#362)
* manual support dot-repeat * cmdwin and terminal * cmdline only * Fix * fix * Improve * Fix test * Support macro * disable cmdline for now * Simplify * fmt * consume once * Ignore = type * cmdline * fmt * Improve * update * fmt * Support incsearch * fix * Add api * Avoid cmdline completion if the native_menu enabled * fix for macro * Improve * fmt * Insert-mode only by default * Update * avoid conflict * Improve default mapping * Fix * fix * similar to native * Update * Fix README.md * Improve * Use <afile>
This commit is contained in:
43
README.md
43
README.md
@@ -44,6 +44,8 @@ call plug#begin(s:plug_dir)
|
||||
Plug 'neovim/nvim-lspconfig'
|
||||
Plug 'hrsh7th/cmp-nvim-lsp'
|
||||
Plug 'hrsh7th/cmp-buffer'
|
||||
Plug 'hrsh7th/cmp-path'
|
||||
Plug 'hrsh7th/cmp-cmdline'
|
||||
Plug 'hrsh7th/nvim-cmp'
|
||||
|
||||
" For vsnip users.
|
||||
@@ -80,11 +82,14 @@ lua <<EOF
|
||||
end,
|
||||
},
|
||||
mapping = {
|
||||
['<C-d>'] = cmp.mapping.scroll_docs(-4),
|
||||
['<C-f>'] = cmp.mapping.scroll_docs(4),
|
||||
['<C-Space>'] = cmp.mapping.complete(),
|
||||
['<C-e>'] = cmp.mapping.close(),
|
||||
['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
|
||||
['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
|
||||
['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
|
||||
['<C-y>'] = cmp.config.disable, -- If you want to remove the default `<C-y>` mapping, You can specify `cmp.config.disable` value.
|
||||
['<C-e>'] = cmp.mapping({
|
||||
i = cmp.mapping.abort(),
|
||||
c = cmp.mapping.close(),
|
||||
}),
|
||||
['<CR>'] = cmp.mapping.confirm({ select = true }),
|
||||
},
|
||||
sources = cmp.config.sources({
|
||||
@@ -98,6 +103,22 @@ lua <<EOF
|
||||
})
|
||||
})
|
||||
|
||||
-- Use buffer source for `/`.
|
||||
cmp.setup.cmdline('/', {
|
||||
sources = {
|
||||
{ name = 'buffer' }
|
||||
}
|
||||
})
|
||||
|
||||
-- Use cmdline & path source for ':'.
|
||||
cmp.setup.cmdline(':', {
|
||||
sources = cmp.config.sources({
|
||||
{ name = 'path' }
|
||||
}, {
|
||||
{ name = 'cmdline' }
|
||||
})
|
||||
})
|
||||
|
||||
-- Setup lspconfig.
|
||||
local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())
|
||||
require('lspconfig')[%YOUR_LSP_SERVER%].setup {
|
||||
@@ -125,6 +146,7 @@ If you want to remove an option, you can set it to `false` instead.
|
||||
|
||||
Built in helper `cmd.mappings` are:
|
||||
|
||||
- *cmp.mapping(...)*
|
||||
- *cmp.mapping.select_prev_item({ cmp.SelectBehavior.{Insert,Select} } })*
|
||||
- *cmp.mapping.select_next_item({ cmp.SelectBehavior.{Insert,Select} })*
|
||||
- *cmp.mapping.scroll_docs(number)*
|
||||
@@ -133,7 +155,7 @@ Built in helper `cmd.mappings` are:
|
||||
- *cmp.mapping.abort()*
|
||||
- *cmp.mapping.confirm({ select = bool, behavior = cmp.ConfirmBehavior.{Insert,Replace} })*
|
||||
|
||||
You can configure `nvim-cmp` to use these `cmd.mappings` like this:
|
||||
You can configure `nvim-cmp` to use these `cmd.mapping` like this:
|
||||
|
||||
```lua
|
||||
mapping = {
|
||||
@@ -162,6 +184,17 @@ mapping = {
|
||||
}
|
||||
```
|
||||
|
||||
One more addition, the mapping mode can be specified by table key. It's useful to specify different function for each modes.
|
||||
|
||||
```lua
|
||||
mapping = {
|
||||
['<CR>'] = cmp.mapping({
|
||||
i = cmp.mapping.confirm({ select = true }),
|
||||
c = cmp.mapping.confirm({ select = false }),
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
You can specify your own custom mapping function.
|
||||
|
||||
```lua
|
||||
|
||||
@@ -15,6 +15,9 @@ config.global = require('cmp.config.default')()
|
||||
---@type table<number, cmp.ConfigSchema>
|
||||
config.buffers = {}
|
||||
|
||||
---@type table<string, cmp.ConfigSchema>
|
||||
config.cmdline = {}
|
||||
|
||||
---Set configuration for global.
|
||||
---@param c cmp.ConfigSchema
|
||||
config.set_global = function(c)
|
||||
@@ -32,14 +35,29 @@ config.set_buffer = function(c, bufnr)
|
||||
config.buffers[bufnr].revision = revision + 1
|
||||
end
|
||||
|
||||
---Set configuration for cmdline
|
||||
config.set_cmdline = function(c, type)
|
||||
local revision = (config.cmdline[type] or {}).revision or 1
|
||||
config.cmdline[type] = c
|
||||
config.cmdline[type].revision = revision + 1
|
||||
end
|
||||
|
||||
---@return cmp.ConfigSchema
|
||||
config.get = function()
|
||||
local global = config.global
|
||||
if api.is_cmdline_mode() then
|
||||
local type = vim.fn.getcmdtype()
|
||||
local cmdline = config.cmdline[type] or { revision = 1, sources = {} }
|
||||
return config.cache:ensure({ 'get_cmdline', type, global.revision or 0, cmdline.revision or 0 }, function()
|
||||
return misc.merge(cmdline, global)
|
||||
end)
|
||||
else
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local buffer = config.buffers[bufnr] or { revision = 1 }
|
||||
return config.cache:ensure({ 'get_buffer', bufnr, global.revision or 0, buffer.revision or 0 }, function()
|
||||
return misc.merge(buffer, global)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---Return cmp is enabled or not.
|
||||
|
||||
@@ -81,12 +81,28 @@ return function()
|
||||
event = {},
|
||||
|
||||
mapping = {
|
||||
['<Down>'] = mapping(mapping.select_next_item({ behavior = types.cmp.SelectBehavior.Select }), { 'i' }),
|
||||
['<Up>'] = mapping(mapping.select_prev_item({ behavior = types.cmp.SelectBehavior.Select }), { 'i' }),
|
||||
['<C-n>'] = mapping(mapping.select_next_item({ behavior = types.cmp.SelectBehavior.Insert }), { 'i' }),
|
||||
['<C-p>'] = mapping(mapping.select_prev_item({ behavior = types.cmp.SelectBehavior.Insert }), { 'i' }),
|
||||
['<C-y>'] = mapping(mapping.confirm({ select = false }), { 'i' }),
|
||||
['<C-e>'] = mapping(mapping.abort(), { 'i' }),
|
||||
['<Down>'] = mapping({
|
||||
i = mapping.select_next_item({ behavior = types.cmp.SelectBehavior.Select }),
|
||||
c = function(fallback)
|
||||
local cmp = require('cmp')
|
||||
cmp.close()
|
||||
vim.schedule(cmp.suspend())
|
||||
fallback()
|
||||
end,
|
||||
}),
|
||||
['<Up>'] = mapping({
|
||||
i = mapping.select_prev_item({ behavior = types.cmp.SelectBehavior.Select }),
|
||||
c = function(fallback)
|
||||
local cmp = require('cmp')
|
||||
cmp.close()
|
||||
vim.schedule(cmp.suspend())
|
||||
fallback()
|
||||
end,
|
||||
}),
|
||||
['<C-n>'] = mapping(mapping.select_next_item({ behavior = types.cmp.SelectBehavior.Insert }), { 'i', 'c' }),
|
||||
['<C-p>'] = mapping(mapping.select_prev_item({ behavior = types.cmp.SelectBehavior.Insert }), { 'i', 'c' }),
|
||||
['<C-y>'] = mapping.confirm({ select = false }),
|
||||
['<C-e>'] = mapping.abort(),
|
||||
},
|
||||
|
||||
formatting = {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
local api = require('cmp.utils.api')
|
||||
|
||||
local mapping
|
||||
mapping = setmetatable({}, {
|
||||
__call = function(_, invoke, modes)
|
||||
@@ -7,9 +9,25 @@ mapping = setmetatable({}, {
|
||||
invoke(...)
|
||||
end,
|
||||
modes = modes or { 'i' },
|
||||
__type = 'mapping',
|
||||
}
|
||||
end
|
||||
elseif type(invoke) == 'table' then
|
||||
if invoke.__type == 'mapping' then
|
||||
return invoke
|
||||
else
|
||||
return mapping(function(fallback)
|
||||
if api.is_insert_mode() and invoke.i then
|
||||
return invoke.i(fallback)
|
||||
elseif api.is_cmdline_mode() and invoke.c then
|
||||
return invoke.c(fallback)
|
||||
elseif api.is_select_mode() and invoke.s then
|
||||
return invoke.s(fallback)
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end, vim.tbl_keys(invoke))
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -53,7 +71,9 @@ end
|
||||
mapping.select_next_item = function(option)
|
||||
return function(fallback)
|
||||
if not require('cmp').select_next_item(option) then
|
||||
local release = require('cmp').core:suspend()
|
||||
fallback()
|
||||
vim.schedule(release)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -62,7 +82,9 @@ end
|
||||
mapping.select_prev_item = function(option)
|
||||
return function(fallback)
|
||||
if not require('cmp').select_prev_item(option) then
|
||||
local release = require('cmp').core:suspend()
|
||||
fallback()
|
||||
vim.schedule(release)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -70,10 +70,6 @@ cmp.close = function()
|
||||
cmp.core:reset()
|
||||
vim.schedule(release)
|
||||
return true
|
||||
elseif vim.fn.pumvisible() == 1 then
|
||||
vim.fn.complete(1, {})
|
||||
cmp.core:reset()
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
@@ -86,14 +82,16 @@ cmp.abort = function()
|
||||
cmp.core.view:abort()
|
||||
vim.schedule(release)
|
||||
return true
|
||||
elseif vim.fn.pumvisible() == 1 then
|
||||
vim.api.nvim_select_popupmenu_item(-1, true, true, {})
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
---Suspend completion.
|
||||
cmp.suspend = function()
|
||||
return cmp.core:suspend()
|
||||
end
|
||||
|
||||
---Select next item if possible
|
||||
cmp.select_next_item = function(option)
|
||||
option = option or {}
|
||||
@@ -252,6 +250,9 @@ cmp.setup = setmetatable({
|
||||
buffer = function(c)
|
||||
config.set_buffer(c, vim.api.nvim_get_current_buf())
|
||||
end,
|
||||
cmdline = function(type, c)
|
||||
config.set_cmdline(c, type)
|
||||
end,
|
||||
}, {
|
||||
__call = function(self, c)
|
||||
self.global(c)
|
||||
|
||||
@@ -267,7 +267,7 @@ source.complete = function(self, ctx, callback)
|
||||
completion_context = {
|
||||
triggerKind = types.lsp.CompletionTriggerKind.TriggerForIncompleteCompletions,
|
||||
}
|
||||
elseif self.request_offset ~= offset then
|
||||
elseif not vim.tbl_contains({ self.request_offset, self.offset }, offset) then
|
||||
completion_context = {
|
||||
triggerKind = types.lsp.CompletionTriggerKind.Invoked,
|
||||
}
|
||||
@@ -303,8 +303,7 @@ source.complete = function(self, ctx, callback)
|
||||
option = self:get_config().opts,
|
||||
completion_context = completion_context,
|
||||
},
|
||||
async.timeout(
|
||||
self.complete_dedup(vim.schedule_wrap(function(response)
|
||||
self.complete_dedup(vim.schedule_wrap(misc.once(function(response)
|
||||
if #((response or {}).items or response or {}) > 0 then
|
||||
debug.log(self:get_debug_name(), 'retrieve', #(response.items or response))
|
||||
local old_offset = self.offset
|
||||
@@ -334,9 +333,7 @@ source.complete = function(self, ctx, callback)
|
||||
self.status = prev_status
|
||||
end
|
||||
callback()
|
||||
end)),
|
||||
2000
|
||||
)
|
||||
end)))
|
||||
)
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -9,10 +9,11 @@ api.is_insert_mode = function()
|
||||
end
|
||||
|
||||
api.is_cmdline_mode = function()
|
||||
return vim.tbl_contains({
|
||||
local is_cmdline_mode = vim.tbl_contains({
|
||||
'c',
|
||||
'cv',
|
||||
}, vim.api.nvim_get_mode().mode)
|
||||
return is_cmdline_mode and vim.fn.getcmdtype() ~= '='
|
||||
end
|
||||
|
||||
api.is_select_mode = function()
|
||||
@@ -41,16 +42,17 @@ api.get_cursor = function()
|
||||
end
|
||||
|
||||
api.get_screen_cursor = function()
|
||||
local cursor = api.get_cursor()
|
||||
if api.is_cmdline_mode() then
|
||||
return cursor
|
||||
return api.get_cursor()
|
||||
end
|
||||
local cursor = api.get_cursor()
|
||||
local pos = vim.fn.screenpos(0, cursor[1], cursor[2] + 1)
|
||||
return { pos.row, pos.col - 1 }
|
||||
end
|
||||
|
||||
api.get_cursor_before_line = function()
|
||||
return string.sub(api.get_current_line(), 1, api.get_cursor()[2] + 1)
|
||||
local cursor = api.get_cursor()
|
||||
return string.sub(api.get_current_line(), 1, cursor[2] + 1)
|
||||
end
|
||||
|
||||
return api
|
||||
|
||||
@@ -64,7 +64,7 @@ keymap.to_keymap = setmetatable({
|
||||
|
||||
---Mode safe break undo
|
||||
keymap.undobreak = function()
|
||||
if api.is_cmdline_mode() then
|
||||
if not api.is_insert_mode() then
|
||||
return ''
|
||||
end
|
||||
return keymap.t('<C-g>u')
|
||||
@@ -72,7 +72,7 @@ end
|
||||
|
||||
---Mode safe join undo
|
||||
keymap.undojoin = function()
|
||||
if api.is_cmdline_mode() then
|
||||
if not api.is_insert_mode() then
|
||||
return ''
|
||||
end
|
||||
return keymap.t('<C-g>U')
|
||||
@@ -244,12 +244,12 @@ keymap.listen = setmetatable({
|
||||
misc.set(_G, { 'cmp', 'utils', 'keymap', 'listen', 'run' }, function(id)
|
||||
local definition = keymap.listen.cache:get({ 'definition', id })
|
||||
if definition.mode == 'c' and vim.fn.getcmdtype() == '=' then
|
||||
return vim.api.nvim_feedkeys(keymap.t(definition.fallback), 'it', true)
|
||||
return vim.api.nvim_feedkeys(keymap.t(definition.fallback.keys), definition.fallback.mode, true)
|
||||
end
|
||||
definition.callback(
|
||||
definition.keys,
|
||||
misc.once(function()
|
||||
vim.api.nvim_feedkeys(keymap.t(definition.fallback), 'it', true)
|
||||
vim.api.nvim_feedkeys(keymap.t(definition.fallback.keys), definition.fallback.mode, true)
|
||||
end)
|
||||
)
|
||||
return keymap.t('<Ignore>')
|
||||
@@ -258,18 +258,27 @@ end)
|
||||
---Evacuate existing key mapping
|
||||
---@param mode string
|
||||
---@param lhs string
|
||||
---@return string
|
||||
---@return { keys: string, mode: string }
|
||||
keymap.evacuate = function(mode, lhs)
|
||||
local map = keymap.find_map_by_lhs(mode, lhs)
|
||||
|
||||
-- Keep existing mapping as <Plug> mapping. We escape fisrt recursive key sequence. See `:help recursive_mapping`)
|
||||
local rhs = map.rhs
|
||||
if map.noremap == 0 then
|
||||
if map.expr == 1 then
|
||||
if map.noremap == 0 and map.expr == 1 then
|
||||
-- remap & expr mapping should evacuate as <Plug> mapping with solving recursive mapping.
|
||||
rhs = string.format('v:lua.cmp.utils.keymap.evacuate.expr("%s", "%s", "%s")', mode, str.escape(keymap.escape(lhs), { '"' }), str.escape(keymap.escape(rhs), { '"' }))
|
||||
else
|
||||
elseif map.noremap ~= 0 and map.expr == 1 then
|
||||
-- noremap & expr mapping should always evacuate as <Plug> mapping.
|
||||
rhs = rhs
|
||||
elseif map.noremap == 0 then
|
||||
-- remap & non-expr mapping should be checked if recursive or not.
|
||||
rhs = keymap.recursive(mode, lhs, rhs)
|
||||
if rhs == map.rhs or map.noremap ~= 0 then
|
||||
return { keys = rhs, mode = 'it' .. (map.noremap == 1 and 'n' or '') }
|
||||
end
|
||||
else
|
||||
-- noremap & non-expr mapping doesn't need to evacuate.
|
||||
return { keys = rhs, mode = 'it' .. (map.noremap == 1 and 'n' or '') }
|
||||
end
|
||||
|
||||
local fallback = ('<Plug>(cmp-utils-keymap-evacuate-rhs:%s)'):format(map.lhs)
|
||||
@@ -280,7 +289,7 @@ keymap.evacuate = function(mode, lhs)
|
||||
silent = true,
|
||||
nowait = true,
|
||||
})
|
||||
return fallback
|
||||
return { keys = fallback, mode = 'it' }
|
||||
end
|
||||
misc.set(_G, { 'cmp', 'utils', 'keymap', 'evacuate', 'expr' }, function(mode, lhs, rhs)
|
||||
return keymap.t(keymap.recursive(mode, lhs, vim.api.nvim_eval(rhs)))
|
||||
|
||||
@@ -43,7 +43,7 @@ describe('keymap', function()
|
||||
noremap = false,
|
||||
})
|
||||
local fallback = keymap.evacuate('i', '(')
|
||||
vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true)
|
||||
vim.api.nvim_feedkeys('i' .. keymap.t(fallback.keys), fallback.mode .. 'x', true)
|
||||
assert.are.same({ '(' }, vim.api.nvim_buf_get_lines(0, 0, -1, true))
|
||||
end)
|
||||
|
||||
@@ -57,7 +57,7 @@ describe('keymap', function()
|
||||
noremap = false,
|
||||
})
|
||||
local fallback = keymap.evacuate('i', '(')
|
||||
vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true)
|
||||
vim.api.nvim_feedkeys('i' .. keymap.t(fallback.keys), fallback.mode .. 'x', true)
|
||||
assert.are.same({ '()' }, vim.api.nvim_buf_get_lines(0, 0, -1, true))
|
||||
end)
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('keymap', function()
|
||||
noremap = false,
|
||||
})
|
||||
local fallback = keymap.evacuate('i', '<Tab>')
|
||||
vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true)
|
||||
vim.api.nvim_feedkeys('i' .. keymap.t(fallback.keys), fallback.mode .. 'x', true)
|
||||
assert.are.same({ 'foobar' }, vim.api.nvim_buf_get_lines(0, 0, -1, true))
|
||||
end)
|
||||
it('false', function()
|
||||
@@ -79,7 +79,7 @@ describe('keymap', function()
|
||||
noremap = false,
|
||||
})
|
||||
local fallback = keymap.evacuate('i', '<Tab>')
|
||||
vim.api.nvim_feedkeys('i' .. keymap.t(fallback), 'x', true)
|
||||
vim.api.nvim_feedkeys('i' .. keymap.t(fallback.keys), fallback.mode .. 'x', true)
|
||||
assert.are.same({ '\taiueo' }, vim.api.nvim_buf_get_lines(0, 0, -1, true))
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -5,12 +5,12 @@ local misc = {}
|
||||
---@return function
|
||||
misc.once = function(callback)
|
||||
local done = false
|
||||
return function()
|
||||
return function(...)
|
||||
if done then
|
||||
return
|
||||
end
|
||||
done = true
|
||||
callback()
|
||||
callback(...)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local cache = require('cmp.utils.cache')
|
||||
local misc = require('cmp.utils.misc')
|
||||
local buffer = require('cmp.utils.buffer')
|
||||
local api = require('cmp.utils.api')
|
||||
|
||||
---@class cmp.WindowStyle
|
||||
---@field public relative string
|
||||
@@ -31,7 +32,6 @@ window.new = function()
|
||||
self.style = {}
|
||||
self.cache = cache.new()
|
||||
self.opt = {}
|
||||
self.id = 0
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -76,8 +76,6 @@ end
|
||||
---Open window
|
||||
---@param style cmp.WindowStyle
|
||||
window.open = function(self, style)
|
||||
self.id = self.id + 1
|
||||
|
||||
if style then
|
||||
self:set_style(style)
|
||||
end
|
||||
@@ -146,13 +144,17 @@ window.update = function(self)
|
||||
self.swin2 = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- In cmdline, vim does not redraw automatically.
|
||||
if api.is_cmdline_mode() then
|
||||
vim.api.nvim_win_call(self.win, function()
|
||||
vim.cmd([[redraw]])
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---Close window
|
||||
window.close = function(self)
|
||||
local id = self.id
|
||||
vim.schedule(function()
|
||||
if id == self.id then
|
||||
if self.win and vim.api.nvim_win_is_valid(self.win) then
|
||||
if self.win and vim.api.nvim_win_is_valid(self.win) then
|
||||
vim.api.nvim_win_hide(self.win)
|
||||
@@ -167,8 +169,6 @@ window.close = function(self)
|
||||
self.swin2 = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---Return the window is visible or not.
|
||||
|
||||
@@ -6,6 +6,8 @@ local types = require('cmp.types')
|
||||
local keymap = require('cmp.utils.keymap')
|
||||
local api = require('cmp.utils.api')
|
||||
|
||||
local SIDE_PADDING = 1
|
||||
|
||||
---@class cmp.CustomEntriesView
|
||||
---@field private entries_win cmp.Window
|
||||
---@field private offset number
|
||||
@@ -50,7 +52,7 @@ custom_entries_view.new = function()
|
||||
local e = self.entries[i + 1]
|
||||
if e then
|
||||
local v = e:get_view(self.offset)
|
||||
local o = 1
|
||||
local o = SIDE_PADDING
|
||||
local a = 0
|
||||
for _, field in ipairs(fields) do
|
||||
if field == types.cmp.ItemField.Abbr then
|
||||
@@ -133,6 +135,7 @@ custom_entries_view.open = function(self, offset, entries)
|
||||
local height = vim.api.nvim_get_option('pumheight')
|
||||
height = height == 0 and #self.entries or height
|
||||
height = math.min(height, #self.entries)
|
||||
|
||||
if (vim.o.lines - pos[1]) <= 8 and pos[1] - 8 > 0 then
|
||||
height = math.min(height, pos[1] - 1)
|
||||
pos[1] = pos[1] - height - 1
|
||||
@@ -151,8 +154,8 @@ custom_entries_view.open = function(self, offset, entries)
|
||||
self.entries_win:open({
|
||||
relative = 'editor',
|
||||
style = 'minimal',
|
||||
row = row,
|
||||
col = col,
|
||||
row = math.max(0, row),
|
||||
col = math.max(0, col),
|
||||
width = width,
|
||||
height = height,
|
||||
zindex = 1001,
|
||||
@@ -196,16 +199,22 @@ custom_entries_view.draw = function(self)
|
||||
if e then
|
||||
local view = e:get_view(self.offset)
|
||||
local text = {}
|
||||
table.insert(text, ' ')
|
||||
table.insert(text, string.rep(' ', SIDE_PADDING))
|
||||
for _, field in ipairs(fields) do
|
||||
table.insert(text, view[field].text)
|
||||
table.insert(text, string.rep(' ', 1 + self.column_width[field] - view[field].width))
|
||||
end
|
||||
table.insert(text, ' ')
|
||||
table.insert(text, string.rep(' ', SIDE_PADDING))
|
||||
table.insert(texts, table.concat(text, ''))
|
||||
end
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(self.entries_win:get_buffer(), topline, botline, false, texts)
|
||||
|
||||
if api.is_cmdline_mode() then
|
||||
vim.api.nvim_win_call(self.entries_win.win, function()
|
||||
vim.cmd([[redraw]])
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
custom_entries_view.visible = function(self)
|
||||
@@ -282,20 +291,33 @@ custom_entries_view._select = function(self, cursor, option)
|
||||
vim.api.nvim_win_set_cursor(self.entries_win.win, { math.max(cursor, 1), is_insert and 0 or 1 })
|
||||
|
||||
if is_insert then
|
||||
self:_insert(self.entries[cursor] and self.entries[cursor]:get_vim_item(self.offset).word or self.prefix)
|
||||
self:_insert(self.entries[cursor] and self.entries[cursor]:get_vim_item(self.offset).word or self.prefix or '')
|
||||
end
|
||||
|
||||
self.entries_win:update()
|
||||
self:draw()
|
||||
self.event:emit('change')
|
||||
end
|
||||
|
||||
custom_entries_view._insert = function(self, word)
|
||||
keymap.feedkeys('', 'n', function()
|
||||
local release = require('cmp').core:suspend()
|
||||
if api.is_cmdline_mode() then
|
||||
local cursor = api.get_cursor()
|
||||
local length = vim.str_utfindex(string.sub(api.get_current_line(), self.offset, cursor[2]))
|
||||
keymap.feedkeys(keymap.backspace(length) .. word, 'int', vim.schedule_wrap(release))
|
||||
vim.api.nvim_feedkeys(keymap.backspace(length) .. word, 'int', true)
|
||||
else
|
||||
local release = require('cmp').core:suspend()
|
||||
keymap.feedkeys('', 'n', function()
|
||||
local cursor = api.get_cursor()
|
||||
local length = vim.str_utfindex(string.sub(api.get_current_line(), self.offset, cursor[2]))
|
||||
keymap.feedkeys(
|
||||
keymap.backspace(length) .. word,
|
||||
'int',
|
||||
vim.schedule_wrap(function()
|
||||
release()
|
||||
end)
|
||||
)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
return custom_entries_view
|
||||
|
||||
@@ -5,11 +5,12 @@ vim.g.loaded_cmp = true
|
||||
|
||||
local api = require "cmp.utils.api"
|
||||
local misc = require('cmp.utils.misc')
|
||||
local config = require('cmp.config')
|
||||
local highlight = require('cmp.utils.highlight')
|
||||
|
||||
-- TODO: https://github.com/neovim/neovim/pull/14661
|
||||
vim.cmd [[
|
||||
augroup cmp
|
||||
augroup ___cmp___
|
||||
autocmd!
|
||||
autocmd InsertEnter * lua require'cmp.utils.autocmd'.emit('InsertEnter')
|
||||
autocmd InsertLeave * lua require'cmp.utils.autocmd'.emit('InsertLeave')
|
||||
@@ -18,9 +19,42 @@ vim.cmd [[
|
||||
autocmd CompleteChanged * lua require'cmp.utils.autocmd'.emit('CompleteChanged')
|
||||
autocmd CompleteDone * lua require'cmp.utils.autocmd'.emit('CompleteDone')
|
||||
autocmd ColorScheme * call v:lua.cmp.plugin.colorscheme()
|
||||
autocmd CmdlineEnter * call v:lua.cmp.plugin.cmdline.enter()
|
||||
autocmd CmdlineLeave * call v:lua.cmp.plugin.cmdline.leave()
|
||||
augroup END
|
||||
]]
|
||||
|
||||
misc.set(_G, { 'cmp', 'plugin', 'cmdline', 'enter' }, function()
|
||||
if config.get().experimental.native_menu then
|
||||
return
|
||||
end
|
||||
local cmdtype = vim.fn.expand('<afile>')
|
||||
if cmdtype ~= '=' then
|
||||
vim.cmd [[
|
||||
augroup cmp-cmdline
|
||||
autocmd!
|
||||
autocmd CmdlineChanged * lua require'cmp.utils.autocmd'.emit('TextChanged')
|
||||
augroup END
|
||||
]]
|
||||
require('cmp.utils.autocmd').emit('InsertEnter')
|
||||
end
|
||||
end)
|
||||
|
||||
misc.set(_G, { 'cmp', 'plugin', 'cmdline', 'leave' }, function()
|
||||
if config.get().experimental.native_menu then
|
||||
return
|
||||
end
|
||||
local cmdtype = vim.fn.expand('<afile>')
|
||||
if cmdtype ~= '=' then
|
||||
vim.cmd [[
|
||||
augroup cmp-cmdline
|
||||
autocmd!
|
||||
augroup END
|
||||
]]
|
||||
require('cmp.utils.autocmd').emit('InsertLeave')
|
||||
end
|
||||
end)
|
||||
|
||||
misc.set(_G, { 'cmp', 'plugin', 'colorscheme' }, function()
|
||||
highlight.inherit('CmpItemAbbrDefault', 'Pmenu', {
|
||||
guibg = 'NONE',
|
||||
|
||||
Reference in New Issue
Block a user