|
21 | 21 | --- @field select fun(idx?: number, opts?: { auto_insert?: boolean, undo_preview?: boolean, is_explicit_selection?: boolean })
|
22 | 22 | --- @field select_next fun(opts?: blink.cmp.CompletionListSelectOpts)
|
23 | 23 | --- @field select_prev fun(opts?: blink.cmp.CompletionListSelectOpts)
|
| 24 | +--- @field jump_by fun(dir: number, opts?: blink.cmp.CompletionListSelectOpts): boolean |
24 | 25 | ---
|
25 | 26 | --- @field undo_preview fun()
|
26 | 27 | --- @field apply_preview fun(item: blink.cmp.CompletionItem)
|
27 | 28 | --- @field accept fun(opts?: blink.cmp.CompletionListAcceptOpts): boolean Applies the currently selected item, returning true if it succeeded
|
28 | 29 |
|
29 | 30 | --- @class blink.cmp.CompletionListSelectOpts
|
30 | 31 | --- @field count? number The number of items to jump by, defaults to 1
|
| 32 | +--- @field jump_by? blink.cmp.CompletionListJumpBy Jump to the item whose specified property differs from the current one. Fallbacks to `count` when no such item is found. |
31 | 33 | --- @field auto_insert? boolean Insert the completion item automatically when selecting it
|
32 | 34 | --- @field on_ghost_text? boolean Run when ghost text is visible, instead of only when the menu is visible
|
33 | 35 |
|
| 36 | +--- @alias blink.cmp.CompletionListJumpBy |
| 37 | +--- | 'client_id' |
| 38 | +--- | 'client_name' |
| 39 | +--- | 'deprecated' |
| 40 | +--- | 'exact' |
| 41 | +--- | 'kind' |
| 42 | +--- | 'score' |
| 43 | +--- | 'score_offset' |
| 44 | +--- | 'source_id' |
| 45 | +--- | 'source_name' |
| 46 | + |
34 | 47 | --- @class blink.cmp.CompletionListSelectAndAcceptOpts
|
35 | 48 | --- @field callback? fun() Called after the item is accepted
|
36 | 49 |
|
@@ -198,7 +211,10 @@ function list.select_next(opts)
|
198 | 211 | return list.select(1, opts)
|
199 | 212 | end
|
200 | 213 |
|
201 |
| - -- typical case, select the next item |
| 214 | + -- try to jump to the item whose specified property differs from the current one |
| 215 | + if list.jump_by(1, opts) then return end |
| 216 | + |
| 217 | + -- fallback, select the next item |
202 | 218 | local count = opts and opts.count or 1
|
203 | 219 | list.select(math.min(list.selected_item_idx + count, #list.items), opts)
|
204 | 220 | end
|
@@ -226,11 +242,52 @@ function list.select_prev(opts)
|
226 | 242 | return list.select(#list.items, opts)
|
227 | 243 | end
|
228 | 244 |
|
229 |
| - -- typical case, select the previous item |
| 245 | + -- try to jump to the item whose specified property differs from the current one |
| 246 | + if list.jump_by(-1, opts) then return end |
| 247 | + |
| 248 | + -- fallback, select the previous item |
230 | 249 | local count = opts and opts.count or 1
|
231 | 250 | list.select(math.max(list.selected_item_idx - count, 1), opts)
|
232 | 251 | end
|
233 | 252 |
|
| 253 | +--- Jump to the item whose specified property differs from the current one. Supports cycling. |
| 254 | +--- @param dir integer direction - 1 for next, -1 for previous |
| 255 | +--- @param opts blink.cmp.CompletionListSelectOpts |
| 256 | +--- @return boolean |
| 257 | +function list.jump_by(dir, opts) |
| 258 | + opts = opts or {} |
| 259 | + |
| 260 | + if not list.items or #list.items == 0 or not list.selected_item_idx then return false end |
| 261 | + if type(opts.jump_by) ~= 'string' then return false end |
| 262 | + |
| 263 | + local current = list.items[list.selected_item_idx][opts.jump_by] |
| 264 | + if not vim.tbl_contains({ 'string', 'number', 'boolean' }, type(current)) then return false end |
| 265 | + |
| 266 | + local function try_jump(start_idx, end_idx, step) |
| 267 | + for i = start_idx, end_idx, step do |
| 268 | + if list.items[i][opts.jump_by] ~= current then |
| 269 | + list.select(i, opts) |
| 270 | + return true |
| 271 | + end |
| 272 | + end |
| 273 | + return false |
| 274 | + end |
| 275 | + |
| 276 | + if dir == 1 then |
| 277 | + if try_jump(list.selected_item_idx + 1, #list.items, 1) then return true end |
| 278 | + if list.config and list.config.cycle and list.config.cycle.from_bottom then |
| 279 | + return try_jump(1, list.selected_item_idx - 1, 1) |
| 280 | + end |
| 281 | + elseif dir == -1 then |
| 282 | + if try_jump(list.selected_item_idx - 1, 1, -1) then return true end |
| 283 | + if list.config and list.config.cycle and list.config.cycle.from_top then |
| 284 | + return try_jump(#list.items, list.selected_item_idx + 1, -1) |
| 285 | + end |
| 286 | + end |
| 287 | + |
| 288 | + return false |
| 289 | +end |
| 290 | + |
234 | 291 | ---------- Preview ----------
|
235 | 292 |
|
236 | 293 | function list.undo_preview()
|
|
0 commit comments