diff --git a/vim/.luarc.json b/vim/.luarc.json index dfc1967..b957ce7 100644 --- a/vim/.luarc.json +++ b/vim/.luarc.json @@ -1,4 +1,7 @@ { "runtime.version": "Lua 5.1", - "diagnostics.globals": ["vim"] + "diagnostics.globals": ["vim"], + "workspace.library": [ + "/home/darkwiiplayer/darkrc/vim/lua" + ] } diff --git a/vim/lua/stacc.lua b/vim/lua/stacc.lua new file mode 100644 index 0000000..72d56ca --- /dev/null +++ b/vim/lua/stacc.lua @@ -0,0 +1,66 @@ +-- 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") + +local locations = {} + +--- @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 = locations; + namespace = ns; +} + +--- 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(locations, {bufnr, id, description, vim.fn.line(".")}) +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 > #locations then + error("stack only has "..#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(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, unpack(final) +end + +--- Clears the entire stack +function stacc.clear() + stacc.pop(#locations) +end + +return stacc diff --git a/vim/plugin/stacc.lua b/vim/plugin/stacc.lua index b4d4731..e1bcb47 100644 --- a/vim/plugin/stacc.lua +++ b/vim/plugin/stacc.lua @@ -1,51 +1,28 @@ --- A simple per-session task stack. --- Allows pushing locations with a note and returning to them later. +local stacc = require "stacc" -local ns = vim.api.nvim_create_namespace("stacc") - -local locations = {} - -local 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(locations, {bufnr, id, description, vim.fn.line(".")}) -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 -function stacc.pop(count) - if count > #locations then - error("stack only has "..#locations.." elements.") +vim.api.nvim_create_user_command("Stacc", function(params) + if params.args == "" then + local count = #stacc.locations + for i, location in ipairs(stacc.locations) do + local bufnr, id, description = unpack(location) + --- @type number[] + local mark = vim.api.nvim_buf_get_extmark_by_id(bufnr, stacc.namespace, id, {}) + print(string.format("%s %s:%i -- %s", + string.format("%" .. math.floor(math.log(count, 10)+1) .. "i", i), + vim.api.nvim_buf_get_name(bufnr):match("[^/]*$"), + mark[1] + 1, + description + )) + end + elseif params.args == "clear" then + stacc.clear() + elseif params.args == "pop" then + local message, bufnr = stacc.pop(1) + print(string.format("[%s] %s", + vim.api.nvim_buf_get_name(bufnr):match("[^/]*$"), + message + )) + else + stacc.push(params.args) end - local description - local final = vim.api.nvim_win_get_cursor(0) - for _=1, count do - local bufnr, id - bufnr, id, description = unpack(table.remove(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.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 -end - -vim.api.nvim_create_user_command("StaccPush", function(params) - stacc.push(params.args) -end, {nargs="?"}) - -vim.api.nvim_create_user_command("StaccPop", function(params) - local message = stacc.pop(tonumber(params.args) or 1) - print(message) end, {nargs="?"})