diff options
author | Guldoman <giulio.lettieri@gmail.com> | 2022-03-18 10:35:51 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-18 05:35:51 -0400 |
commit | 9aa494522b58b7acd92cf2c0670629612cd592b7 (patch) | |
tree | 7a92e79785eb5604c06e065c0a855ce03a73c974 | |
parent | 05b675fb57465e3d95d00550dffc243a455b2541 (diff) | |
download | lite-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
-rw-r--r-- | plugins/smoothcaret.lua | 77 |
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 |