Skip to content

Commit

Permalink
feat: output preview with ghost text, including for snippets (#186)
Browse files Browse the repository at this point in the history
* feat: show output preview with ghost-text

* feat: handle ghost text in the middle of line

* fix: buffer text being covered by ghost text

* feat: ghost text preview supports snippets

* feat: add highlight link for ghost text preview

* feat: add option to enable/disable ghost text preview

* refactor: rename ghost-text-preview to ghost-text

* feat: add default to ghost text config and update readme

* refactor: use text-edits libs textEdit item

* refactor: listen to autocomplete on_select to decide when to show ghost text

* feat: use smarter way to get ghost text result

* chore: remove previously added line break
  • Loading branch information
giuxtaposition authored Oct 25, 2024
1 parent 70438ac commit 6d25187
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ MiniDeps.add({
border = 'padded',
winhighlight = 'Normal:BlinkCmpSignatureHelp,FloatBorder:BlinkCmpSignatureHelpBorder',
},
ghost_text = {
enabled = false,
},
},

highlight = {
Expand Down
7 changes: 7 additions & 0 deletions lua/blink/cmp/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
--- @field autocomplete? blink.cmp.AutocompleteConfig
--- @field documentation? blink.cmp.DocumentationConfig
--- @field signature_help? blink.cmp.SignatureHelpConfig
--- @field ghost_text? GhostTextConfig

--- @class blink.cmp.HighlightConfig
--- @field ns? number
Expand Down Expand Up @@ -137,6 +138,9 @@
--- @field border? blink.cmp.WindowBorder
--- @field winhighlight? string

--- @class GhostTextConfig
--- @field enabled? boolean

--- @class blink.cmp.Config
--- @field keymap? blink.cmp.KeymapConfig
--- @field accept? blink.cmp.AcceptConfig
Expand Down Expand Up @@ -340,6 +344,9 @@ local config = {
border = 'padded',
winhighlight = 'Normal:BlinkCmpSignatureHelp,FloatBorder:BlinkCmpSignatureHelpBorder',
},
ghost_text = {
enabled = false,
},
},

highlight = {
Expand Down
3 changes: 3 additions & 0 deletions lua/blink/cmp/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cmp.setup = function(opts)
cmp.windows = {
autocomplete = require('blink.cmp.windows.autocomplete').setup(),
documentation = require('blink.cmp.windows.documentation').setup(),
ghost_text = require('blink.cmp.windows.ghost-text').setup(),
}

cmp.trigger.listen_on_show(function(context) cmp.sources.request_completions(context) end)
Expand Down Expand Up @@ -99,6 +100,8 @@ cmp.add_default_highlights = function()
set_hl('BlinkCmpKind' .. kind, { link = use_nvim_cmp and 'CmpItemKind' .. kind or 'BlinkCmpKind' })
end

set_hl('BlinkCmpGhostText', { link = use_nvim_cmp and 'CmpGhostText' or 'Comment' })

set_hl('BlinkCmpMenu', { link = 'Pmenu' })
set_hl('BlinkCmpMenuBorder', { link = 'Pmenu' })
set_hl('BlinkCmpMenuSelection', { link = 'PmenuSel' })
Expand Down
66 changes: 66 additions & 0 deletions lua/blink/cmp/windows/ghost-text.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
local config = require('blink.cmp.config')
local autocomplete = require('blink.cmp.windows.autocomplete')

local ghost_text_config = config.windows.ghost_text

local ghost_text = {
enabled = ghost_text_config and ghost_text_config.enabled,
extmark_id = 1,
ns_id = config.highlight.ns,
}

function ghost_text.setup()
autocomplete.listen_on_select(function(item, context)
if ghost_text.enabled ~= true then return end
ghost_text.show_preview(item)
end)
autocomplete.listen_on_close(function() ghost_text.clear_preview() end)

return ghost_text
end

--- @param textEdit lsp.TextEdit
local function get_still_untyped_text(textEdit)
local type_text_length = textEdit.range['end'].character - textEdit.range.start.character
local result = textEdit.newText:sub(type_text_length + 1)
return result
end

--- @param selected_item? blink.cmp.CompletionItem
function ghost_text.show_preview(selected_item)
if selected_item == nil then return end
local text_edits_lib = require('blink.cmp.accept.text-edits')
local text_edit = text_edits_lib.get_from_item(selected_item)

if selected_item.insertTextFormat == vim.lsp.protocol.InsertTextFormat.Snippet then
local expanded_snippet = require('blink.cmp.sources.snippets.utils').safe_parse(text_edit.newText)
text_edit.newText = expanded_snippet and tostring(expanded_snippet) or text_edit.newText
end

local display_lines = vim.split(get_still_untyped_text(text_edit), '\n', { plain = true }) or {}

--- @type vim.api.keyset.set_extmark
local extmark = {
id = ghost_text.extmark_id,
virt_text_pos = 'inline',
virt_text = { { display_lines[1], 'BlinkCmpGhostText' } },
hl_mode = 'combine',
}

if #display_lines > 1 then
extmark.virt_lines = {}
for i = 2, #display_lines do
extmark.virt_lines[i - 1] = { { display_lines[i], 'BlinkCmpGhostText' } }
end
end

local cursor_pos = {
text_edit.range.start.line,
text_edit.range['end'].character,
}
vim.api.nvim_buf_set_extmark(0, ghost_text.ns_id, cursor_pos[1], cursor_pos[2], extmark)
end

function ghost_text.clear_preview() vim.api.nvim_buf_del_extmark(0, ghost_text.ns_id, ghost_text.extmark_id) end

return ghost_text

0 comments on commit 6d25187

Please sign in to comment.