Improve CommandView and autocomplete scroll behavior (#1732)

* Make command palette item scrolling more natural

Also add a config option for the maximum number of visible entries in the command palette.

* Make `autocomplete` item scrolling more natural

Co-authored-by: Guldoman <giulio.lettieri@gmail.com>
This commit is contained in:
takase1121
2024-03-23 20:27:47 +08:00
co-authored by Guldoman
parent 499124d8e3
commit 48aa350a3e
2 changed files with 47 additions and 9 deletions
+27 -6
View File
@@ -50,6 +50,7 @@ local default_state = {
function CommandView:new() function CommandView:new()
CommandView.super.new(self, SingleLineDoc()) CommandView.super.new(self, SingleLineDoc())
self.suggestion_idx = 1 self.suggestion_idx = 1
self.suggestions_offset = 1
self.suggestions = {} self.suggestions = {}
self.suggestions_height = 0 self.suggestions_height = 0
self.last_change_id = 0 self.last_change_id = 0
@@ -123,6 +124,24 @@ function CommandView:move_suggestion_idx(dir)
end end
end end
local function get_suggestions_offset()
local max_visible = math.min(max_suggestions, #self.suggestions)
if dir > 0 then
if self.suggestions_offset + max_visible < self.suggestion_idx + 1 then
return self.suggestion_idx - max_visible + 1
elseif self.suggestions_offset > self.suggestion_idx then
return self.suggestion_idx
end
else
if self.suggestions_offset > self.suggestion_idx then
return self.suggestion_idx
elseif self.suggestions_offset + max_visible < self.suggestion_idx + 1 then
return self.suggestion_idx - max_visible + 1
end
end
return self.suggestions_offset
end
if self.state.show_suggestions then if self.state.show_suggestions then
local n = self.suggestion_idx + dir local n = self.suggestion_idx + dir
self.suggestion_idx = overflow_suggestion_idx(n, #self.suggestions) self.suggestion_idx = overflow_suggestion_idx(n, #self.suggestions)
@@ -146,6 +165,8 @@ function CommandView:move_suggestion_idx(dir)
self.last_change_id = self.doc:get_change_id() self.last_change_id = self.doc:get_change_id()
self.state.suggest(self:get_text()) self.state.suggest(self:get_text())
end end
self.suggestions_offset = get_suggestions_offset()
end end
@@ -256,6 +277,7 @@ function CommandView:update_suggestions()
end end
self.suggestions = res self.suggestions = res
self.suggestion_idx = 1 self.suggestion_idx = 1
self.suggestions_offset = 1
end end
@@ -299,7 +321,7 @@ function CommandView:update()
self:move_towards("suggestions_height", dest, nil, "commandview") self:move_towards("suggestions_height", dest, nil, "commandview")
-- update suggestion cursor offset -- update suggestion cursor offset
local dest = math.min(self.suggestion_idx, max_suggestions) * self:get_suggestion_line_height() local dest = (self.suggestion_idx - self.suggestions_offset + 1) * self:get_suggestion_line_height()
self:move_towards("selection_offset", dest, nil, "commandview") self:move_towards("selection_offset", dest, nil, "commandview")
-- update size based on whether this is the active_view -- update size based on whether this is the active_view
@@ -335,6 +357,7 @@ local function draw_suggestions_box(self)
local h = math.ceil(self.suggestions_height) local h = math.ceil(self.suggestions_height)
local rx, ry, rw, rh = self.position.x, self.position.y - h - dh, self.size.x, h local rx, ry, rw, rh = self.position.x, self.position.y - h - dh, self.size.x, h
core.push_clip_rect(rx, ry, rw, rh)
-- draw suggestions background -- draw suggestions background
if #self.suggestions > 0 then if #self.suggestions > 0 then
renderer.draw_rect(rx, ry, rw, rh, style.background3) renderer.draw_rect(rx, ry, rw, rh, style.background3)
@@ -344,14 +367,12 @@ local function draw_suggestions_box(self)
end end
-- draw suggestion text -- draw suggestion text
local offset = math.max(self.suggestion_idx - max_suggestions, 0) local first = math.max(self.suggestions_offset, 1)
local last = math.min(offset + max_suggestions, #self.suggestions) local last = math.min(self.suggestions_offset + max_suggestions, #self.suggestions)
core.push_clip_rect(rx, ry, rw, rh)
local first = 1 + offset
for i=first, last do for i=first, last do
local item = self.suggestions[i] local item = self.suggestions[i]
local color = (i == self.suggestion_idx) and style.accent or style.text local color = (i == self.suggestion_idx) and style.accent or style.text
local y = self.position.y - (i - offset) * lh - dh local y = self.position.y - (i - first + 1) * lh - dh
common.draw_text(self:get_font(), color, item.text, nil, x, y, 0, lh) common.draw_text(self:get_font(), color, item.text, nil, x, y, 0, lh)
if item.info then if item.info then
+20 -3
View File
@@ -212,12 +212,14 @@ end)
local partial = "" local partial = ""
local suggestions_offset = 1
local suggestions_idx = 1 local suggestions_idx = 1
local suggestions = {} local suggestions = {}
local last_line, last_col local last_line, last_col
local function reset_suggestions() local function reset_suggestions()
suggestions_offset = 1
suggestions_idx = 1 suggestions_idx = 1
suggestions = {} suggestions = {}
@@ -261,6 +263,7 @@ local function update_suggestions()
end end
end end
suggestions_idx = 1 suggestions_idx = 1
suggestions_offset = 1
end end
local function get_partial_symbol() local function get_partial_symbol()
@@ -457,8 +460,8 @@ local function draw_suggestions_box(av)
local font = av:get_font() local font = av:get_font()
local lh = font:get_height() + style.padding.y local lh = font:get_height() + style.padding.y
local y = ry + style.padding.y / 2 local y = ry + style.padding.y / 2
local show_count = #suggestions <= ah and #suggestions or ah local show_count = math.min(#suggestions, ah)
local start_index = suggestions_idx > ah and (suggestions_idx-(ah-1)) or 1 local start_index = suggestions_offset
for i=start_index, start_index+show_count-1, 1 do for i=start_index, start_index+show_count-1, 1 do
if not suggestions[i] then if not suggestions[i] then
@@ -665,7 +668,7 @@ command.add(predicate, {
local current_partial = get_partial_symbol() local current_partial = get_partial_symbol()
local sz = #current_partial local sz = #current_partial
for idx, line1, col1, line2, col2 in doc:get_selections(true) do for _, line1, col1, line2, _ in doc:get_selections(true) do
local n = col1 - 1 local n = col1 - 1
local line = doc.lines[line1] local line = doc.lines[line1]
for i = 1, sz + 1 do for i = 1, sz + 1 do
@@ -686,10 +689,24 @@ command.add(predicate, {
["autocomplete:previous"] = function() ["autocomplete:previous"] = function()
suggestions_idx = (suggestions_idx - 2) % #suggestions + 1 suggestions_idx = (suggestions_idx - 2) % #suggestions + 1
local ah = math.min(config.plugins.autocomplete.max_height, #suggestions)
if suggestions_offset > suggestions_idx then
suggestions_offset = suggestions_idx
elseif suggestions_offset + ah < suggestions_idx + 1 then
suggestions_offset = suggestions_idx - ah + 1
end
end, end,
["autocomplete:next"] = function() ["autocomplete:next"] = function()
suggestions_idx = (suggestions_idx % #suggestions) + 1 suggestions_idx = (suggestions_idx % #suggestions) + 1
local ah = math.min(config.plugins.autocomplete.max_height, #suggestions)
if suggestions_offset + ah < suggestions_idx + 1 then
suggestions_offset = suggestions_idx - ah + 1
elseif suggestions_offset > suggestions_idx then
suggestions_offset = suggestions_idx
end
end, end,
["autocomplete:cycle"] = function() ["autocomplete:cycle"] = function()