|
| 1 | +local config = require('blink.cmp.config') |
| 2 | +local autocomplete = require('blink.cmp.windows.autocomplete') |
| 3 | + |
| 4 | +local ghost_text_config = config.windows.ghost_text |
| 5 | + |
| 6 | +local ghost_text = { |
| 7 | + enabled = ghost_text_config and ghost_text_config.enabled, |
| 8 | + extmark_id = 1, |
| 9 | + ns_id = config.highlight.ns, |
| 10 | +} |
| 11 | + |
| 12 | +function ghost_text.setup() |
| 13 | + autocomplete.listen_on_select(function(item, context) |
| 14 | + if ghost_text.enabled ~= true then return end |
| 15 | + ghost_text.show_preview(item) |
| 16 | + end) |
| 17 | + autocomplete.listen_on_close(function() ghost_text.clear_preview() end) |
| 18 | + |
| 19 | + return ghost_text |
| 20 | +end |
| 21 | + |
| 22 | +--- @param textEdit lsp.TextEdit |
| 23 | +local function get_still_untyped_text(textEdit) |
| 24 | + local type_text_length = textEdit.range['end'].character - textEdit.range.start.character |
| 25 | + local result = textEdit.newText:sub(type_text_length + 1) |
| 26 | + return result |
| 27 | +end |
| 28 | + |
| 29 | +--- @param selected_item? blink.cmp.CompletionItem |
| 30 | +function ghost_text.show_preview(selected_item) |
| 31 | + if selected_item == nil then return end |
| 32 | + local text_edits_lib = require('blink.cmp.accept.text-edits') |
| 33 | + local text_edit = text_edits_lib.get_from_item(selected_item) |
| 34 | + |
| 35 | + if selected_item.insertTextFormat == vim.lsp.protocol.InsertTextFormat.Snippet then |
| 36 | + local expanded_snippet = require('blink.cmp.sources.snippets.utils').safe_parse(text_edit.newText) |
| 37 | + text_edit.newText = expanded_snippet and tostring(expanded_snippet) or text_edit.newText |
| 38 | + end |
| 39 | + |
| 40 | + local display_lines = vim.split(get_still_untyped_text(text_edit), '\n', { plain = true }) or {} |
| 41 | + |
| 42 | + --- @type vim.api.keyset.set_extmark |
| 43 | + local extmark = { |
| 44 | + id = ghost_text.extmark_id, |
| 45 | + virt_text_pos = 'inline', |
| 46 | + virt_text = { { display_lines[1], 'BlinkCmpGhostText' } }, |
| 47 | + hl_mode = 'combine', |
| 48 | + } |
| 49 | + |
| 50 | + if #display_lines > 1 then |
| 51 | + extmark.virt_lines = {} |
| 52 | + for i = 2, #display_lines do |
| 53 | + extmark.virt_lines[i - 1] = { { display_lines[i], 'BlinkCmpGhostText' } } |
| 54 | + end |
| 55 | + end |
| 56 | + |
| 57 | + local cursor_pos = { |
| 58 | + text_edit.range.start.line, |
| 59 | + text_edit.range['end'].character, |
| 60 | + } |
| 61 | + vim.api.nvim_buf_set_extmark(0, ghost_text.ns_id, cursor_pos[1], cursor_pos[2], extmark) |
| 62 | +end |
| 63 | + |
| 64 | +function ghost_text.clear_preview() vim.api.nvim_buf_del_extmark(0, ghost_text.ns_id, ghost_text.extmark_id) end |
| 65 | + |
| 66 | +return ghost_text |
0 commit comments