blink.cmp
blink.cmp copied to clipboard
Ability to scroll list by count?
Feature Description
Ty @Saghen for this wonderful plugin!
I might be missing something but I also looked at the code and couldn't find an equivalent for documentation scroll up|down for the item list.
The use case is using <C-b>|<C-f> to scroll the item list back/forward, perhaps something like #382 but for select_{next|prev}?
keymap = {
['<C-b>'] = { function(cmp) cmp.select_prev({ count = 10 }) end },
['<C-f>'] = { function(cmp) cmp.select_next({ count = 10 }) end },
quick workaround
local function select_next_idx(idx, dir)
dir = dir or 1
local list = require "blink.cmp.completion.list"
if #list.items == 0 then
return
end
local target_idx
-- haven't selected anything yet
if list.selected_item_idx == nil then
if dir == 1 then
target_idx = idx
else
target_idx = #list.items - idx
end
elseif list.selected_item_idx == #list.items then
if dir == 1 then
target_idx = 1
else
target_idx = #list.items - idx
end
elseif list.selected_item_idx == 1 and dir == -1 then
target_idx = #list.items - idx
else
target_idx = list.selected_item_idx + (idx * dir)
end
-- clamp
if target_idx < 1 then
target_idx = 1
elseif target_idx > #list.items then
target_idx = #list.items
end
list.select(target_idx)
end
keymap = {
["<PageDown>"] = {
function(cmp)
if not cmp.is_visible() then
return
end
vim.schedule(function()
select_next_idx(3)
end)
return true
end,
"fallback",
},
["<PageUp>"] = {
function(cmp)
if not cmp.is_visible() then
return
end
vim.schedule(function()
select_next_idx(3, -1)
end)
return true
end,
"fallback",
},
}
Would you expect this to respect completion.list.cycle?
Would you expect this to respect
completion.list.cycle?
I'm not sure, either way is fine, your call :-)
Would you expect this to respect completion.list.cycle?
I believe the more sane default would be to respect it, but maybe it could be a setup parameter?
Would you expect this to respect
completion.list.cycle?
It should cycle if it's already at the end, but not to cycle if there are fewer than count but more than zero items away from the end.
Here's an implementation I came up with. Could this be integrated into the plugin?
---@param cb fun(cmp: blink.cmp.API)
---@return fun(cmp: blink.cmp.API): boolean
local function wrap_scroll_page(cb)
return function(cmp)
if cmp.is_menu_visible() then
vim.schedule(cb)
return true
else
return false
end
end
end
local function scroll_page_up()
local list = require('blink.cmp.completion.list')
if #list.items == 0 or list.context == nil then
return
elseif list.selected_item_idx == nil then
return list.select(#list.items)
else
local page_size = require('blink.cmp.completion.windows.menu').win:get_height()
return list.select(math.max(list.selected_item_idx - page_size, 1))
end
end
local function scroll_page_down()
local list = require('blink.cmp.completion.list')
if #list.items == 0 or list.context == nil then
return
elseif list.selected_item_idx == nil then
return list.select(#list.items)
else
local page_size = require('blink.cmp.completion.windows.menu').win:get_height()
return list.select(math.min(list.selected_item_idx + page_size, #list.items))
end
end
require('blink.cmp').setup({
keymap = {
['<C-u>'] = { wrap_scroll_page(scroll_page_up), 'fallback' },
['<C-d>'] = { wrap_scroll_page(scroll_page_down), 'fallback' },
},
})