diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 8b6a526be9..35c0353fce 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -4136,6 +4136,7 @@ Provides operations to compare, calculate, and convert ranges represented by Fields: ~ • {start} (`vim.Pos`) Start position. • {end_} (`vim.Pos`) End position, exclusive. + • {is_empty} (`fun(self: vim.Range): boolean`) See |Range:is_empty()|. • {has} (`fun(outer: vim.Range, inner: vim.Range): boolean`) See |Range:has()|. • {intersect} (`fun(r1: vim.Range, r2: vim.Range): vim.Range?`) See @@ -4167,6 +4168,12 @@ Range:intersect({r1}, {r2}) *Range:intersect()* (`vim.Range?`) range that is present inside both `r1` and `r2`. `nil` if such range does not exist. See |vim.Range|. +Range:is_empty() *Range:is_empty()* + Checks whether the given range is empty; i.e., start >= end. + + Return: ~ + (`boolean`) `true` if the given range is empty + Range:lsp({buf}, {range}, {position_encoding}) *Range:lsp()* Creates a new |vim.Range| from `lsp.Range`. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 03f3966400..7b2a840505 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -280,6 +280,7 @@ LUA • Experimental `vim.pos` and `vim.range` for Position/Range abstraction. • |vim.json.encode()| has an `indent` option for pretty-formatting. • |vim.json.encode()| has an `sort_keys` option. +• |Range:is_empty()| to check if a |vim.Range| is empty. OPTIONS diff --git a/runtime/lua/vim/lsp/inline_completion.lua b/runtime/lua/vim/lsp/inline_completion.lua index a5e6f4e7d3..aa0ad13e59 100644 --- a/runtime/lua/vim/lsp/inline_completion.lua +++ b/runtime/lua/vim/lsp/inline_completion.lua @@ -248,7 +248,7 @@ function Completor:show(hint) api.nvim_buf_set_extmark(self.bufnr, namespace, row, col, { virt_text = virt_text, virt_lines = virt_lines, - virt_text_pos = current.range and 'overlay' or 'inline', + virt_text_pos = (current.range and not current.range:is_empty() and 'overlay') or 'inline', hl_mode = 'combine', }) end diff --git a/runtime/lua/vim/range.lua b/runtime/lua/vim/range.lua index e76509f060..50f5a795e6 100644 --- a/runtime/lua/vim/range.lua +++ b/runtime/lua/vim/range.lua @@ -99,6 +99,13 @@ function Range.__eq(r1, r2) return r1.start == r2.start and r1.end_ == r2.end_ end +--- Checks whether the given range is empty; i.e., start >= end. +--- +---@return boolean `true` if the given range is empty +function Range:is_empty() + return self.start >= self.end_ +end + --- Checks whether {outer} range contains {inner} range. --- ---@param outer vim.Range diff --git a/test/functional/plugin/lsp/inline_completion_spec.lua b/test/functional/plugin/lsp/inline_completion_spec.lua index 028d0cdf8a..d82410153f 100644 --- a/test/functional/plugin/lsp/inline_completion_spec.lua +++ b/test/functional/plugin/lsp/inline_completion_spec.lua @@ -83,6 +83,27 @@ describe('vim.lsp.inline_completion', function() }, handlers = { ['textDocument/inlineCompletion'] = function(_, _, callback) + if _G.empty then + callback(nil, { + items = { + { + insertText = 'foobar', + range = { + start = { + line = 0, + character = 19, + }, + ['end'] = { + line = 0, + character = 19, + }, + }, + }, + }, + }) + return + end + callback(nil, { items = { { @@ -198,6 +219,19 @@ describe('vim.lsp.inline_completion', function() screen:expect({ grid = grid_applied_candidates }) end) + it('correctly displays with absent/empty range', function() + exec_lua(function() + _G.empty = true + end) + feed('I') + screen:expect([[ + function fibonacci({1:foobar}) | + ^ | + {1:~ }|*11 + {3:-- INSERT --} | + ]]) + end) + it('accepts on_accept callback', function() feed('i') screen:expect({ grid = grid_with_candidates })