95 lines
3.2 KiB
Lua
95 lines
3.2 KiB
Lua
-- A simple per-session task stack.
|
|
-- Allows pushing locations with a note and returning to them later.
|
|
|
|
--- @type number Namespace id for the plugin
|
|
local ns = vim.api.nvim_create_namespace("stacc")
|
|
|
|
--- @class Location
|
|
--- @field [1] number Buffer Number
|
|
--- @field [2] number ExtMark ID
|
|
--- @field [3] string Description
|
|
--- @field [4] number Current line number
|
|
|
|
--- @class stacc
|
|
--- @field locations Location[] Array listing all the locations with newest ones having the highest indices
|
|
--- @field namespace number Namespace ID used for ExtMarks
|
|
local stacc = {
|
|
locations = {};
|
|
namespace = ns;
|
|
}
|
|
stacc.__index = stacc
|
|
|
|
--- Pushes a new location to the stack
|
|
--- @param description string A message to display when returning to this location
|
|
function stacc:push(description)
|
|
local bufnr = vim.fn.bufnr()
|
|
local line, column = unpack(vim.api.nvim_win_get_cursor(0))
|
|
line = line - 1 -- 0-based :help api-indexing
|
|
local id = vim.api.nvim_buf_set_extmark(bufnr, ns, line, column, {})
|
|
table.insert(self.locations, {bufnr, id, description, vim.fn.line(".")})
|
|
end
|
|
|
|
--- Silently pops/drops a given number of items from the task stack
|
|
--- @param count number How many items to drop from the stack
|
|
--- @return string description The description of the current task
|
|
--- @return number bufnr Buffer number of the stack entry
|
|
--- @return number row Line number (1-indexed)
|
|
--- @return number col Column number (1-indexed)
|
|
function stacc:drop(count)
|
|
if count > #self.locations then
|
|
error("stack only has "..#self.locations.." elements.")
|
|
end
|
|
local bufnr, description
|
|
local final = vim.api.nvim_win_get_cursor(0)
|
|
for _=1, count do
|
|
local id
|
|
bufnr, id, description = unpack(table.remove(self.locations))
|
|
final = vim.api.nvim_buf_get_extmark_by_id(bufnr, ns, id, {})
|
|
vim.api.nvim_buf_del_extmark(bufnr, ns, id)
|
|
final[1] = final[1] + 1 -- Make line 1-indexed
|
|
final[2] = final[2] + 1 -- Make column 1-indexed
|
|
end
|
|
return description, bufnr, final[1], final[2]
|
|
end
|
|
|
|
--- Pops a given number of items from the task stack
|
|
--- Jumps to the last removed item and displays its description
|
|
--- @param count number How many items to pop from the stack
|
|
--- @return string description The description of the current task
|
|
--- @return number bufnr Buffer number of the stack entry
|
|
--- @return number row Line number (1-indexed)
|
|
--- @return number col Column number (1-indexed)
|
|
function stacc:pop(count)
|
|
if count > #self.locations then
|
|
error("stack only has "..#self.locations.." elements.")
|
|
end
|
|
local bufnr, description
|
|
local final = vim.api.nvim_win_get_cursor(0)
|
|
for _=1, count do
|
|
local id
|
|
bufnr, id, description = unpack(table.remove(self.locations))
|
|
final = vim.api.nvim_buf_get_extmark_by_id(bufnr, ns, id, {})
|
|
vim.api.nvim_buf_del_extmark(bufnr, ns, id)
|
|
final[1] = final[1] + 1 -- Make line 1-indexed
|
|
final[2] = final[2] + 1 -- Make column 1-indexed
|
|
final.bufnr = bufnr
|
|
end
|
|
vim.api.nvim_set_current_buf(final.bufnr or 0)
|
|
final.bufnr = nil
|
|
vim.api.nvim_win_set_cursor(0, final)
|
|
return description, bufnr, final[1], final[2]
|
|
end
|
|
|
|
--- Clears the entire stack
|
|
function stacc:clear()
|
|
self:pop(#self.locations)
|
|
end
|
|
|
|
--- @return Stacc new
|
|
function stacc:new(new)
|
|
new = new or {}
|
|
new.locations = new.locations or {}
|
|
return setmetatable(new, self)
|
|
end
|
|
|
|
return stacc
|