fix(mark): can't stop session if cursor is out of range
This commit is contained in:
@@ -212,13 +212,15 @@ return setmetatable({}, {
|
||||
vim.api.nvim_buf_set_lines(0, row, row, true, content)
|
||||
|
||||
if #marks_pos > 0 then
|
||||
-- start session of marks
|
||||
-- Start session of marks
|
||||
mark:start()
|
||||
for _, pos in ipairs(marks_pos) do
|
||||
mark:add_mark(pos)
|
||||
end
|
||||
vim.cmd("startinsert")
|
||||
mark:jump()
|
||||
-- Add range mark after first jump
|
||||
mark:add_range_mark({row, 0, row + #template_content, 1})
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
---@class Mark
|
||||
---@field started boolean
|
||||
---@field bufnr number
|
||||
---@field winid number
|
||||
---@field index number
|
||||
---@field last_cursor number
|
||||
---@field ids number[]
|
||||
---@field range_id number
|
||||
local mark = {}
|
||||
|
||||
local api = vim.api
|
||||
local ns = api.nvim_create_namespace("neogen")
|
||||
|
||||
local function compare_pos(p1, p2)
|
||||
return p1[1] == p2[1] and p1[2] - p2[2] or p1[1] - p2[1]
|
||||
end
|
||||
|
||||
--- Start marks creation and get useful informations
|
||||
---@private
|
||||
mark.start = function(self)
|
||||
@@ -11,14 +23,19 @@ mark.start = function(self)
|
||||
end
|
||||
self.bufnr = api.nvim_get_current_buf()
|
||||
self.winid = api.nvim_get_current_win()
|
||||
self.index = 0
|
||||
local pos = api.nvim_win_get_cursor(self.winid)
|
||||
local row, col = unpack(pos)
|
||||
self.last_jump = api.nvim_buf_set_extmark(self.bufnr, ns, row - 1, col, {})
|
||||
self.index = 0
|
||||
self.last_cursor_id = api.nvim_buf_set_extmark(self.bufnr, ns, row - 1, col, {})
|
||||
self.ids = {}
|
||||
self.range_id = nil
|
||||
self.started = true
|
||||
end
|
||||
|
||||
mark.valid = function(self)
|
||||
return self.bufnr == api.nvim_get_current_buf() and self.winid == api.nvim_get_current_win()
|
||||
end
|
||||
|
||||
--- Get a mark specified with i index
|
||||
---@param i number
|
||||
---@private
|
||||
@@ -45,6 +62,29 @@ mark.mark_len = function(self)
|
||||
return #self.ids
|
||||
end
|
||||
|
||||
mark.get_range_mark = function(self)
|
||||
local d = api.nvim_buf_get_extmark_by_id(self.bufnr, ns, self.range_id, {details = true})
|
||||
local row, col, end_row, end_col = d[1], d[2], d[3].end_row, d[3].end_col
|
||||
return row, col, end_row, end_col
|
||||
end
|
||||
|
||||
mark.add_range_mark = function(self, range)
|
||||
local row, col, end_row, end_col = unpack(range)
|
||||
self.range_id = api.nvim_buf_set_extmark(self.bufnr, ns, row, col,
|
||||
{end_row = end_row, end_col = end_col})
|
||||
end
|
||||
|
||||
mark.cursor_in_range = function(self, validated)
|
||||
local ret = validated or self:valid()
|
||||
if ret and self.range_id then
|
||||
local pos = api.nvim_win_get_cursor(self.winid)
|
||||
pos[1] = pos[1] - 1
|
||||
local row, col, end_row, end_col = self:get_range_mark()
|
||||
ret = compare_pos({row, col}, pos) <= 0 and compare_pos({end_row, end_col}, pos) >= 0
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Verify if the marks can be jumpable
|
||||
---@param reverse boolean
|
||||
---@return boolean
|
||||
@@ -53,14 +93,24 @@ mark.jumpable = function(self, reverse)
|
||||
if not self.started then
|
||||
return false
|
||||
end
|
||||
local ret = true
|
||||
local validated = self:valid()
|
||||
if not validated then
|
||||
self:stop()
|
||||
return validated
|
||||
end
|
||||
local ret
|
||||
if reverse then
|
||||
ret = self.index > 0
|
||||
else
|
||||
ret = #self.ids >= self.index
|
||||
end
|
||||
if ret then
|
||||
ret = self.bufnr == api.nvim_get_current_buf() and self.winid == api.nvim_get_current_win()
|
||||
ret = self:cursor_in_range(true)
|
||||
end
|
||||
|
||||
if not ret then
|
||||
self:jump_last_cursor(true)
|
||||
self:stop()
|
||||
end
|
||||
return ret
|
||||
end
|
||||
@@ -69,42 +119,44 @@ end
|
||||
---@param reverse boolean
|
||||
---@private
|
||||
mark.jump = function(self, reverse)
|
||||
if mark:jumpable(reverse) then
|
||||
if self.started then
|
||||
self.index = reverse and self.index - 1 or self.index + 1
|
||||
if self.index > 0 and self.index <= #self.ids then
|
||||
local line, row = unpack(self:get_mark(self.index))
|
||||
api.nvim_win_set_cursor(self.winid, { line + 1, row })
|
||||
else
|
||||
self:stop(true)
|
||||
end
|
||||
else
|
||||
self:stop(true)
|
||||
end
|
||||
if mark:jumpable(reverse) then
|
||||
local line, row = unpack(self:get_mark(self.index))
|
||||
api.nvim_win_set_cursor(self.winid, {line + 1, row})
|
||||
end
|
||||
end
|
||||
|
||||
mark.jump_last_cursor = function(self, validated)
|
||||
if self:cursor_in_range(validated) then
|
||||
local winid = self.winid
|
||||
local pos = api.nvim_buf_get_extmark_by_id(self.bufnr, ns, self.last_cursor_id, {})
|
||||
local line, col = unpack(pos)
|
||||
api.nvim_win_set_cursor(winid, {line + 1, col})
|
||||
end
|
||||
end
|
||||
|
||||
--- Clear marks and stop jumping ability
|
||||
---@private
|
||||
mark.stop = function(self, should_jump)
|
||||
mark.stop = function(self)
|
||||
local bufnr = self.bufnr
|
||||
if bufnr and bufnr > 0 and api.nvim_buf_is_valid(bufnr) then
|
||||
for _, id in ipairs(self.ids) do
|
||||
api.nvim_buf_del_extmark(bufnr, ns, id)
|
||||
end
|
||||
|
||||
local winid = self.winid
|
||||
if should_jump and winid and winid > 0 and api.nvim_win_is_valid(winid) then
|
||||
local pos = api.nvim_buf_get_extmark_by_id(self.bufnr, ns, self.last_jump, {})
|
||||
local line, col = unpack(pos)
|
||||
api.nvim_win_set_cursor(winid, { line + 1, col })
|
||||
api.nvim_buf_del_extmark(bufnr, ns, self.last_cursor_id)
|
||||
if self.range_id then
|
||||
api.nvim_buf_del_extmark(bufnr, ns, self.range_id)
|
||||
end
|
||||
api.nvim_buf_del_extmark(bufnr, ns, self.last_jump)
|
||||
end
|
||||
self.bufnr = nil
|
||||
self.winid = nil
|
||||
self.index = nil
|
||||
self.last_jump = nil
|
||||
self.last_cursor_id = nil
|
||||
self.started = false
|
||||
self.ids = {}
|
||||
self.range_id = nil
|
||||
end
|
||||
|
||||
return mark
|
||||
|
||||
Reference in New Issue
Block a user