aboutsummaryrefslogtreecommitdiff
path: root/plugins/smoothcaret.lua
diff options
context:
space:
mode:
authorGuldoman <giulio.lettieri@gmail.com>2022-03-18 10:35:51 +0100
committerGitHub <noreply@github.com>2022-03-18 05:35:51 -0400
commit9aa494522b58b7acd92cf2c0670629612cd592b7 (patch)
tree7a92e79785eb5604c06e065c0a855ce03a73c974 /plugins/smoothcaret.lua
parent05b675fb57465e3d95d00550dffc243a455b2541 (diff)
downloadlite-xl-plugins-9aa494522b58b7acd92cf2c0670629612cd592b7.tar.gz
lite-xl-plugins-9aa494522b58b7acd92cf2c0670629612cd592b7.zip
Improve `smoothcaret` plugin (#46)
- Add support for multiple carets - Avoid making the caret "jump" around on blink - Don't animate the caret during scroll - Consistently animate the caret on click
Diffstat (limited to 'plugins/smoothcaret.lua')
-rw-r--r--plugins/smoothcaret.lua77
1 files changed, 67 insertions, 10 deletions
diff --git a/plugins/smoothcaret.lua b/plugins/smoothcaret.lua
index 26f7d98..40d852e 100644
--- a/plugins/smoothcaret.lua
+++ b/plugins/smoothcaret.lua
@@ -1,4 +1,5 @@
-- mod-version:2 -- lite-xl 2.0
+local core = require "core"
local config = require "core.config"
local style = require "core.style"
local DocView = require "core.docview"
@@ -9,18 +10,74 @@ local docview_update = DocView.update
function DocView:update()
docview_update(self)
- if not self.caret then
- self.caret = { current = { x = 0, y = 0 }, target = { x = 0, y = 0 } }
- end
- local c = self.caret
- self:move_towards(c.current, "x", c.target.x, config.plugins.smoothcaret.rate)
- self:move_towards(c.current, "y", c.target.y, config.plugins.smoothcaret.rate)
+ local minline, maxline = self:get_visible_line_range()
+
+ -- We need to keep track of all the carets
+ if not self.carets then
+ self.carets = { }
+ end
+ -- and we need the list of visible ones that `DocView:draw_caret` will use in succession
+ self.visible_carets = { }
+
+ local idx, v_idx = 1, 1
+ for _, line, col in self.doc:get_selections() do
+ local x, y = self:get_line_screen_position(line)
+ -- Keep the position relative to the whole View
+ -- This way scrolling won't animate the caret
+ x = x + self:get_col_x_offset(line, col) + self.scroll.x
+ y = y + self.scroll.y
+
+ if not self.carets[idx] then
+ self.carets[idx] = { current = { x = x, y = y }, target = { x = x, y = y } }
+ end
+
+ local c = self.carets[idx]
+ c.target.x = x
+ c.target.y = y
+
+ -- Chech if the number of carets changed
+ if self.last_n_selections ~= #self.doc.selections then
+ -- Don't animate when there are new carets
+ c.current.x = x
+ c.current.y = y
+ else
+ self:move_towards(c.current, "x", c.target.x, config.plugins.smoothcaret.rate)
+ self:move_towards(c.current, "y", c.target.y, config.plugins.smoothcaret.rate)
+ end
+
+ -- Keep track of visible carets
+ if line >= minline and line <= maxline then
+ self.visible_carets[v_idx] = self.carets[idx]
+ v_idx = v_idx + 1
+ end
+ idx = idx + 1
+ end
+ self.last_n_selections = #self.doc.selections
+
+ -- Remove unused carets to avoid animating new ones when they are added
+ for i = idx, #self.carets do
+ self.carets[idx] = nil
+ end
+
+ if self.mouse_selecting ~= self.last_mouse_selecting then
+ self.last_mouse_selecting = self.mouse_selecting
+ -- Show the caret on click, so that it can be seen moving towards the new position
+ if self.mouse_selecting then
+ core.blink_timer = core.blink_timer + config.blink_period / 2
+ core.redraw = true
+ end
+ end
+
+ -- This is used by `DocView:draw_caret` to keep track of the current caret
+ self.caret_idx = 1
end
function DocView:draw_caret(x, y)
- local c = self.caret
+ local c = self.visible_carets[self.caret_idx] or { current = { x = x, y = y } }
local lh = self:get_line_height()
- c.target.x = x
- c.target.y = y
- renderer.draw_rect(c.current.x, c.current.y, style.caret_width, lh, style.caret)
+
+ -- We use the scroll position to move back to the position relative to the window
+ renderer.draw_rect(c.current.x - self.scroll.x, c.current.y - self.scroll.y, style.caret_width, lh, style.caret)
+
+ self.caret_idx = self.caret_idx + 1
end