Allow per window or buffer nvim staccs

This commit is contained in:
Talia 2024-10-29 11:56:27 +01:00
parent 6dfc4c08ce
commit f88e714758
2 changed files with 60 additions and 19 deletions

View file

@ -4,8 +4,6 @@
--- @type number Namespace id for the plugin --- @type number Namespace id for the plugin
local ns = vim.api.nvim_create_namespace("stacc") local ns = vim.api.nvim_create_namespace("stacc")
local locations = {}
--- @class Location --- @class Location
--- @field [1] number Buffer Number --- @field [1] number Buffer Number
--- @field [2] number ExtMark ID --- @field [2] number ExtMark ID
@ -16,18 +14,19 @@ local locations = {}
--- @field locations Location[] Array listing all the locations with newest ones having the highest indices --- @field locations Location[] Array listing all the locations with newest ones having the highest indices
--- @field namespace number Namespace ID used for ExtMarks --- @field namespace number Namespace ID used for ExtMarks
local stacc = { local stacc = {
locations = locations; locations = {};
namespace = ns; namespace = ns;
} }
stacc.__index = stacc
--- Pushes a new location to the stack --- Pushes a new location to the stack
--- @param description string A message to display when returning to this location --- @param description string A message to display when returning to this location
function stacc.push(description) function stacc:push(description)
local bufnr = vim.fn.bufnr() local bufnr = vim.fn.bufnr()
local line, column = unpack(vim.api.nvim_win_get_cursor(0)) local line, column = unpack(vim.api.nvim_win_get_cursor(0))
line = line - 1 -- 0-based :help api-indexing line = line - 1 -- 0-based :help api-indexing
local id = vim.api.nvim_buf_set_extmark(bufnr, ns, line, column, {}) local id = vim.api.nvim_buf_set_extmark(bufnr, ns, line, column, {})
table.insert(locations, {bufnr, id, description, vim.fn.line(".")}) table.insert(self.locations, {bufnr, id, description, vim.fn.line(".")})
end end
--- Pops a given number of items from the task stack --- Pops a given number of items from the task stack
@ -37,15 +36,15 @@ end
--- @return number bufnr Buffer number of the stack entry --- @return number bufnr Buffer number of the stack entry
--- @return number row Line number (1-indexed) --- @return number row Line number (1-indexed)
--- @return number col Column number (1-indexed) --- @return number col Column number (1-indexed)
function stacc.pop(count) function stacc:pop(count)
if count > #locations then if count > #self.locations then
error("stack only has "..#locations.." elements.") error("stack only has "..#self.locations.." elements.")
end end
local bufnr, description local bufnr, description
local final = vim.api.nvim_win_get_cursor(0) local final = vim.api.nvim_win_get_cursor(0)
for _=1, count do for _=1, count do
local id local id
bufnr, id, description = unpack(table.remove(locations)) bufnr, id, description = unpack(table.remove(self.locations))
final = vim.api.nvim_buf_get_extmark_by_id(bufnr, ns, id, {}) final = vim.api.nvim_buf_get_extmark_by_id(bufnr, ns, id, {})
vim.api.nvim_buf_del_extmark(bufnr, ns, id) vim.api.nvim_buf_del_extmark(bufnr, ns, id)
final[1] = final[1] + 1 -- Make line 1-indexed final[1] = final[1] + 1 -- Make line 1-indexed
@ -59,8 +58,14 @@ function stacc.pop(count)
end end
--- Clears the entire stack --- Clears the entire stack
function stacc.clear() function stacc:clear()
stacc.pop(#locations) stacc.pop(#self.locations)
end
function stacc:new(new)
new = new or {}
new.locations = new.locations or {}
return setmetatable(new, self)
end end
return stacc return stacc

View file

@ -1,10 +1,40 @@
local stacc = require "stacc" local Stacc = require "stacc"
vim.api.nvim_create_user_command("Stacc", function(params) local function staccmap()
return setmetatable({}, {__index=function(self, key)
self[key] = Stacc:new {}
return self[key]
end})
end
local windows = staccmap()
local buffers = staccmap()
local augroup = vim.api.nvim_create_augroup("stacc", {})
vim.api.nvim_create_autocmd({"WinClosed"}, {
group = augroup;
callback = function(arguments)
windows[arguments.match] = nil
end
})
local handler = function(params)
local command = params.name
local stacc if command:find("^G") then
stacc = Stacc
elseif command:find("^W") then
stacc = windows[vim.fn.win_getid()]
elseif command:find("^B") then
stacc = buffers[vim.fn.bufnr()]
else -- Default to per-window stack
stacc = windows[vim.fn.win_getid()]
end
if params.args == "" then if params.args == "" then
local count = #stacc.locations local count = #stacc.locations
if count == 0 then if count == 0 then
print("Stacc is empty. Push with `:Stacc description of current task`") print("Stacc is empty. Push with `:"..command.." description of current task`")
else else
for i, location in ipairs(stacc.locations) do for i, location in ipairs(stacc.locations) do
local bufnr, id, description = unpack(location) local bufnr, id, description = unpack(location)
@ -17,17 +47,23 @@ vim.api.nvim_create_user_command("Stacc", function(params)
description description
)) ))
end end
print(":Stacc pop|clear") print(":"..command.." pop|clear")
end end
elseif params.args == "clear" then elseif params.args == "clear" then
stacc.clear() stacc:clear()
elseif params.args == "pop" then elseif params.args == "pop" then
local message, bufnr = stacc.pop(1) local message, bufnr = stacc:pop(1)
print(string.format("[%s] %s", print(string.format("[%s] %s",
vim.api.nvim_buf_get_name(bufnr):match("[^/]*$"), vim.api.nvim_buf_get_name(bufnr):match("[^/]*$"),
message message
)) ))
else else
stacc.push(params.args) stacc:push(params.args)
end end
end, {nargs="?"}) end
vim.api.nvim_create_user_command("GStacc", handler, {nargs="?"})
vim.api.nvim_create_user_command("WStacc", handler, {nargs="?"})
vim.api.nvim_create_user_command("BStacc", handler, {nargs="?"})
vim.api.nvim_create_user_command("Stacc", handler, {nargs="?"})