Experimental: Ghost text (#119)

* Inline suggest experimental

* Fix flicker

* Fix ci fails

* Reduce flicker

* Improve menu functions

* Default false

* README.md

* Add require

* Rename inline_preview to ghost_text
This commit is contained in:
hrsh7th
2021-09-03 18:34:10 +09:00
committed by GitHub
parent 6cc8b82267
commit e867bf233e
5 changed files with 74 additions and 31 deletions

View File

@@ -61,6 +61,10 @@ return function()
end
},
experimental = {
ghost_text = false,
},
sources = {},
}
end

View File

@@ -1,5 +1,6 @@
local debug = require('cmp.utils.debug')
local char = require('cmp.utils.char')
local str = require('cmp.utils.str')
local pattern = require('cmp.utils.pattern')
local async = require('cmp.utils.async')
local keymap = require('cmp.utils.keymap')
@@ -18,6 +19,16 @@ core.SOURCE_TIMEOUT = 500
---Suspending state.
core.suspending = false
core.GHOST_TEXT_NS = vim.api.nvim_create_namespace('cmp:GHOST_TEXT');
vim.api.nvim_set_decoration_provider(core.GHOST_TEXT_NS, {
on_win = function()
if config.get().experimental.ghost_text then
core.ghost_text(core.menu:get_first_entry())
end
end,
})
---@type cmp.Menu
core.menu = menu.new({
on_select = function(e)
@@ -27,6 +38,43 @@ core.menu = menu.new({
end,
})
---Show ghost text if possible
---@param e cmp.Entry
core.ghost_text = function(e)
if not e then
return
end
local ctx = context.new()
if ctx.cursor_after_line ~= '' then
return
end
local diff = ctx.cursor.col - e:get_offset()
local text = e:get_insert_text()
if e.completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet then
text = vim.lsp.util.parse_snippet(text)
end
text = string.sub(str.oneline(text), diff + 1)
if #text > 0 then
vim.api.nvim_buf_set_extmark(
ctx.bufnr,
core.GHOST_TEXT_NS,
ctx.cursor.row - 1,
ctx.cursor.col - 1,
{
right_gravity = true,
virt_text = { { text, 'Comment' } },
virt_text_pos = 'overlay',
virt_text_win_col = ctx.cursor.col - 1,
hl_mode = 'blend',
priority = 0,
ephemeral = true,
}
)
end
end
---@type table<number, cmp.Source>
core.sources = {}

View File

@@ -193,58 +193,39 @@ end
---Geta current active entry
---@return cmp.Entry|nil
menu.get_active_entry = function(self)
local completed_item = vim.v.completed_item or {}
if vim.fn.pumvisible() == 0 or not completed_item.user_data then
if vim.fn.pumvisible() == 0 or not (vim.v.completed_item or {}).user_data then
return nil
end
local id = completed_item.user_data.cmp
if id then
return self.entry_map[id]
end
return nil
return self:get_selected_entry()
end
---Get current selected entry
---@return cmp.Entry|nil
menu.get_selected_entry = function(self)
local e = self:get_active_entry()
if e then
return e
if not self:is_valid_mode() then
return nil
end
local selected = vim.fn.complete_info({ 'selected' }).selected
if selected == -1 then
return nil
end
local items = vim.fn.complete_info({ 'items' }).items
local completed_item = items[math.max(selected, 0) + 1] or {}
if not completed_item.user_data then
return nil
end
local id = completed_item.user_data.cmp
if id then
return self.entry_map[id]
end
return nil
return self.entries[math.max(selected, 0) + 1]
end
---Get first entry
---@param self cmp.Entry|nil
menu.get_first_entry = function(self)
local info = vim.fn.complete_info({ 'items' })
local completed_item = info.items[1] or {}
if not completed_item.user_data then
if not self:is_valid_mode() then
return nil
end
return self.entries[1]
end
local id = completed_item.user_data.cmp
if id then
return self.entry_map[id]
end
return nil
---Return the completion menu is visible or not.
---@return boolean
menu.is_valid_mode = function()
return vim.fn.complete_info({ 'mode' }).mode == 'eval'
end
return menu

View File

@@ -57,6 +57,7 @@ cmp.PreselectMode.None = 'none'
---@field public event cmp.EventConfig
---@field public mapping table<string, fun(core: cmp.Core, fallback: function)>
---@field public sources cmp.SourceConfig[]
---@field public experimental cmp.ExperimentalConfig
---@class cmp.CompletionConfig
---@field public autocomplete cmp.TriggerEvent[]
@@ -88,6 +89,9 @@ cmp.PreselectMode.None = 'none'
---@class cmp.EventConfig
---@field on_confirm_done function(e: cmp.Entry)
---@class cmp.ExperimentalConfig
---@field public ghost_text boolean
---@class cmp.SourceConfig
---@field public name string
---@field public opts table