@@ -33,30 +33,70 @@ cmp.kind_icons = {
33
33
TypeParameter = ' ' ,
34
34
}
35
35
cmp .filtered_items = {}
36
+ -- the column of the cursor when the items were fetched
37
+ cmp .items_column = - 1
36
38
37
39
cmp .fuzzy = require (' blink.fuzzy' ).fuzzy
38
40
cmp .lsp = require (' blink.cmp.lsp' )
39
41
40
42
cmp .accept = function (cmp_win )
41
- local bufnr = vim .api .nvim_get_current_buf ()
42
- local current_line , start_col , end_col = cmp .get_query_to_replace (bufnr )
43
-
44
43
-- Get the item from the filtered items based on the cursorline position
45
44
local item = cmp .filtered_items [vim .api .nvim_win_get_cursor (cmp_win .id )[1 ]]
45
+ local text_edit = item .item .textEdit
46
+
47
+ if text_edit ~= nil then
48
+ -- Adjust the position of the text edit to be the current cursor position
49
+ -- since the data might be outdated. We compare the cursor column position
50
+ -- from when the items were fetched versus the current.
51
+ -- HACK: need to figure out a better way
52
+ local offset = vim .api .nvim_win_get_cursor (0 )[2 ] - cmp .items_cursor_column
53
+ text_edit .range [' end' ].character = text_edit .range [' end' ].character + offset
54
+
55
+ -- Delete the old text
56
+ vim .api .nvim_buf_set_text (
57
+ vim .api .nvim_get_current_buf (),
58
+ text_edit .range .start .line ,
59
+ text_edit .range .start .character ,
60
+ text_edit .range [' end' ].line ,
61
+ text_edit .range [' end' ].character ,
62
+ {}
63
+ )
46
64
47
- -- Apply text edit
48
- vim .api .nvim_buf_set_text (bufnr , current_line , start_col , current_line , end_col , { item .word })
49
- vim .api .nvim_win_set_cursor (0 , { current_line + 1 , start_col + # item .word })
65
+ -- HACK: some LSPs (typescript-language-server) include snippets in non-snippet
66
+ -- completions because fuck a spec so we expand all text as a snippet
67
+ vim .snippet .expand (text_edit .newText )
68
+
69
+ -- Apply the text edit and move the cursor
70
+ -- cmp.apply_text_edits(item.client_id, { text_edit })
71
+ -- vim.api.nvim_win_set_cursor(
72
+ -- 0,
73
+ -- { text_edit.range.start.line + 1, text_edit.range.start.character + #text_edit.newText }
74
+ -- )
75
+ else
76
+ -- No text edit so we fallback to our own resolution
77
+ -- TODO: LSP provides info on what chars should be replaced in general
78
+ -- and the get_query_to_replace function should take advantage of it
79
+ local current_line , start_col , end_col = cmp .get_query_to_replace (vim .api .nvim_get_current_buf ())
80
+ vim .api .nvim_buf_set_text (
81
+ vim .api .nvim_get_current_buf (),
82
+ current_line ,
83
+ start_col ,
84
+ current_line ,
85
+ end_col ,
86
+ { item .word }
87
+ )
88
+ vim .api .nvim_win_set_cursor (0 , { current_line + 1 , start_col + # item .word })
89
+ end
50
90
51
91
-- Apply additional text edits
52
92
-- LSPs can either include these in the initial response or require a resolve
53
93
-- These are used for things like auto-imports
54
- -- todo : check capabilities to know ahead of time
94
+ -- TODO : check capabilities to know ahead of time
55
95
if item .additionalTextEdits ~= nil then
56
96
cmp .apply_additional_text_edits (item .client_id , item )
57
97
else
58
98
cmp .lsp .resolve (
59
- item ,
99
+ item . item ,
60
100
function (client_id , resolved_item ) cmp .apply_additional_text_edits (client_id , resolved_item ) end
61
101
)
62
102
end
@@ -95,11 +135,12 @@ cmp.select_prev = function(cmp_win, doc_win)
95
135
cmp .update_doc (cmp_win , doc_win )
96
136
end
97
137
98
- cmp .update = function (cmp_win , doc_win , items , opts )
138
+ cmp .update = function (cmp_win , doc_win , items , cursor_column , opts )
99
139
local query = cmp .get_query ()
100
140
101
141
-- get the items based on the user's query
102
142
local filtered_items = cmp .filter_items (query , items )
143
+ cmp .items_cursor_column = cursor_column
103
144
104
145
-- guards for cases where we shouldn't show the completion window
105
146
local no_items = # filtered_items == 0
@@ -220,8 +261,11 @@ cmp.get_query_to_replace = function(bufnr)
220
261
-- Search forward/backward for the start/end of the word
221
262
local start_col = current_col
222
263
while start_col > 1 do
223
- local char = line :sub (start_col - 1 , start_col - 1 )
224
- if char :match (' [%w_\\ -]' ) == nil then break end
264
+ local char = line :sub (start_col , start_col )
265
+ if char :match (' [%w_\\ -]' ) == nil then
266
+ start_col = start_col + 1
267
+ break
268
+ end
225
269
start_col = start_col - 1
226
270
end
227
271
0 commit comments