Skip to content

Commit db3d1ad

Browse files
committed
feat: support editRange, use textEditText when editRange is defined
closes #310
1 parent fb9f374 commit db3d1ad

File tree

4 files changed

+41
-31
lines changed

4 files changed

+41
-31
lines changed

lua/blink/cmp/accept/text-edits.lua

+33-25
Original file line numberDiff line numberDiff line change
@@ -56,46 +56,54 @@ local function get_line_byte_from_position(position, offset_encoding)
5656
end
5757

5858
--- Gets the text edit from an item, handling insert/replace ranges and converts
59-
--- offset encodings (utf-16 | utf-32) to byte offset (equivalent to utf-8)
59+
--- offset encodings (utf-16 | utf-32) to utf-8
6060
--- @param item blink.cmp.CompletionItem
6161
--- @return lsp.TextEdit
6262
function text_edits.get_from_item(item)
63-
-- Adjust the position of the text edit to be the current cursor position
64-
-- since the data might be outdated. We compare the cursor column position
65-
-- from when the items were fetched versus the current.
66-
-- hack: is there a better way?
67-
if item.textEdit ~= nil then
68-
-- FIXME: temporarily convert insertReplaceEdit to regular textEdit
69-
if item.textEdit.insert ~= nil then
70-
item.textEdit.range = item.textEdit.insert
71-
elseif item.textEdit.replace ~= nil then
72-
item.textEdit.range = item.textEdit.replace
73-
end
63+
local text_edit = vim.deepcopy(item.textEdit)
64+
65+
-- Fallback to default edit range if defined, and no text edit was set
66+
if text_edit == nil and item.editRange ~= nil then
67+
text_edit = {
68+
newText = item.textEditText or item.insertText or item.label,
69+
-- FIXME: temporarily convert insertReplaceEdit to regular textEdit
70+
range = item.editRange.insert or item.editRange.replace or item.editRange,
71+
}
72+
end
7473

75-
local text_edit = vim.deepcopy(item.textEdit)
74+
-- Guess the text edit if the item doesn't define it
75+
if text_edit == nil then return text_edits.guess(item) end
7676

77-
local client = vim.lsp.get_client_by_id(item.client_id)
78-
local offset_encoding = client ~= nil and client.offset_encoding or 'utf-8'
77+
-- FIXME: temporarily convert insertReplaceEdit to regular textEdit
78+
text_edit.range = text_edit.range or text_edit.insert or text_edit.replace
79+
text_edit.insert = nil
80+
text_edit.replace = nil
81+
--- @cast text_edit lsp.TextEdit
7982

80-
if offset_encoding ~= 'utf-8' then
81-
text_edit.range.start.character = get_line_byte_from_position(text_edit.range.start, offset_encoding)
82-
text_edit.range['end'].character = get_line_byte_from_position(text_edit.range['end'], offset_encoding)
83-
end
83+
local client = vim.lsp.get_client_by_id(item.client_id)
84+
local offset_encoding = client ~= nil and client.offset_encoding or 'utf-8'
8485

85-
local offset = vim.api.nvim_win_get_cursor(0)[2] - item.cursor_column
86-
text_edit.range['end'].character = text_edit.range['end'].character + offset
87-
return text_edit
86+
-- convert the offset encoding to utf-8 if necessary
87+
if offset_encoding ~= 'utf-8' then
88+
text_edit.range.start.character = get_line_byte_from_position(text_edit.range.start, offset_encoding)
89+
text_edit.range['end'].character = get_line_byte_from_position(text_edit.range['end'], offset_encoding)
8890
end
8991

90-
-- No text edit so we fallback to our own resolution
91-
return text_edits.guess(item)
92+
-- Adjust the position of the text edit to be the current cursor position
93+
-- since the data might be outdated. We compare the cursor column position
94+
-- from when the items were fetched versus the current.
95+
-- HACK: is there a better way?
96+
-- TODO: take into account the offset_encoding
97+
local offset = vim.api.nvim_win_get_cursor(0)[2] - item.cursor_column
98+
text_edit.range['end'].character = text_edit.range['end'].character + offset
99+
return text_edit
92100
end
93101

94102
--- Uses the keyword_regex to guess the text edit ranges
95103
--- @param item blink.cmp.CompletionItem
96104
--- TODO: doesnt work when the item contains characters not included in the context regex
97105
function text_edits.guess(item)
98-
local word = item.textEditText or item.insertText or item.label
106+
local word = item.insertText or item.label
99107

100108
local cmp_config = config.trigger.completion
101109
local range = require('blink.cmp.utils').get_regex_around_cursor(

lua/blink/cmp/sources/lib/utils.lua

+3-2
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ end
5252
--- @return lsp.CompletionItem
5353
function utils.blink_item_to_lsp_item(item)
5454
local lsp_item = vim.deepcopy(item)
55-
lsp_item.cursor_column = nil
5655
lsp_item.score_offset = nil
57-
lsp_item.client_id = nil
5856
lsp_item.source_id = nil
5957
lsp_item.source_name = nil
58+
lsp_item.cursor_column = nil
59+
lsp_item.client_id = nil
60+
lsp_item.editRange = nil
6061
return lsp_item
6162
end
6263

lua/blink/cmp/sources/lsp.lua

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,16 @@ function lsp:get_completions(context, callback)
110110

111111
-- convert full response to our internal format
112112
else
113+
-- add defaults to the items
113114
local defaults = response.result and response.result.itemDefaults or {}
114-
-- TODO: excluding editRange for now
115115
local known_defaults = {
116116
'commitCharacters',
117+
'editRange',
117118
'insertTextFormat',
118119
'insertTextMode',
119120
'data',
120121
}
121122
for _, item in ipairs(response.result.items) do
122-
-- add defaults to the item
123123
for key, value in pairs(defaults) do
124124
if vim.tbl_contains(known_defaults, key) then item[key] = item[key] or value end
125125
end

lua/blink/cmp/types.lua

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
--- @class blink.cmp.CompletionItem : lsp.CompletionItem
2-
--- @field score_offset number | nil
2+
--- @field score_offset? number
33
--- @field source_id string
44
--- @field source_name string
55
--- @field cursor_column number
6-
--- @field client_id number
6+
--- @field client_id? number
7+
--- @field editRange? lsp.Range | { insert: lsp.Range, replace: lsp.Range }
78

89
return {
910
-- some plugins mutate the vim.lsp.protocol.CompletionItemKind table

0 commit comments

Comments
 (0)