From 560f20958743149bfd5bf8910bb7dd51ed77598b Mon Sep 17 00:00:00 2001 From: Patrick Dewey Date: Mon, 26 Aug 2024 17:22:33 -0400 Subject: [PATCH] feat/refactor: added backwards paste and changed global names --- Makefile | 2 +- lua/yankbank/api.lua | 14 +++---- lua/yankbank/clipboard.lua | 18 ++++---- lua/yankbank/data.lua | 10 ++--- lua/yankbank/helpers.lua | 7 ++-- lua/yankbank/init.lua | 15 +++---- lua/yankbank/menu.lua | 70 ++++++++++++++++++++------------ lua/yankbank/persistence.lua | 8 ++-- lua/yankbank/persistence/sql.lua | 8 ++-- 9 files changed, 86 insertions(+), 66 deletions(-) diff --git a/Makefile b/Makefile index f8cd0bc..b872a54 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,6 @@ fmt: lint: echo "Linting lua/yankbank..." - luacheck lua/ --globals vim YANKS REG_TYPES OPTS + luacheck lua/ --globals vim YB_YANKS YB_REG_TYPES YB_OPTS pr-ready: fmt lint diff --git a/lua/yankbank/api.lua b/lua/yankbank/api.lua index 7c36ec1..72bf00f 100644 --- a/lua/yankbank/api.lua +++ b/lua/yankbank/api.lua @@ -5,8 +5,8 @@ local M = {} ---@return table function M.get_entry(i) return { - yank_text = YANKS[i], - reg_type = REG_TYPES[i], + yank_text = YB_YANKS[i], + reg_type = YB_REG_TYPES[i], } end @@ -14,10 +14,10 @@ end ---@return table function M.get_all() local out = {} - for i, v in ipairs(YANKS) do + for i, v in ipairs(YB_YANKS) do table.insert(out, { yank_text = v, - reg_type = REG_TYPES[i], + reg_type = YB_REG_TYPES[i], }) end return out @@ -33,9 +33,9 @@ end --- remove entry from yankbank by index ---@param i integer index to remove function M.remove_entry(i) - local yank_text = table.remove(YANKS, i) - table.remove(REG_TYPES, i) - if OPTS.persist_type == "sqlite" then + local yank_text = table.remove(YB_YANKS, i) + table.remove(YB_REG_TYPES, i) + if YB_OPTS.persist_type == "sqlite" then require("yankbank.persistence.sql").data().remove_match(yank_text) end end diff --git a/lua/yankbank/clipboard.lua b/lua/yankbank/clipboard.lua index 0420376..b12548a 100644 --- a/lua/yankbank/clipboard.lua +++ b/lua/yankbank/clipboard.lua @@ -13,23 +13,23 @@ function M.add_yank(text, reg_type) end -- check for duplicate values already inserted - for i, entry in ipairs(YANKS) do + for i, entry in ipairs(YB_YANKS) do if entry == text then -- remove matched entry so it can be inserted at 1st position - table.remove(YANKS, i) - table.remove(REG_TYPES, i) + table.remove(YB_YANKS, i) + table.remove(YB_REG_TYPES, i) break end end -- add entry to bank - table.insert(YANKS, 1, text) - table.insert(REG_TYPES, 1, reg_type) + table.insert(YB_YANKS, 1, text) + table.insert(YB_REG_TYPES, 1, reg_type) -- trim table size if necessary - if #YANKS > OPTS.max_entries then - table.remove(YANKS) - table.remove(REG_TYPES) + if #YB_YANKS > YB_OPTS.max_entries then + table.remove(YB_YANKS) + table.remove(YB_REG_TYPES) end -- add entry to persistent store @@ -62,7 +62,7 @@ function M.setup_yank_autocmd() }) -- poll registers when vim is focused (check for new clipboard activity) - if OPTS.focus_gain_poll == true then + if YB_OPTS.focus_gain_poll == true then vim.api.nvim_create_autocmd("FocusGained", { callback = function() -- get register information diff --git a/lua/yankbank/data.lua b/lua/yankbank/data.lua index e5cbdbd..564e10b 100644 --- a/lua/yankbank/data.lua +++ b/lua/yankbank/data.lua @@ -8,10 +8,10 @@ function M.get_display_lines() local yank_num = 0 -- calculate the maximum width needed for the yank numbers - local max_digits = #tostring(#YANKS) + local max_digits = #tostring(#YB_YANKS) -- assumes yanks is table of strings - for i, yank in ipairs(YANKS) do + for i, yank in ipairs(YB_YANKS) do yank_num = yank_num + 1 local yank_lines = yank @@ -48,12 +48,12 @@ function M.get_display_lines() table.insert(line_yank_map, i) end - if i < #YANKS then + if i < #YB_YANKS then -- Add a visual separator between yanks, aligned with the yank content - if OPTS.sep ~= "" then + if YB_OPTS.sep ~= "" then table.insert( display_lines, - string.rep(" ", max_digits + 2) .. OPTS.sep + string.rep(" ", max_digits + 2) .. YB_OPTS.sep ) end table.insert(line_yank_map, false) diff --git a/lua/yankbank/helpers.lua b/lua/yankbank/helpers.lua index 8dea2e6..5797c3f 100644 --- a/lua/yankbank/helpers.lua +++ b/lua/yankbank/helpers.lua @@ -43,10 +43,11 @@ function M.prev_numbered_item(steps) vim.api.nvim_win_set_cursor(0, { 1, 0 }) end ---- customized paste function that functions like 'p' +--- customized paste function that functions like 'p' or 'P' ---@param text string|table ---@param reg_type string -function M.smart_paste(text, reg_type) +---@param after boolean define if text should be pasted after 'p' or before 'P' +function M.smart_paste(text, reg_type, after) local lines = {} if type(text) == "string" then -- convert text string to string list @@ -61,7 +62,7 @@ function M.smart_paste(text, reg_type) lines = text end - vim.api.nvim_put(lines, reg_type, true, true) + vim.api.nvim_put(lines, reg_type, after, true) end return M diff --git a/lua/yankbank/init.lua b/lua/yankbank/init.lua index 2145b3a..909d6fc 100644 --- a/lua/yankbank/init.lua +++ b/lua/yankbank/init.lua @@ -1,14 +1,15 @@ local M = {} +-- define global variables +YB_YANKS = {} +YB_REG_TYPES = {} +YB_OPTS = {} + -- local imports local menu = require("yankbank.menu") local clipboard = require("yankbank.clipboard") local persistence = require("yankbank.persistence") -YANKS = {} -REG_TYPES = {} -OPTS = {} - -- default plugin options local default_opts = { max_entries = 10, @@ -24,7 +25,7 @@ local default_opts = { --- wrapper function for main plugin functionality local function show_yank_bank() - YANKS = persistence.get_yanks() or YANKS + YB_YANKS = persistence.get_yanks() or YB_YANKS -- initialize buffer and populate bank local buf_data = menu.create_and_fill_buffer() @@ -43,10 +44,10 @@ end ---@param opts? table function M.setup(opts) -- merge opts with default options table - OPTS = vim.tbl_deep_extend("keep", opts or {}, default_opts) + YB_OPTS = vim.tbl_deep_extend("keep", opts or {}, default_opts) -- enable persistence based on opts (needs to be called before autocmd setup) - YANKS, REG_TYPES = persistence.setup() + YB_YANKS, YB_REG_TYPES = persistence.setup() -- create clipboard autocmds clipboard.setup_yank_autocmd() diff --git a/lua/yankbank/menu.lua b/lua/yankbank/menu.lua index 75603c5..b9f7fd2 100644 --- a/lua/yankbank/menu.lua +++ b/lua/yankbank/menu.lua @@ -8,6 +8,7 @@ local default_keymaps = { navigation_next = "j", navigation_prev = "k", paste = "", + paste_back = "P", yank = "yy", close = { "", "", "q" }, } @@ -17,6 +18,16 @@ local default_registers = { yank_register = "+", } +-- merge default and options keymap tables +local k = vim.tbl_deep_extend("force", default_keymaps, YB_OPTS.keymaps or {}) + +-- merge default and options register tables +YB_OPTS.registers = + vim.tbl_deep_extend("force", default_registers, YB_OPTS.registers or {}) + +-- check table for number behavior option (prefix or jump, default to prefix) +YB_OPTS.num_behavior = YB_OPTS.num_behavior or "prefix" + --- Container class for YankBank buffer related variables ---@class YankBankBufData ---@field bufnr integer @@ -28,7 +39,7 @@ local default_registers = { ---@return YankBankBufData? function M.create_and_fill_buffer() -- stop if yanks or register types table is empty - if #YANKS == 0 or #REG_TYPES == 0 then + if #YB_YANKS == 0 or #YB_REG_TYPES == 0 then print("No yanks to show.") return nil end @@ -105,18 +116,8 @@ function M.set_keymaps(b) -- key mappings for selection and closing the popup local map_opts = { noremap = true, silent = true, buffer = b.bufnr } - -- merge default and options keymap tables - local k = vim.tbl_deep_extend("force", default_keymaps, OPTS.keymaps or {}) - - -- merge default and options keymap tables - OPTS.registers = - vim.tbl_deep_extend("force", default_registers, OPTS.registers or {}) - - -- check table for number behavior option (prefix or jump, default to prefix) - OPTS.num_behavior = OPTS.num_behavior or "prefix" - -- popup buffer navigation binds - if OPTS.num_behavior == "prefix" then + if YB_OPTS.num_behavior == "prefix" then vim.keymap.set("n", k.navigation_next, function() local count = vim.v.count1 > 0 and vim.v.count1 or 1 helpers.next_numbered_item(count) @@ -126,25 +127,25 @@ function M.set_keymaps(b) local count = vim.v.count1 > 0 and vim.v.count1 or 1 helpers.prev_numbered_item(count) return "" - end, { noremap = true, silent = true, buffer = b.bufnr }) + end, map_opts) else vim.keymap.set( "n", k.navigation_next, helpers.next_numbered_item, - { noremap = true, silent = true, buffer = b.bufnr } + map_opts ) vim.keymap.set( "n", k.navigation_prev, helpers.prev_numbered_item, - { noremap = true, silent = true, buffer = b.bufnr } + map_opts ) end - -- Map number keys to jump to entry if num_behavior is 'jump' - if OPTS.num_behavior == "jump" then - for i = 1, OPTS.max_entries do + -- map number keys to jump to entry if num_behavior is 'jump' + if YB_OPTS.num_behavior == "jump" then + for i = 1, YB_OPTS.max_entries do vim.keymap.set("n", tostring(i), function() local target_line = nil for line_num, yank_num in pairs(b.line_yank_map) do @@ -166,27 +167,44 @@ function M.set_keymaps(b) -- use the mapping to find the original yank local yankIndex = b.line_yank_map[cursor] if yankIndex then - -- retrieve the full yank, including all lines - local text = YANKS[yankIndex] - -- close window upon selection vim.api.nvim_win_close(b.win_id, true) - helpers.smart_paste(text, REG_TYPES[yankIndex]) + helpers.smart_paste( + YB_YANKS[yankIndex], + YB_REG_TYPES[yankIndex], + true + ) + else + print("Error: Invalid selection") + end + end, map_opts) + -- paste backwards + vim.keymap.set("n", k.paste_back, function() + local cursor = vim.api.nvim_win_get_cursor(b.win_id)[1] + -- use the mapping to find the original yank + local yankIndex = b.line_yank_map[cursor] + if yankIndex then + -- close window upon selection + vim.api.nvim_win_close(b.win_id, true) + helpers.smart_paste( + YB_YANKS[yankIndex], + YB_REG_TYPES[yankIndex], + false + ) else print("Error: Invalid selection") end - end, { buffer = b.bufnr }) + end, map_opts) -- bind yank behavior vim.keymap.set("n", k.yank, function() local cursor = vim.api.nvim_win_get_cursor(b.win_id)[1] local yankIndex = b.line_yank_map[cursor] if yankIndex then - local text = YANKS[yankIndex] - vim.fn.setreg(OPTS.registers.yank_register, text) + vim.fn.setreg(YB_OPTS.registers.yank_register, YB_YANKS[yankIndex]) vim.api.nvim_win_close(b.win_id, true) end - end, { buffer = b.bufnr }) + end, map_opts) -- close popup keybinds -- REFACTOR: check if close keybind is string, handle differently diff --git a/lua/yankbank/persistence.lua b/lua/yankbank/persistence.lua index 15d67ef..36b7230 100644 --- a/lua/yankbank/persistence.lua +++ b/lua/yankbank/persistence.lua @@ -6,14 +6,14 @@ local persistence = {} ---@param entry string ---@param reg_type string function M.add_entry(entry, reg_type) - if OPTS.persist_type == "sqlite" then + if YB_OPTS.persist_type == "sqlite" then persistence:insert_yank(entry, reg_type) end end --- get current state of yanks in persistent storage function M.get_yanks() - if OPTS.persist_type == "sqlite" then + if YB_OPTS.persist_type == "sqlite" then return persistence:get_bank() end end @@ -22,9 +22,9 @@ end ---@return table ---@return table function M.setup() - if not OPTS.persist_type then + if not YB_OPTS.persist_type then return {}, {} - elseif OPTS.persist_type == "sqlite" then + elseif YB_OPTS.persist_type == "sqlite" then persistence = require("yankbank.persistence.sql").setup() return persistence:get_bank() else diff --git a/lua/yankbank/persistence/sql.lua b/lua/yankbank/persistence/sql.lua index 2baee71..5202968 100644 --- a/lua/yankbank/persistence/sql.lua +++ b/lua/yankbank/persistence/sql.lua @@ -102,15 +102,15 @@ end --- set up database persistence ---@return sqlite_tbl data function M.setup() - max_entries = OPTS.max_entries + max_entries = YB_OPTS.max_entries vim.api.nvim_create_user_command("YankBankClearDB", function() data:remove() - YANKS = {} - REG_TYPES = {} + YB_YANKS = {} + YB_REG_TYPES = {} end, {}) - if OPTS.debug == true then + if YB_OPTS.debug == true then vim.api.nvim_create_user_command("YankBankViewDB", function() print(vim.inspect(data:get())) end, {})