dev (#956)
* Adjust empty line count * Implement vim.api.nvim_create_autocmd (#844) * Implement vim.api.nvim_create_autocmd * Only use vim.api.nvim_create_autocmd on nighly * Cleanup * cleanup * Rename autos.lua to autocmds.lua * Fix forgot to rename autos to autocmds * Remove legacy autocmd * Add descriptions on autocmds * Update descriptions on autocmds * Update CmpStatus command to lua API (#922) Signed-off-by: Micah Halter <micah@balena.io> * Move highlights to nvim_set_hl lua API (#925) Signed-off-by: Micah Halter <micah@balena.io> * Add default to highlight * Refactor autocmds * fmt * Improve performance * Fix bug * Improve matching logic Fixes https://github.com/hrsh7th/nvim-cmp/discussions/954 * Fix format * Improve performance Fix #825 * Fix cmdline redraw bug * Fix event Co-authored-by: hrsh7th <> Co-authored-by: zer09 <zer09@users.noreply.github.com> Co-authored-by: Micah Halter <micah@mehalter.com>
This commit is contained in:
@@ -24,7 +24,6 @@ Concept
|
|||||||
- No flicker
|
- No flicker
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Setup
|
Setup
|
||||||
====================
|
====================
|
||||||
|
|
||||||
@@ -134,15 +133,14 @@ EOF
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Where can I find more completion sources?
|
### Where can I find more completion sources?
|
||||||
|
|
||||||
- See the [Wiki](https://github.com/hrsh7th/nvim-cmp/wiki/List-of-sources)
|
- See the [Wiki](https://github.com/hrsh7th/nvim-cmp/wiki/List-of-sources)
|
||||||
- See the [GitHub topic](https://github.com/topics/nvim-cmp).
|
- See the [GitHub topic](https://github.com/topics/nvim-cmp).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Where can I find advanced configuration examples?
|
### Where can I find advanced configuration examples?
|
||||||
|
|
||||||
See the [Wiki](https://github.com/hrsh7th/nvim-cmp/wiki)
|
See the [Wiki](https://github.com/hrsh7th/nvim-cmp/wiki)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ local event = require('cmp.utils.event')
|
|||||||
|
|
||||||
local SOURCE_TIMEOUT = 500
|
local SOURCE_TIMEOUT = 500
|
||||||
local DEBOUNCE_TIME = 80
|
local DEBOUNCE_TIME = 80
|
||||||
local THROTTLE_TIME = 60
|
local THROTTLE_TIME = 40
|
||||||
|
|
||||||
---@class cmp.Core
|
---@class cmp.Core
|
||||||
---@field public suspending boolean
|
---@field public suspending boolean
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ local feedkeys = require('cmp.utils.feedkeys')
|
|||||||
local autocmd = require('cmp.utils.autocmd')
|
local autocmd = require('cmp.utils.autocmd')
|
||||||
local keymap = require('cmp.utils.keymap')
|
local keymap = require('cmp.utils.keymap')
|
||||||
local misc = require('cmp.utils.misc')
|
local misc = require('cmp.utils.misc')
|
||||||
|
local async = require('cmp.utils.async')
|
||||||
|
|
||||||
local cmp = {}
|
local cmp = {}
|
||||||
|
|
||||||
@@ -283,39 +284,40 @@ cmp.setup = setmetatable({
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
autocmd.subscribe('InsertEnter', function()
|
-- In InsertEnter autocmd, vim will detects mode=normal unexpectedly.
|
||||||
feedkeys.call('', 'i', function()
|
autocmd.subscribe(
|
||||||
|
{ 'InsertEnter', 'CmdlineEnter' },
|
||||||
|
async.debounce_safe_state(function()
|
||||||
if config.enabled() then
|
if config.enabled() then
|
||||||
|
cmp.config.compare.scopes:update()
|
||||||
|
cmp.config.compare.locality:update()
|
||||||
cmp.core:prepare()
|
cmp.core:prepare()
|
||||||
cmp.core:on_change('InsertEnter')
|
cmp.core:on_change('InsertEnter')
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end)
|
)
|
||||||
|
|
||||||
autocmd.subscribe('InsertLeave', function()
|
-- async.throttle is needed for performance. The mapping `:<C-u>...<CR>` will fire `CmdlineChanged` for each character.
|
||||||
cmp.core:reset()
|
autocmd.subscribe(
|
||||||
cmp.core.view:close()
|
{ 'TextChangedI', 'TextChangedP', 'CmdlineChanged' },
|
||||||
end)
|
async.debounce_safe_state(function()
|
||||||
|
|
||||||
autocmd.subscribe('CmdlineEnter', function()
|
|
||||||
if config.enabled() then
|
|
||||||
cmp.core:prepare()
|
|
||||||
cmp.core:on_change('InsertEnter')
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
autocmd.subscribe('CmdlineLeave', function()
|
|
||||||
cmp.core:reset()
|
|
||||||
cmp.core.view:close()
|
|
||||||
end)
|
|
||||||
|
|
||||||
autocmd.subscribe('TextChanged', function()
|
|
||||||
if config.enabled() then
|
if config.enabled() then
|
||||||
cmp.core:on_change('TextChanged')
|
cmp.core:on_change('TextChanged')
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
)
|
||||||
|
|
||||||
autocmd.subscribe('CursorMoved', function()
|
-- If make this asynchronous, the completion menu will not close when the command output is displayed.
|
||||||
|
autocmd.subscribe({ 'InsertLeave', 'CmdlineLeave' }, function()
|
||||||
|
if config.enabled() then
|
||||||
|
cmp.core:reset()
|
||||||
|
cmp.core.view:close()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
autocmd.subscribe(
|
||||||
|
'CursorMovedI',
|
||||||
|
async.debounce_safe_state(function()
|
||||||
if config.enabled() then
|
if config.enabled() then
|
||||||
cmp.core:on_moved()
|
cmp.core:on_moved()
|
||||||
else
|
else
|
||||||
@@ -323,11 +325,7 @@ autocmd.subscribe('CursorMoved', function()
|
|||||||
cmp.core.view:close()
|
cmp.core.view:close()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
)
|
||||||
autocmd.subscribe('InsertEnter', function()
|
|
||||||
cmp.config.compare.scopes:update()
|
|
||||||
cmp.config.compare.locality:update()
|
|
||||||
end)
|
|
||||||
|
|
||||||
cmp.event:on('complete_done', function(evt)
|
cmp.event:on('complete_done', function(evt)
|
||||||
if evt.entry then
|
if evt.entry then
|
||||||
|
|||||||
@@ -66,9 +66,15 @@ end
|
|||||||
--
|
--
|
||||||
-- `candlesingle` -> candle#accept#single
|
-- `candlesingle` -> candle#accept#single
|
||||||
-- ^^^^^^~~~~~~ ^^^^^^ ~~~~~~
|
-- ^^^^^^~~~~~~ ^^^^^^ ~~~~~~
|
||||||
--
|
|
||||||
-- * The `accept`'s `a` should not match to `candle`'s `a`
|
-- * The `accept`'s `a` should not match to `candle`'s `a`
|
||||||
--
|
--
|
||||||
|
-- 7. Avoid false positive matching
|
||||||
|
--
|
||||||
|
-- `,` -> print,
|
||||||
|
-- ~
|
||||||
|
-- * Typically, the middle match with symbol characters only is false positive. should be ignored.
|
||||||
|
--
|
||||||
|
--
|
||||||
---Match entry
|
---Match entry
|
||||||
---@param input string
|
---@param input string
|
||||||
---@param word string
|
---@param word string
|
||||||
@@ -100,12 +106,14 @@ matcher.match = function(input, word, option)
|
|||||||
local input_end_index = 1
|
local input_end_index = 1
|
||||||
local word_index = 1
|
local word_index = 1
|
||||||
local word_bound_index = 1
|
local word_bound_index = 1
|
||||||
|
local no_symbol_match = false
|
||||||
while input_end_index <= #input and word_index <= #word do
|
while input_end_index <= #input and word_index <= #word do
|
||||||
local m = matcher.find_match_region(input, input_start_index, input_end_index, word, word_index)
|
local m = matcher.find_match_region(input, input_start_index, input_end_index, word, word_index)
|
||||||
if m and input_end_index <= m.input_match_end then
|
if m and input_end_index <= m.input_match_end then
|
||||||
m.index = word_bound_index
|
m.index = word_bound_index
|
||||||
input_start_index = m.input_match_start + 1
|
input_start_index = m.input_match_start + 1
|
||||||
input_end_index = m.input_match_end + 1
|
input_end_index = m.input_match_end + 1
|
||||||
|
no_symbol_match = no_symbol_match or m.no_symbol_match
|
||||||
word_index = char.get_next_semantic_index(word, m.word_match_end)
|
word_index = char.get_next_semantic_index(word, m.word_match_end)
|
||||||
table.insert(matches, m)
|
table.insert(matches, m)
|
||||||
else
|
else
|
||||||
@@ -146,6 +154,10 @@ matcher.match = function(input, word, option)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if no_symbol_match and not prefix then
|
||||||
|
return 0, {}
|
||||||
|
end
|
||||||
|
|
||||||
-- Compute prefix match score
|
-- Compute prefix match score
|
||||||
local score = prefix and matcher.PREFIX_FACTOR or 0
|
local score = prefix and matcher.PREFIX_FACTOR or 0
|
||||||
local offset = prefix and matches[1].index - 1 or 0
|
local offset = prefix and matches[1].index - 1 or 0
|
||||||
@@ -260,6 +272,7 @@ matcher.find_match_region = function(input, input_start_index, input_end_index,
|
|||||||
local word_offset = 0
|
local word_offset = 0
|
||||||
local strict_count = 0
|
local strict_count = 0
|
||||||
local match_count = 0
|
local match_count = 0
|
||||||
|
local no_symbol_match = false
|
||||||
while input_index <= #input and word_index + word_offset <= #word do
|
while input_index <= #input and word_index + word_offset <= #word do
|
||||||
local c1 = string.byte(input, input_index)
|
local c1 = string.byte(input, input_index)
|
||||||
local c2 = string.byte(word, word_index + word_offset)
|
local c2 = string.byte(word, word_index + word_offset)
|
||||||
@@ -272,6 +285,7 @@ matcher.find_match_region = function(input, input_start_index, input_end_index,
|
|||||||
strict_count = strict_count + (c1 == c2 and 1 or 0)
|
strict_count = strict_count + (c1 == c2 and 1 or 0)
|
||||||
match_count = match_count + 1
|
match_count = match_count + 1
|
||||||
word_offset = word_offset + 1
|
word_offset = word_offset + 1
|
||||||
|
no_symbol_match = no_symbol_match or char.is_symbol(c1)
|
||||||
else
|
else
|
||||||
-- Match end (partial region)
|
-- Match end (partial region)
|
||||||
if input_match_start ~= -1 then
|
if input_match_start ~= -1 then
|
||||||
@@ -281,6 +295,7 @@ matcher.find_match_region = function(input, input_start_index, input_end_index,
|
|||||||
word_match_start = word_index,
|
word_match_start = word_index,
|
||||||
word_match_end = word_index + word_offset - 1,
|
word_match_end = word_index + word_offset - 1,
|
||||||
strict_ratio = strict_count / match_count,
|
strict_ratio = strict_count / match_count,
|
||||||
|
no_symbol_match = no_symbol_match,
|
||||||
fuzzy = false,
|
fuzzy = false,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -298,6 +313,7 @@ matcher.find_match_region = function(input, input_start_index, input_end_index,
|
|||||||
word_match_start = word_index,
|
word_match_start = word_index,
|
||||||
word_match_end = word_index + word_offset - 1,
|
word_match_end = word_index + word_offset - 1,
|
||||||
strict_ratio = strict_count / match_count,
|
strict_ratio = strict_count / match_count,
|
||||||
|
no_symbol_match = no_symbol_match,
|
||||||
fuzzy = false,
|
fuzzy = false,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ describe('matcher', function()
|
|||||||
assert.is.truthy(matcher.match('my_', 'my_awesome_variable') > matcher.match('my_', 'completion_matching_strategy_list'))
|
assert.is.truthy(matcher.match('my_', 'my_awesome_variable') > matcher.match('my_', 'completion_matching_strategy_list'))
|
||||||
assert.is.truthy(matcher.match('2', '[[2021') >= 1)
|
assert.is.truthy(matcher.match('2', '[[2021') >= 1)
|
||||||
|
|
||||||
|
assert.is.truthy(matcher.match(',', 'pri,') == 0)
|
||||||
|
assert.is.truthy(matcher.match('/', '/**') >= 1)
|
||||||
|
|
||||||
assert.is.truthy(matcher.match('true', 'v:true', { synonyms = { 'true' } }) == matcher.match('true', 'true'))
|
assert.is.truthy(matcher.match('true', 'v:true', { synonyms = { 'true' } }) == matcher.match('true', 'true'))
|
||||||
assert.is.truthy(matcher.match('g', 'get', { synonyms = { 'get' } }) > matcher.match('g', 'dein#get', { 'dein#get' }))
|
assert.is.truthy(matcher.match('g', 'get', { synonyms = { 'get' } }) > matcher.match('g', 'dein#get', { 'dein#get' }))
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
local feedkeys = require('cmp.utils.feedkeys')
|
||||||
|
|
||||||
local async = {}
|
local async = {}
|
||||||
|
|
||||||
---@class cmp.AsyncThrottle
|
---@class cmp.AsyncThrottle
|
||||||
@@ -109,4 +111,19 @@ async.sync = function(runner, timeout)
|
|||||||
end, 10, false)
|
end, 10, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Wait and callback for next safe state.
|
||||||
|
async.debounce_safe_state = function(callback)
|
||||||
|
local running = false
|
||||||
|
return function()
|
||||||
|
if running then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
running = true
|
||||||
|
feedkeys.call('', 'n', function()
|
||||||
|
running = false
|
||||||
|
callback()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return async
|
return async
|
||||||
|
|||||||
@@ -2,16 +2,33 @@ local debug = require('cmp.utils.debug')
|
|||||||
|
|
||||||
local autocmd = {}
|
local autocmd = {}
|
||||||
|
|
||||||
|
autocmd.group = vim.api.nvim_create_augroup('___cmp___', { clear = true })
|
||||||
|
|
||||||
autocmd.events = {}
|
autocmd.events = {}
|
||||||
|
|
||||||
---Subscribe autocmd
|
---Subscribe autocmd
|
||||||
---@param event string
|
---@param events string|string[]
|
||||||
---@param callback function
|
---@param callback function
|
||||||
---@return function
|
---@return function
|
||||||
autocmd.subscribe = function(event, callback)
|
autocmd.subscribe = function(events, callback)
|
||||||
autocmd.events[event] = autocmd.events[event] or {}
|
events = type(events) == 'string' and { events } or events
|
||||||
|
|
||||||
|
for _, event in ipairs(events) do
|
||||||
|
if not autocmd.events[event] then
|
||||||
|
autocmd.events[event] = {}
|
||||||
|
vim.api.nvim_create_autocmd(event, {
|
||||||
|
desc = ('nvim-cmp: autocmd: %s'):format(event),
|
||||||
|
group = autocmd.group,
|
||||||
|
callback = function()
|
||||||
|
autocmd.emit(event)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
table.insert(autocmd.events[event], callback)
|
table.insert(autocmd.events[event], callback)
|
||||||
|
end
|
||||||
|
|
||||||
return function()
|
return function()
|
||||||
|
for _, event in ipairs(events) do
|
||||||
for i, callback_ in ipairs(autocmd.events[event]) do
|
for i, callback_ in ipairs(autocmd.events[event]) do
|
||||||
if callback_ == callback then
|
if callback_ == callback then
|
||||||
table.remove(autocmd.events[event], i)
|
table.remove(autocmd.events[event], i)
|
||||||
@@ -20,6 +37,7 @@ autocmd.subscribe = function(event, callback)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---Emit autocmd
|
---Emit autocmd
|
||||||
---@param event string
|
---@param event string
|
||||||
|
|||||||
@@ -7,22 +7,18 @@ feedkeys.call = setmetatable({
|
|||||||
callbacks = {},
|
callbacks = {},
|
||||||
}, {
|
}, {
|
||||||
__call = function(self, keys, mode, callback)
|
__call = function(self, keys, mode, callback)
|
||||||
if vim.fn.reg_recording() ~= '' then
|
|
||||||
return feedkeys.call_macro(keys, mode, callback)
|
|
||||||
end
|
|
||||||
|
|
||||||
local is_insert = string.match(mode, 'i') ~= nil
|
local is_insert = string.match(mode, 'i') ~= nil
|
||||||
local is_immediate = string.match(mode, 'x') ~= nil
|
local is_immediate = string.match(mode, 'x') ~= nil
|
||||||
|
|
||||||
local queue = {}
|
local queue = {}
|
||||||
if #keys > 0 then
|
if #keys > 0 then
|
||||||
table.insert(queue, { keymap.t('<Cmd>set lazyredraw<CR>'), 'n' })
|
table.insert(queue, { keymap.t('<Cmd>setlocal lazyredraw<CR>'), 'n' })
|
||||||
table.insert(queue, { keymap.t('<Cmd>set textwidth=0<CR>'), 'n' })
|
table.insert(queue, { keymap.t('<Cmd>setlocal textwidth=0<CR>'), 'n' })
|
||||||
table.insert(queue, { keymap.t('<Cmd>set eventignore=all<CR>'), 'n' })
|
table.insert(queue, { keymap.t('<Cmd>setlocal backspace=2<CR>'), 'n' })
|
||||||
table.insert(queue, { keys, string.gsub(mode, '[itx]', ''), true })
|
table.insert(queue, { keys, string.gsub(mode, '[itx]', ''), true })
|
||||||
table.insert(queue, { keymap.t('<Cmd>set %slazyredraw<CR>'):format(vim.o.lazyredraw and '' or 'no'), 'n' })
|
table.insert(queue, { keymap.t('<Cmd>setlocal %slazyredraw<CR>'):format(vim.o.lazyredraw and '' or 'no'), 'n' })
|
||||||
table.insert(queue, { keymap.t('<Cmd>set textwidth=%s<CR>'):format(vim.bo.textwidth or 0), 'n' })
|
table.insert(queue, { keymap.t('<Cmd>setlocal textwidth=%s<CR>'):format(vim.bo.textwidth or 0), 'n' })
|
||||||
table.insert(queue, { keymap.t('<Cmd>set eventignore=%s<CR>'):format(vim.o.eventignore or ''), 'n' })
|
table.insert(queue, { keymap.t('<Cmd>setlocal backspace=%s<CR>'):format(vim.go.backspace or 2), 'n' })
|
||||||
end
|
end
|
||||||
|
|
||||||
if callback then
|
if callback then
|
||||||
@@ -54,57 +50,4 @@ misc.set(_G, { 'cmp', 'utils', 'feedkeys', 'call', 'run' }, function(id)
|
|||||||
return ''
|
return ''
|
||||||
end)
|
end)
|
||||||
|
|
||||||
feedkeys.call_macro = setmetatable({
|
|
||||||
queue = {},
|
|
||||||
current = nil,
|
|
||||||
timer = vim.loop.new_timer(),
|
|
||||||
running = false,
|
|
||||||
}, {
|
|
||||||
__call = function(self, keys, mode, callback)
|
|
||||||
local is_insert = string.match(mode, 'i') ~= nil
|
|
||||||
table.insert(self.queue, is_insert and 1 or #self.queue + 1, {
|
|
||||||
keys = keys,
|
|
||||||
mode = mode,
|
|
||||||
callback = callback,
|
|
||||||
})
|
|
||||||
|
|
||||||
if not self.running then
|
|
||||||
self.running = true
|
|
||||||
local consume
|
|
||||||
consume = vim.schedule_wrap(function()
|
|
||||||
if vim.fn.getchar(1) == 0 then
|
|
||||||
if self.current then
|
|
||||||
vim.cmd(('set backspace=%s'):format(self.current.backspace or ''))
|
|
||||||
vim.cmd(('set eventignore=%s'):format(self.current.eventignore or ''))
|
|
||||||
if self.current.callback then
|
|
||||||
self.current.callback()
|
|
||||||
end
|
|
||||||
self.current = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local current = table.remove(self.queue, 1)
|
|
||||||
if current then
|
|
||||||
self.current = {
|
|
||||||
keys = current.keys,
|
|
||||||
callback = current.callback,
|
|
||||||
backspace = vim.o.backspace,
|
|
||||||
eventignore = vim.o.eventignore,
|
|
||||||
}
|
|
||||||
vim.api.nvim_feedkeys(keymap.t('<Cmd>set backspace=start<CR>'), 'n', true)
|
|
||||||
vim.api.nvim_feedkeys(keymap.t('<Cmd>set eventignore=all<CR>'), 'n', true)
|
|
||||||
vim.api.nvim_feedkeys(current.keys, string.gsub(current.mode, '[i]', ''), true) -- 'i' flag is manually resolved.
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if #self.queue ~= 0 or self.current then
|
|
||||||
vim.defer_fn(consume, 1)
|
|
||||||
else
|
|
||||||
self.running = false
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
vim.defer_fn(consume, 1)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
return feedkeys
|
return feedkeys
|
||||||
|
|||||||
@@ -23,6 +23,15 @@ describe('feedkeys', function()
|
|||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('bacckspace', function()
|
||||||
|
vim.cmd([[setlocal backspace=0]])
|
||||||
|
feedkeys.call(keymap.t('iaiueo'), 'nx')
|
||||||
|
feedkeys.call(keymap.t('a<BS><BS>'), 'nx')
|
||||||
|
assert.are.same(vim.api.nvim_buf_get_lines(0, 0, -1, false), {
|
||||||
|
'aiu',
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
it('testability', function()
|
it('testability', function()
|
||||||
feedkeys.call('i', 'n', function()
|
feedkeys.call('i', 'n', function()
|
||||||
feedkeys.call('', 'n', function()
|
feedkeys.call('', 'n', function()
|
||||||
|
|||||||
@@ -1,46 +1,30 @@
|
|||||||
local highlight = {}
|
local highlight = {}
|
||||||
|
|
||||||
highlight.keys = {
|
highlight.keys = {
|
||||||
'gui',
|
'fg',
|
||||||
'guifg',
|
'bg',
|
||||||
'guibg',
|
'bold',
|
||||||
'cterm',
|
'italic',
|
||||||
'ctermfg',
|
'reverse',
|
||||||
'ctermbg',
|
'standout',
|
||||||
|
'underline',
|
||||||
|
'undercurl',
|
||||||
|
'strikethrough',
|
||||||
}
|
}
|
||||||
|
|
||||||
highlight.inherit = function(name, source, override)
|
highlight.inherit = function(name, source, settings)
|
||||||
local cmd = ('highlight default %s'):format(name)
|
|
||||||
for _, key in ipairs(highlight.keys) do
|
for _, key in ipairs(highlight.keys) do
|
||||||
if override[key] then
|
if not settings[key] then
|
||||||
cmd = cmd .. (' %s=%s'):format(key, override[key])
|
local v = vim.fn.synIDattr(vim.fn.hlID(source), key)
|
||||||
else
|
if key ~= 'fg' and key ~= 'bg' then
|
||||||
local v = highlight.get(source, key)
|
v = v == 1
|
||||||
v = v == '' and 'NONE' or v
|
end
|
||||||
cmd = cmd .. (' %s=%s'):format(key, v)
|
if v then
|
||||||
|
settings[key] = v == '' and 'NONE' or v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
vim.cmd(cmd)
|
|
||||||
end
|
|
||||||
|
|
||||||
highlight.get = function(source, key)
|
|
||||||
if key == 'gui' or key == 'cterm' then
|
|
||||||
local ui = {}
|
|
||||||
for _, k in ipairs({ 'bold', 'italic', 'reverse', 'inverse', 'standout', 'underline', 'undercurl', 'strikethrough' }) do
|
|
||||||
if vim.fn.synIDattr(vim.fn.hlID(source), k, key) == 1 then
|
|
||||||
table.insert(ui, k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return table.concat(ui, ',')
|
|
||||||
elseif key == 'guifg' then
|
|
||||||
return vim.fn.synIDattr(vim.fn.hlID(source), 'fg#', 'gui')
|
|
||||||
elseif key == 'guibg' then
|
|
||||||
return vim.fn.synIDattr(vim.fn.hlID(source), 'bg#', 'gui')
|
|
||||||
elseif key == 'ctermfg' then
|
|
||||||
return vim.fn.synIDattr(vim.fn.hlID(source), 'fg', 'term')
|
|
||||||
elseif key == 'ctermbg' then
|
|
||||||
return vim.fn.synIDattr(vim.fn.hlID(source), 'bg', 'term')
|
|
||||||
end
|
end
|
||||||
|
vim.api.nvim_set_hl(0, name, settings)
|
||||||
end
|
end
|
||||||
|
|
||||||
return highlight
|
return highlight
|
||||||
|
|||||||
128
plugin/cmp.lua
128
plugin/cmp.lua
@@ -3,126 +3,54 @@ if vim.g.loaded_cmp then
|
|||||||
end
|
end
|
||||||
vim.g.loaded_cmp = true
|
vim.g.loaded_cmp = true
|
||||||
|
|
||||||
local api = require "cmp.utils.api"
|
local api = require('cmp.utils.api')
|
||||||
local misc = require('cmp.utils.misc')
|
|
||||||
local types = require('cmp.types')
|
local types = require('cmp.types')
|
||||||
local config = require('cmp.config')
|
|
||||||
local highlight = require('cmp.utils.highlight')
|
local highlight = require('cmp.utils.highlight')
|
||||||
|
local autocmd = require('cmp.utils.autocmd')
|
||||||
|
|
||||||
-- TODO: https://github.com/neovim/neovim/pull/14661
|
vim.api.nvim_set_hl(0, 'CmpItemAbbr', { link = 'CmpItemAbbrDefault', default = true })
|
||||||
vim.cmd [[
|
vim.api.nvim_set_hl(0, 'CmpItemAbbrDeprecated', { link = 'CmpItemAbbrDeprecatedDefault', default = true })
|
||||||
augroup ___cmp___
|
vim.api.nvim_set_hl(0, 'CmpItemAbbrMatch', { link = 'CmpItemAbbrMatchDefault', default = true })
|
||||||
autocmd!
|
vim.api.nvim_set_hl(0, 'CmpItemAbbrMatchFuzzy', { link = 'CmpItemAbbrMatchFuzzyDefault', default = true })
|
||||||
autocmd InsertEnter * lua require'cmp.utils.autocmd'.emit('InsertEnter')
|
vim.api.nvim_set_hl(0, 'CmpItemKind', { link = 'CmpItemKindDefault', default = true })
|
||||||
autocmd InsertLeave * lua require'cmp.utils.autocmd'.emit('InsertLeave')
|
vim.api.nvim_set_hl(0, 'CmpItemMenu', { link = 'CmpItemMenuDefault', default = true })
|
||||||
autocmd TextChangedI,TextChangedP * lua require'cmp.utils.autocmd'.emit('TextChanged')
|
for kind in pairs(types.lsp.CompletionItemKind) do
|
||||||
autocmd CursorMovedI * lua require'cmp.utils.autocmd'.emit('CursorMoved')
|
if type(kind) == 'string' then
|
||||||
autocmd CompleteChanged * lua require'cmp.utils.autocmd'.emit('CompleteChanged')
|
local name = ('CmpItemKind%s'):format(kind)
|
||||||
autocmd CompleteDone * lua require'cmp.utils.autocmd'.emit('CompleteDone')
|
vim.api.nvim_set_hl(0, name, { link = ('%sDefault'):format(name), default = true })
|
||||||
autocmd ColorScheme * call v:lua.cmp.plugin.colorscheme()
|
end
|
||||||
autocmd CmdlineEnter * call v:lua.cmp.plugin.cmdline.enter()
|
end
|
||||||
autocmd CmdwinEnter * call v:lua.cmp.plugin.cmdline.leave() " for entering cmdwin with `<C-f>`
|
|
||||||
augroup END
|
|
||||||
]]
|
|
||||||
|
|
||||||
misc.set(_G, { 'cmp', 'plugin', 'cmdline', 'enter' }, function()
|
autocmd.subscribe('ColorScheme', function()
|
||||||
if config.is_native_menu() then
|
highlight.inherit('CmpItemAbbrDefault', 'Pmenu', { bg = 'NONE', default = true })
|
||||||
return
|
highlight.inherit('CmpItemAbbrDeprecatedDefault', 'Comment', { bg = 'NONE', default = true })
|
||||||
end
|
highlight.inherit('CmpItemAbbrMatchDefault', 'Pmenu', { bg = 'NONE', default = true })
|
||||||
if vim.fn.expand('<afile>') ~= '=' then
|
highlight.inherit('CmpItemAbbrMatchFuzzyDefault', 'Pmenu', { bg = 'NONE', default = true })
|
||||||
vim.schedule(function()
|
highlight.inherit('CmpItemKindDefault', 'Special', { bg = 'NONE', default = true })
|
||||||
if api.is_cmdline_mode() then
|
highlight.inherit('CmpItemMenuDefault', 'Pmenu', { bg = 'NONE', default = true })
|
||||||
vim.cmd [[
|
|
||||||
augroup cmp-cmdline
|
|
||||||
autocmd!
|
|
||||||
autocmd CmdlineChanged * lua require'cmp.utils.autocmd'.emit('TextChanged')
|
|
||||||
autocmd CmdlineLeave * call v:lua.cmp.plugin.cmdline.leave()
|
|
||||||
augroup END
|
|
||||||
]]
|
|
||||||
require('cmp.utils.autocmd').emit('CmdlineEnter')
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
misc.set(_G, { 'cmp', 'plugin', 'cmdline', 'leave' }, function()
|
|
||||||
if vim.fn.expand('<afile>') ~= '=' then
|
|
||||||
vim.cmd [[
|
|
||||||
augroup cmp-cmdline
|
|
||||||
autocmd!
|
|
||||||
augroup END
|
|
||||||
]]
|
|
||||||
require('cmp.utils.autocmd').emit('CmdlineLeave')
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
misc.set(_G, { 'cmp', 'plugin', 'colorscheme' }, function()
|
|
||||||
highlight.inherit('CmpItemAbbrDefault', 'Pmenu', {
|
|
||||||
guibg = 'NONE',
|
|
||||||
ctermbg = 'NONE',
|
|
||||||
})
|
|
||||||
highlight.inherit('CmpItemAbbrDeprecatedDefault', 'Comment', {
|
|
||||||
gui = 'NONE',
|
|
||||||
guibg = 'NONE',
|
|
||||||
ctermbg = 'NONE',
|
|
||||||
})
|
|
||||||
highlight.inherit('CmpItemAbbrMatchDefault', 'Pmenu', {
|
|
||||||
gui = 'NONE',
|
|
||||||
guibg = 'NONE',
|
|
||||||
ctermbg = 'NONE',
|
|
||||||
})
|
|
||||||
highlight.inherit('CmpItemAbbrMatchFuzzyDefault', 'Pmenu', {
|
|
||||||
gui = 'NONE',
|
|
||||||
guibg = 'NONE',
|
|
||||||
ctermbg = 'NONE',
|
|
||||||
})
|
|
||||||
highlight.inherit('CmpItemKindDefault', 'Special', {
|
|
||||||
guibg = 'NONE',
|
|
||||||
ctermbg = 'NONE',
|
|
||||||
})
|
|
||||||
highlight.inherit('CmpItemMenuDefault', 'Pmenu', {
|
|
||||||
guibg = 'NONE',
|
|
||||||
ctermbg = 'NONE',
|
|
||||||
})
|
|
||||||
for name in pairs(types.lsp.CompletionItemKind) do
|
for name in pairs(types.lsp.CompletionItemKind) do
|
||||||
if type(name) == 'string' then
|
if type(name) == 'string' then
|
||||||
vim.cmd(([[highlight default link CmpItemKind%sDefault CmpItemKind]]):format(name))
|
vim.api.nvim_set_hl(0, ('CmpItemKind%sDefault'):format(name), { link = 'CmpItemKind', default = true })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
_G.cmp.plugin.colorscheme()
|
autocmd.emit('ColorScheme')
|
||||||
|
|
||||||
vim.cmd [[
|
|
||||||
highlight default link CmpItemAbbr CmpItemAbbrDefault
|
|
||||||
highlight default link CmpItemAbbrDeprecated CmpItemAbbrDeprecatedDefault
|
|
||||||
highlight default link CmpItemAbbrMatch CmpItemAbbrMatchDefault
|
|
||||||
highlight default link CmpItemAbbrMatchFuzzy CmpItemAbbrMatchFuzzyDefault
|
|
||||||
highlight default link CmpItemKind CmpItemKindDefault
|
|
||||||
highlight default link CmpItemMenu CmpItemMenuDefault
|
|
||||||
]]
|
|
||||||
|
|
||||||
for name in pairs(types.lsp.CompletionItemKind) do
|
|
||||||
if type(name) == 'string' then
|
|
||||||
local hi = ('CmpItemKind%s'):format(name)
|
|
||||||
if vim.fn.hlexists(hi) ~= 1 then
|
|
||||||
vim.cmd(([[highlight default link %s %sDefault]]):format(hi, hi))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if vim.on_key then
|
if vim.on_key then
|
||||||
vim.on_key(function(keys)
|
vim.on_key(function(keys)
|
||||||
if keys == vim.api.nvim_replace_termcodes('<C-c>', true, true, true) then
|
if keys == vim.api.nvim_replace_termcodes('<C-c>', true, true, true) then
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
if not api.is_suitable_mode() then
|
if not api.is_suitable_mode() then
|
||||||
require('cmp.utils.autocmd').emit('InsertLeave')
|
autocmd.emit('InsertLeave')
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end, vim.api.nvim_create_namespace('cmp.plugin'))
|
end, vim.api.nvim_create_namespace('cmp.plugin'))
|
||||||
end
|
end
|
||||||
|
|
||||||
vim.cmd [[command! CmpStatus lua require('cmp').status()]]
|
vim.api.nvim_create_user_command('CmpStatus', function()
|
||||||
|
require('cmp').status()
|
||||||
|
end, { desc = 'Check status of cmp sources' })
|
||||||
|
|
||||||
vim.cmd [[doautocmd <nomodeline> User CmpReady]]
|
vim.cmd([[doautocmd <nomodeline> User CmpReady]])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user