7
7
8
8
local config = require (' blink.cmp.config' )
9
9
local renderer = require (' blink.cmp.windows.lib.render' )
10
+ local text_edits_lib = require (' blink.cmp.accept.text-edits' )
10
11
local autocmp_config = config .windows .autocomplete
11
12
local autocomplete = {
12
13
--- @type blink.cmp.CompletionItem[]
@@ -74,7 +75,7 @@ function autocomplete.open_with_items(context, items)
74
75
75
76
autocomplete .context = context
76
77
autocomplete .update_position (context )
77
- autocomplete .set_has_selected (autocmp_config .preselect )
78
+ autocomplete .set_has_selected (autocmp_config .selection == ' preselect' )
78
79
79
80
-- todo: some logic to maintain the selection if the user moved the cursor?
80
81
vim .api .nvim_win_set_cursor (autocomplete .win :get_win (), { 1 , 0 })
@@ -85,13 +86,13 @@ function autocomplete.open()
85
86
if autocomplete .win :is_open () then return end
86
87
vim .iter (autocomplete .event_targets .on_open ):each (function (callback ) callback () end )
87
88
autocomplete .win :open ()
88
- autocomplete .set_has_selected (autocmp_config .preselect )
89
+ autocomplete .set_has_selected (autocmp_config .selection == ' preselect' )
89
90
end
90
91
91
92
function autocomplete .close ()
92
93
if not autocomplete .win :is_open () then return end
93
94
autocomplete .win :close ()
94
- autocomplete .has_selected = autocmp_config . preselect
95
+ autocomplete .set_has_selected ( autocmp_config . selection == ' preselect' )
95
96
96
97
vim .iter (autocomplete .event_targets .on_close ):each (function (callback ) callback () end )
97
98
end
157
158
158
159
---- ------ Selection ----------
159
160
161
+ --- @param line number
162
+ local function select (line )
163
+ local prev_selected_item = autocomplete .get_selected_item ()
164
+
165
+ autocomplete .set_has_selected (true )
166
+ vim .api .nvim_win_set_cursor (autocomplete .win :get_win (), { line , 0 })
167
+
168
+ local selected_item = autocomplete .get_selected_item ()
169
+
170
+ -- when auto_insert is enabled, we immediately apply the text edit
171
+ -- todo: move this to the accept module
172
+ if config .windows .autocomplete .selection == ' auto_insert' and selected_item ~= nil then
173
+ require (' blink.cmp.trigger.completion' ).ignore_autocmds_for_callback (function ()
174
+ local text_edit = text_edits_lib .get_from_item (selected_item )
175
+
176
+ if selected_item .insertTextFormat == vim .lsp .protocol .InsertTextFormat .Snippet then
177
+ text_edit .newText = selected_item .label
178
+ end
179
+
180
+ if
181
+ prev_selected_item ~= nil and prev_selected_item .insertTextFormat == vim .lsp .protocol .InsertTextFormat .Snippet
182
+ then
183
+ local current_col = vim .api .nvim_win_get_cursor (0 )[2 ]
184
+ text_edit .range .start .character = current_col - # prev_selected_item .label
185
+ end
186
+
187
+ text_edits_lib .apply_text_edits (selected_item .client_id , { text_edit })
188
+ vim .api .nvim_win_set_cursor (0 , {
189
+ text_edit .range .start .line + 1 ,
190
+ text_edit .range .start .character + # text_edit .newText ,
191
+ })
192
+ end )
193
+ end
194
+
195
+ autocomplete .event_targets .on_select (selected_item , autocomplete .context )
196
+ end
197
+
160
198
function autocomplete .select_next ()
161
199
if not autocomplete .win :is_open () then return end
162
200
@@ -166,6 +204,7 @@ function autocomplete.select_next()
166
204
-- We need to ajust the disconnect between the line position
167
205
-- on the window and the selected item
168
206
if not autocomplete .has_selected then line = line - 1 end
207
+ if autocomplete .has_selected and l == 1 then return end
169
208
if line == l then
170
209
-- at the end of completion list and the config is not enabled: do nothing
171
210
if not cycle_from_bottom then return end
@@ -174,10 +213,7 @@ function autocomplete.select_next()
174
213
line = line + 1
175
214
end
176
215
177
- autocomplete .set_has_selected (true )
178
-
179
- vim .api .nvim_win_set_cursor (autocomplete .win :get_win (), { line , 0 })
180
- autocomplete .event_targets .on_select (autocomplete .get_selected_item (), autocomplete .context )
216
+ select (line )
181
217
end
182
218
183
219
function autocomplete .select_prev ()
@@ -186,17 +222,15 @@ function autocomplete.select_prev()
186
222
local cycle_from_top = config .windows .autocomplete .cycle .from_top
187
223
local l = # autocomplete .items
188
224
local line = vim .api .nvim_win_get_cursor (autocomplete .win :get_win ())[1 ]
225
+ if autocomplete .has_selected and l == 1 then return end
189
226
if line <= 1 then
190
227
if not cycle_from_top then return end
191
228
line = l
192
229
else
193
230
line = line - 1
194
231
end
195
232
196
- autocomplete .set_has_selected (true )
197
-
198
- vim .api .nvim_win_set_cursor (autocomplete .win :get_win (), { line , 0 })
199
- autocomplete .event_targets .on_select (autocomplete .get_selected_item (), autocomplete .context )
233
+ select (line )
200
234
end
201
235
202
236
function autocomplete .listen_on_select (callback ) autocomplete .event_targets .on_select = callback end
@@ -289,6 +323,8 @@ function autocomplete.render_item_reversed(ctx)
289
323
}
290
324
end
291
325
326
+ --- @param ctx blink.cmp.CompletionRenderContext
327
+ --- @return blink.cmp.Component[]
292
328
function autocomplete .render_item_minimal (ctx )
293
329
return {
294
330
' ' ,
0 commit comments