From 9734453d77d87dc6aa4be32091edddb81438d5d4 Mon Sep 17 00:00:00 2001 From: Javier Lopez Date: Thu, 4 Nov 2021 21:49:42 -0500 Subject: [PATCH] fix(ghost_text): generate it using chars instead of bytes (#471) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously if the completion entry text had a multibyte character the ghostly text renderd improperly, for example: The cursor position is "|" 1. In this case the ghost text was spliting a multibyte character. entry: comunicación prev: comunicacio|n now: comunicacio|n 2. In this case the multibyte character was before meking the index wrong, therefore presenting an extra character of the entry as ghost text. entry: árbol prev: arbol|l now: arbol| With this changes the calculation for the bytes to show is done based on characters avoiding both of the issues above. --- lua/cmp/view/ghost_text_view.lua | 38 ++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/lua/cmp/view/ghost_text_view.lua b/lua/cmp/view/ghost_text_view.lua index d12239f..ed92363 100644 --- a/lua/cmp/view/ghost_text_view.lua +++ b/lua/cmp/view/ghost_text_view.lua @@ -26,19 +26,15 @@ ghost_text_view.new = function() return end - local cursor = vim.api.nvim_win_get_cursor(0) - if string.sub(vim.api.nvim_get_current_line(), cursor[2] + 1) ~= '' then + local row, col = unpack(vim.api.nvim_win_get_cursor(0)) + local line = vim.api.nvim_get_current_line() + if string.sub(line, col + 1) ~= '' then return end - local diff = 1 + cursor[2] - self.entry:get_offset() - local text = self.entry:get_insert_text() - if self.entry.completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet then - text = vim.lsp.util.parse_snippet(text) - end - text = string.sub(str.oneline(text), diff + 1) + local text = self.text_gen(self, line, col) if #text > 0 then - vim.api.nvim_buf_set_extmark(0, ghost_text_view.ns, cursor[1] - 1, cursor[2], { + vim.api.nvim_buf_set_extmark(0, ghost_text_view.ns, row - 1, col, { right_gravity = false, virt_text = { { text, c.hl_group or 'Comment' } }, virt_text_pos = 'overlay', @@ -51,6 +47,30 @@ ghost_text_view.new = function() return self end +---Generate the ghost text +--- This function calculates the bytes of the entry to display calculating the number +--- of character differences instead of just byte difference. +ghost_text_view.text_gen = function(self, line, cursor_col) + local word = self.entry:get_insert_text() + if self.entry.completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet then + word = vim.lsp.util.parse_snippet(word) + end + word = str.oneline(word) + local word_clen = vim.str_utfindex(word) + local cword = string.sub(line, self.entry:get_offset(), cursor_col) + local cword_clen = vim.str_utfindex(cword) + -- Number of characters from entry text (word) to be displayed as ghost thext + local nchars = word_clen - cword_clen + -- Missing characters to complete the entry text + local text + if nchars > 0 then + text = string.sub(word, vim.str_byteindex(word, word_clen - nchars) + 1) + else + text = "" + end + return text +end + ---Show ghost text ---@param e cmp.Entry ghost_text_view.show = function(self, e)