Neovim plugin improving access to clipboard history (mirror)

feat: remove globals and lazy load modules for better startup time

ptdewey 89635bf3 3701b59a

+303 -193
+31 -15
lua/yankbank/api.lua
··· 1 1 local M = {} 2 2 3 + local state = require("yankbank.state") 4 + 3 5 --- get a table containg a single yankbank entry by index 4 6 ---@param i integer 5 7 ---@return table 6 8 function M.get_entry(i) 7 9 return { 8 - yank_text = YB_YANKS[i], 9 - reg_type = YB_REG_TYPES[i], 10 + yank_text = state.get_yanks()[i], 11 + reg_type = state.get_reg_types()[i], 10 12 } 11 13 end 12 14 ··· 14 16 ---@return table 15 17 function M.get_all() 16 18 local out = {} 17 - for i, v in ipairs(YB_YANKS) do 19 + local yanks = state.get_yanks() 20 + local reg_types = state.get_reg_types() 21 + for i, v in ipairs(yanks) do 18 22 table.insert(out, { 19 23 yank_text = v, 20 - reg_type = YB_REG_TYPES[i], 24 + reg_type = reg_types[i], 21 25 }) 22 26 end 23 27 return out ··· 34 38 --- remove entry from yankbank by index 35 39 ---@param i integer index to remove 36 40 function M.remove_entry(i) 37 - local yank_text = table.remove(YB_YANKS, i) 38 - local reg_type = table.remove(YB_REG_TYPES, i) 39 - if YB_OPTS.persist_type == "sqlite" then 41 + local yanks = state.get_yanks() 42 + local reg_types = state.get_reg_types() 43 + local yank_text = table.remove(yanks, i) 44 + local reg_type = table.remove(reg_types, i) 45 + state.set_yanks(yanks) 46 + state.set_reg_types(reg_types) 47 + 48 + local opts = state.get_opts() 49 + if opts.persist_type == "sqlite" then 40 50 require("yankbank.persistence.sql") 41 51 .data() 42 52 .remove_match(yank_text, reg_type) ··· 47 57 --- 48 58 ---@param i integer index to pin 49 59 function M.pin_entry(i) 50 - if i > #YB_PINS then 60 + local pins = state.get_pins() 61 + if i > #pins then 51 62 return 52 63 end 53 64 54 65 -- TODO: show pins differently in popup (could use different hl_groups for pinned entries?) 55 - YB_PINS[i] = 1 66 + pins[i] = 1 67 + state.set_pins(pins) 56 68 57 - if YB_OPTS.persist_type == "sqlite" then 69 + local opts = state.get_opts() 70 + if opts.persist_type == "sqlite" then 58 71 return require("yankbank.persistence.sql") 59 72 .data() 60 - .pin(YB_YANKS[i], YB_REG_TYPES[i]) 73 + .pin(state.get_yanks()[i], state.get_reg_types()[i]) 61 74 end 62 75 end 63 76 ··· 65 78 --- 66 79 ---@param i integer index to unpin 67 80 function M.unpin_entry(i) 68 - if i > #YB_PINS then 81 + local pins = state.get_pins() 82 + if i > #pins then 69 83 return 70 84 end 71 85 72 86 -- TODO: update popup pin highlight 73 - YB_PINS[i] = 0 87 + pins[i] = 0 88 + state.set_pins(pins) 74 89 75 - if YB_OPTS.persist_type == "sqlite" then 90 + local opts = state.get_opts() 91 + if opts.persist_type == "sqlite" then 76 92 return require("yankbank.persistence.sql") 77 93 .data() 78 - .unpin(YB_YANKS[i], YB_REG_TYPES[i]) 94 + .unpin(state.get_yanks()[i], state.get_reg_types()[i]) 79 95 end 80 96 end 81 97
+42 -13
lua/yankbank/clipboard.lua
··· 1 1 local M = {} 2 2 3 + local state = require("yankbank.state") 4 + 5 + --- get the last zero entry in a table 6 + --- 7 + ---@param t table 8 + ---@return integer? 9 + local function last_zero_entry(t) 10 + for i = #t, 1, -1 do 11 + if t[i] == 0 then 12 + return i 13 + end 14 + end 15 + return nil 16 + end 17 + 3 18 --- Function to add yanked text to table 4 19 ---@param text string 5 20 ---@param reg_type string ··· 11 26 end 12 27 13 28 local is_pinned = 0 29 + local yanks = state.get_yanks() 30 + local reg_types = state.get_reg_types() 31 + local pins = state.get_pins() 14 32 15 33 -- check for duplicate values already inserted 16 - for i, entry in ipairs(YB_YANKS) do 34 + for i, entry in ipairs(yanks) do 17 35 if entry == text then 18 36 -- remove matched entry so it can be inserted at 1st position 19 - table.remove(YB_YANKS, i) 20 - table.remove(YB_REG_TYPES, i) 21 - is_pinned = table.remove(YB_PINS, i) 37 + table.remove(yanks, i) 38 + table.remove(reg_types, i) 39 + is_pinned = table.remove(pins, i) 22 40 break 23 41 end 24 42 end ··· 29 47 or is_pinned 30 48 31 49 -- add entry to bank 32 - table.insert(YB_YANKS, 1, text) 33 - table.insert(YB_REG_TYPES, 1, reg_type) 34 - table.insert(YB_PINS, 1, is_pinned) 50 + table.insert(yanks, 1, text) 51 + table.insert(reg_types, 1, reg_type) 52 + table.insert(pins, 1, is_pinned) 35 53 36 54 -- trim table size if necessary 37 - if #YB_YANKS > YB_OPTS.max_entries then 38 - local i = require("yankbank.utils").last_zero_entry(YB_PINS) 55 + local opts = state.get_opts() 56 + if #yanks > opts.max_entries then 57 + local i = last_zero_entry(pins) 39 58 40 59 if not i or i == 1 then 41 60 -- WARN: undefined behavior ··· 44 63 ) 45 64 else 46 65 -- remove last non-pinned entry 47 - table.remove(YB_YANKS, i) 48 - table.remove(YB_REG_TYPES, i) 49 - table.remove(YB_PINS, i) 66 + table.remove(yanks, i) 67 + table.remove(reg_types, i) 68 + table.remove(pins, i) 50 69 end 51 70 end 71 + 72 + -- update state 73 + state.set_yanks(yanks) 74 + state.set_reg_types(reg_types) 75 + state.set_pins(pins) 52 76 53 77 -- add entry to persistent store 54 78 require("yankbank.persistence").add_entry(text, reg_type, pin) ··· 74 98 return 75 99 end 76 100 101 + -- lazy load initialization when first yank happens 102 + require("yankbank").ensure_initialized() 77 103 M.add_yank(yank_text, reg_type) 78 104 end 79 105 end, 80 106 }) 81 107 82 108 -- poll registers when vim is focused (check for new clipboard activity) 83 - if YB_OPTS.focus_gain_poll == true then 109 + local opts = state.get_opts() 110 + if opts.focus_gain_poll == true then 84 111 vim.api.nvim_create_autocmd("FocusGained", { 85 112 callback = function() 86 113 -- get register information ··· 95 122 return 96 123 end 97 124 125 + -- lazy load initialization when first focus gain happens 126 + require("yankbank").ensure_initialized() 98 127 M.add_yank(yank_text, reg_type) 99 128 end, 100 129 })
-66
lua/yankbank/data.lua
··· 1 - local M = {} 2 - 3 - --- reformat yanks table for popup 4 - ---@return table, table 5 - function M.get_display_lines() 6 - local display_lines = {} 7 - local line_yank_map = {} 8 - local yank_num = 0 9 - 10 - -- calculate the maximum width needed for the yank numbers 11 - local max_digits = #tostring(#YB_YANKS) 12 - 13 - -- assumes yanks is table of strings 14 - for i, yank in ipairs(YB_YANKS) do 15 - yank_num = yank_num + 1 16 - 17 - local yank_lines = yank 18 - if type(yank) == "string" then 19 - -- remove trailing newlines 20 - yank = yank:gsub("\n$", "") 21 - yank_lines = vim.split(yank, "\n", { plain = true }) 22 - end 23 - 24 - local leading_space, leading_space_length 25 - 26 - -- determine the number of leading whitespaces on the first line 27 - if #yank_lines > 0 then 28 - leading_space = yank_lines[1]:match("^(%s*)") 29 - leading_space_length = #leading_space 30 - end 31 - 32 - for j, line in ipairs(yank_lines) do 33 - if j == 1 then 34 - -- Format the line number with uniform spacing 35 - local lineNumber = 36 - string.format("%" .. max_digits .. "d: ", yank_num) 37 - line = line:sub(leading_space_length + 1) 38 - table.insert(display_lines, lineNumber .. line) 39 - else 40 - -- Remove the same amount of leading whitespace as on the first line 41 - line = line:sub(leading_space_length + 1) 42 - -- Use spaces equal to the line number's reserved space to align subsequent lines 43 - table.insert( 44 - display_lines, 45 - string.rep(" ", max_digits + 2) .. line 46 - ) 47 - end 48 - table.insert(line_yank_map, i) 49 - end 50 - 51 - if i < #YB_YANKS then 52 - -- Add a visual separator between yanks, aligned with the yank content 53 - if YB_OPTS.sep ~= "" then 54 - table.insert( 55 - display_lines, 56 - string.rep(" ", max_digits + 2) .. YB_OPTS.sep 57 - ) 58 - end 59 - table.insert(line_yank_map, false) 60 - end 61 - end 62 - 63 - return display_lines, line_yank_map 64 - end 65 - 66 - return M
+58 -43
lua/yankbank/init.lua
··· 1 1 local M = {} 2 2 3 + local initialized = false 4 + 5 + function M.ensure_initialized() 6 + if initialized then 7 + return 8 + end 9 + 10 + local state = require("yankbank.state") 11 + local persistence = require("yankbank.persistence") 12 + 13 + -- enable persistence based on opts (needs to be called before autocmd setup) 14 + local yanks, reg_types, pins = persistence.setup() 15 + state.init(yanks, reg_types, pins, state.get_opts()) 16 + 17 + initialized = true 18 + end 19 + 20 + --- wrapper function for main plugin functionality 21 + local function show_yank_bank() 22 + M.ensure_initialized() 23 + 24 + local state = require("yankbank.state") 25 + local menu = require("yankbank.menu") 26 + 27 + -- set up menu keybinds from defaults and state.get_opts().keymaps 28 + menu.setup() 29 + 30 + local persistence = require("yankbank.persistence") 31 + local yanks = persistence.get_yanks() or state.get_yanks() 32 + state.set_yanks(yanks) 33 + 34 + -- initialize buffer and populate bank 35 + local buf_data = menu.create_and_fill_buffer() 36 + if not buf_data then 37 + return 38 + end 39 + 40 + -- open popup window 41 + buf_data.win_id = menu.open_window(buf_data) 42 + 43 + -- set popup keybinds 44 + menu.set_keymaps(buf_data) 45 + end 46 + 3 47 -- plugin setup 4 48 ---@param opts? table 5 49 function M.setup(opts) 6 - -- define global variables 7 - YB_YANKS = {} 8 - YB_REG_TYPES = {} 9 - YB_PINS = {} 10 - YB_OPTS = {} 11 - 12 - -- local imports 13 - local clipboard = require("yankbank.clipboard") 14 - local persistence = require("yankbank.persistence") 15 - 16 50 -- default plugin options 17 51 local default_opts = { 18 52 max_entries = 10, ··· 27 61 db_path = nil, 28 62 bind_indices = nil, 29 63 } 30 - 31 - --- wrapper function for main plugin functionality 32 - local function show_yank_bank() 33 - local menu = require("yankbank.menu") 34 - 35 - -- set up menu keybinds from defaults and YB_OPTS.keymaps 36 - menu.setup() 37 - 38 - YB_YANKS = persistence.get_yanks() or YB_YANKS 39 - 40 - -- initialize buffer and populate bank 41 - local buf_data = menu.create_and_fill_buffer() 42 - if not buf_data then 43 - return 44 - end 45 - 46 - -- open popup window 47 - buf_data.win_id = menu.open_window(buf_data) 48 - 49 - -- set popup keybinds 50 - menu.set_keymaps(buf_data) 51 - end 52 64 53 65 -- merge opts with default options table 54 - YB_OPTS = vim.tbl_deep_extend("keep", opts or {}, default_opts) 66 + local merged_opts = vim.tbl_deep_extend("keep", opts or {}, default_opts) 55 67 56 - -- enable persistence based on opts (needs to be called before autocmd setup) 57 - YB_YANKS, YB_REG_TYPES, YB_PINS = persistence.setup() 58 - 59 - -- create clipboard autocmds 60 - clipboard.setup_yank_autocmd() 68 + -- store config in state module (lazy loaded when needed) 69 + local state = require("yankbank.state") 70 + state.set_opts(merged_opts) 61 71 62 72 -- create user command 63 73 vim.api.nvim_create_user_command("YankBank", function() 64 74 show_yank_bank() 65 75 end, { desc = "Show Recent Yanks" }) 76 + 77 + -- create clipboard autocmds 78 + require("yankbank.clipboard").setup_yank_autocmd() 66 79 67 80 -- Bind 1-n if `bind_indices` is set to a string 68 - if YB_OPTS.bind_indices then 69 - for i = 1, YB_OPTS.max_entries do 70 - vim.keymap.set("n", YB_OPTS.bind_indices .. i, function() 81 + if merged_opts.bind_indices then 82 + for i = 1, merged_opts.max_entries do 83 + vim.keymap.set("n", merged_opts.bind_indices .. i, function() 84 + M.ensure_initialized() 85 + local state = require("yankbank.state") 71 86 require("yankbank.helpers").smart_paste( 72 - YB_YANKS[i], 73 - YB_REG_TYPES[i], 87 + state.get_yanks()[i], 88 + state.get_reg_types()[i], 74 89 true 75 90 ) 76 91 end, {
+101 -27
lua/yankbank/menu.lua
··· 1 1 local M = {} 2 2 3 - local data = require("yankbank.data") 4 - local helpers = require("yankbank.helpers") 3 + local state = require("yankbank.state") 5 4 6 5 -- default plugin keymaps 7 6 local default_keymaps = { ··· 18 17 yank_register = "+", 19 18 } 20 19 21 - -- local YB_OPTS.keymaps = {} 22 - 23 20 function M.setup() 21 + local opts = state.get_opts() 24 22 -- merge default and options keymap tables 25 - YB_OPTS.keymaps = 26 - vim.tbl_deep_extend("force", default_keymaps, YB_OPTS.keymaps or {}) 23 + opts.keymaps = 24 + vim.tbl_deep_extend("force", default_keymaps, opts.keymaps or {}) 27 25 -- merge default and options register tables 28 - YB_OPTS.registers = 29 - vim.tbl_deep_extend("force", default_registers, YB_OPTS.registers or {}) 26 + opts.registers = 27 + vim.tbl_deep_extend("force", default_registers, opts.registers or {}) 30 28 31 29 -- check table for number behavior option (prefix or jump, default to prefix) 32 - YB_OPTS.num_behavior = YB_OPTS.num_behavior or "prefix" 30 + opts.num_behavior = opts.num_behavior or "prefix" 31 + 32 + state.set_opts(opts) 33 + end 34 + 35 + --- reformat yanks table for popup 36 + ---@return table, table 37 + local function get_display_lines() 38 + local display_lines = {} 39 + local line_yank_map = {} 40 + local yank_num = 0 41 + 42 + local yanks = state.get_yanks() 43 + local opts = state.get_opts() 44 + 45 + -- calculate the maximum width needed for the yank numbers 46 + local max_digits = #tostring(#yanks) 47 + 48 + -- assumes yanks is table of strings 49 + for i, yank in ipairs(yanks) do 50 + yank_num = yank_num + 1 51 + 52 + local yank_lines = yank 53 + if type(yank) == "string" then 54 + -- remove trailing newlines 55 + yank = yank:gsub("\n$", "") 56 + yank_lines = vim.split(yank, "\n", { plain = true }) 57 + end 58 + 59 + local leading_space, leading_space_length 60 + 61 + -- determine the number of leading whitespaces on the first line 62 + if #yank_lines > 0 then 63 + leading_space = yank_lines[1]:match("^(%s*)") 64 + leading_space_length = #leading_space 65 + end 66 + 67 + for j, line in ipairs(yank_lines) do 68 + if j == 1 then 69 + -- Format the line number with uniform spacing 70 + local lineNumber = 71 + string.format("%" .. max_digits .. "d: ", yank_num) 72 + line = line:sub(leading_space_length + 1) 73 + table.insert(display_lines, lineNumber .. line) 74 + else 75 + -- Remove the same amount of leading whitespace as on the first line 76 + line = line:sub(leading_space_length + 1) 77 + -- Use spaces equal to the line number's reserved space to align subsequent lines 78 + table.insert( 79 + display_lines, 80 + string.rep(" ", max_digits + 2) .. line 81 + ) 82 + end 83 + table.insert(line_yank_map, i) 84 + end 85 + 86 + if i < #yanks then 87 + -- Add a visual separator between yanks, aligned with the yank content 88 + if opts.sep ~= "" then 89 + table.insert( 90 + display_lines, 91 + string.rep(" ", max_digits + 2) .. opts.sep 92 + ) 93 + end 94 + table.insert(line_yank_map, false) 95 + end 96 + end 97 + 98 + return display_lines, line_yank_map 33 99 end 34 100 35 101 --- Container class for YankBank buffer related variables ··· 43 109 ---@return YankBankBufData? 44 110 function M.create_and_fill_buffer() 45 111 -- stop if yanks or register types table is empty 46 - if #YB_YANKS == 0 or #YB_REG_TYPES == 0 then 112 + local yanks = state.get_yanks() 113 + local reg_types = state.get_reg_types() 114 + if #yanks == 0 or #reg_types == 0 then 47 115 print("No yanks to show.") 48 116 return nil 49 117 end ··· 55 123 local current_filetype = vim.bo.filetype 56 124 vim.api.nvim_set_option_value("filetype", current_filetype, { buf = bufnr }) 57 125 58 - local display_lines, line_yank_map = data.get_display_lines() 126 + local display_lines, line_yank_map = get_display_lines() 59 127 60 128 -- replace current buffer contents with updated table 61 129 vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, display_lines) ··· 119 187 function M.set_keymaps(b) 120 188 -- key mappings for selection and closing the popup 121 189 local map_opts = { noremap = true, silent = true, buffer = b.bufnr } 190 + local opts = state.get_opts() 191 + 192 + local helpers = require("yankbank.helpers") 122 193 123 194 -- popup buffer navigation binds 124 - if YB_OPTS.num_behavior == "prefix" then 125 - vim.keymap.set("n", YB_OPTS.keymaps.navigation_next, function() 195 + if opts.num_behavior == "prefix" then 196 + vim.keymap.set("n", opts.keymaps.navigation_next, function() 126 197 local count = vim.v.count1 > 0 and vim.v.count1 or 1 127 198 helpers.next_numbered_item(count) 128 199 return "" 129 200 end, { noremap = true, silent = true, buffer = b.bufnr }) 130 - vim.keymap.set("n", YB_OPTS.keymaps.navigation_prev, function() 201 + vim.keymap.set("n", opts.keymaps.navigation_prev, function() 131 202 local count = vim.v.count1 > 0 and vim.v.count1 or 1 132 203 helpers.prev_numbered_item(count) 133 204 return "" ··· 135 206 else 136 207 vim.keymap.set( 137 208 "n", 138 - YB_OPTS.keymaps.navigation_next, 209 + opts.keymaps.navigation_next, 139 210 helpers.next_numbered_item, 140 211 map_opts 141 212 ) 142 213 vim.keymap.set( 143 214 "n", 144 - YB_OPTS.keymaps.navigation_prev, 215 + opts.keymaps.navigation_prev, 145 216 helpers.prev_numbered_item, 146 217 map_opts 147 218 ) 148 219 end 149 220 150 221 -- map number keys to jump to entry if num_behavior is 'jump' 151 - if YB_OPTS.num_behavior == "jump" then 152 - for i = 1, YB_OPTS.max_entries do 222 + if opts.num_behavior == "jump" then 223 + for i = 1, opts.max_entries do 153 224 vim.keymap.set("n", tostring(i), function() 154 225 local target_line = nil 155 226 for line_num, yank_num in pairs(b.line_yank_map) do ··· 166 237 end 167 238 168 239 -- bind paste behavior 169 - vim.keymap.set("n", YB_OPTS.keymaps.paste, function() 240 + vim.keymap.set("n", opts.keymaps.paste, function() 170 241 local cursor = vim.api.nvim_win_get_cursor(b.win_id)[1] 171 242 -- use the mapping to find the original yank 172 243 local yankIndex = b.line_yank_map[cursor] ··· 174 245 -- close window upon selection 175 246 vim.api.nvim_win_close(b.win_id, true) 176 247 helpers.smart_paste( 177 - YB_YANKS[yankIndex], 178 - YB_REG_TYPES[yankIndex], 248 + state.get_yanks()[yankIndex], 249 + state.get_reg_types()[yankIndex], 179 250 true 180 251 ) 181 252 else ··· 183 254 end 184 255 end, map_opts) 185 256 -- paste backwards 186 - vim.keymap.set("n", YB_OPTS.keymaps.paste_back, function() 257 + vim.keymap.set("n", opts.keymaps.paste_back, function() 187 258 local cursor = vim.api.nvim_win_get_cursor(b.win_id)[1] 188 259 -- use the mapping to find the original yank 189 260 local yankIndex = b.line_yank_map[cursor] ··· 191 262 -- close window upon selection 192 263 vim.api.nvim_win_close(b.win_id, true) 193 264 helpers.smart_paste( 194 - YB_YANKS[yankIndex], 195 - YB_REG_TYPES[yankIndex], 265 + state.get_yanks()[yankIndex], 266 + state.get_reg_types()[yankIndex], 196 267 false 197 268 ) 198 269 else ··· 201 272 end, map_opts) 202 273 203 274 -- bind yank behavior 204 - vim.keymap.set("n", YB_OPTS.keymaps.yank, function() 275 + vim.keymap.set("n", opts.keymaps.yank, function() 205 276 local cursor = vim.api.nvim_win_get_cursor(b.win_id)[1] 206 277 local yankIndex = b.line_yank_map[cursor] 207 278 if yankIndex then 208 - vim.fn.setreg(YB_OPTS.registers.yank_register, YB_YANKS[yankIndex]) 279 + vim.fn.setreg( 280 + opts.registers.yank_register, 281 + state.get_yanks()[yankIndex] 282 + ) 209 283 vim.api.nvim_win_close(b.win_id, true) 210 284 end 211 285 end, map_opts) 212 286 213 287 -- close popup keybinds 214 288 -- REFACTOR: check if close keybind is string, handle differently 215 - for _, map in ipairs(YB_OPTS.keymaps.close) do 289 + for _, map in ipairs(opts.keymaps.close) do 216 290 vim.keymap.set("n", map, function() 217 291 vim.api.nvim_win_close(b.win_id, true) 218 292 end, map_opts)
+8 -4
lua/yankbank/persistence.lua
··· 1 1 local M = {} 2 2 3 + local state = require("yankbank.state") 3 4 local persistence = {} 4 5 5 6 ---add entry from bank to ··· 7 8 ---@param reg_type string 8 9 ---@param pin integer|boolean? 9 10 function M.add_entry(entry, reg_type, pin) 10 - if YB_OPTS.persist_type == "sqlite" then 11 + local opts = state.get_opts() 12 + if opts.persist_type == "sqlite" then 11 13 persistence:insert_yank(entry, reg_type, pin) 12 14 end 13 15 end 14 16 15 17 --- get current state of yanks in persistent storage 16 18 function M.get_yanks() 17 - if YB_OPTS.persist_type == "sqlite" then 19 + local opts = state.get_opts() 20 + if opts.persist_type == "sqlite" then 18 21 return persistence:get_bank() 19 22 end 20 23 end ··· 24 27 ---@return table 25 28 ---@return table 26 29 function M.setup() 27 - if not YB_OPTS.persist_type then 30 + local opts = state.get_opts() 31 + if not opts.persist_type then 28 32 return {}, {}, {} 29 - elseif YB_OPTS.persist_type == "sqlite" then 33 + elseif opts.persist_type == "sqlite" then 30 34 persistence = require("yankbank.persistence.sql").setup() 31 35 return persistence:get_bank() 32 36 else
+14 -9
lua/yankbank/persistence/sql.lua
··· 1 1 local M = {} 2 2 3 3 local sqlite = require("sqlite") 4 + local state = require("yankbank.state") 4 5 5 - local dbdir = YB_OPTS.db_path 6 - or debug.getinfo(1).source:sub(2):match("(.*/).*/.*/.*/") 7 - or "./" 8 - -- or vim.fn.stdpath("data") 6 + local function get_db_path() 7 + local opts = state.get_opts() 8 + return opts.db_path 9 + or debug.getinfo(1).source:sub(2):match("(.*/).*/.*/.*/") 10 + or "./" 11 + end 12 + 9 13 local max_entries = 10 10 14 11 15 ---@class YankBankDB:sqlite_db 12 16 ---@field bank sqlite_tbl 13 17 ---@field bank sqlite_tbl 14 18 local db = sqlite({ 15 - uri = dbdir .. "/yankbank.db", 19 + uri = get_db_path() .. "/yankbank.db", 16 20 bank = { 17 21 -- yanked text should be unique and be primary key 18 22 yank_text = { "text", unique = true, primary = true, required = true }, ··· 178 182 --- set up database persistence 179 183 ---@return sqlite_tbl data 180 184 function M.setup() 181 - max_entries = YB_OPTS.max_entries 185 + local opts = state.get_opts() 186 + max_entries = opts.max_entries 182 187 183 188 vim.api.nvim_create_user_command("YankBankClearDB", function() 184 189 data:drop() 185 - YB_YANKS = {} 186 - YB_REG_TYPES = {} 190 + state.set_yanks({}) 191 + state.set_reg_types({}) 187 192 end, {}) 188 193 189 - if YB_OPTS.debug == true then 194 + if opts.debug == true then 190 195 vim.api.nvim_create_user_command("YankBankViewDB", function() 191 196 print(vim.inspect(data:get())) 192 197 end, {})
+49
lua/yankbank/state.lua
··· 1 + local M = {} 2 + 3 + local state = { 4 + yanks = {}, 5 + reg_types = {}, 6 + pins = {}, 7 + opts = {} 8 + } 9 + 10 + function M.get_yanks() 11 + return state.yanks 12 + end 13 + 14 + function M.set_yanks(yanks) 15 + state.yanks = yanks 16 + end 17 + 18 + function M.get_reg_types() 19 + return state.reg_types 20 + end 21 + 22 + function M.set_reg_types(reg_types) 23 + state.reg_types = reg_types 24 + end 25 + 26 + function M.get_pins() 27 + return state.pins 28 + end 29 + 30 + function M.set_pins(pins) 31 + state.pins = pins 32 + end 33 + 34 + function M.get_opts() 35 + return state.opts 36 + end 37 + 38 + function M.set_opts(opts) 39 + state.opts = opts 40 + end 41 + 42 + function M.init(yanks, reg_types, pins, opts) 43 + state.yanks = yanks or {} 44 + state.reg_types = reg_types or {} 45 + state.pins = pins or {} 46 + state.opts = opts or {} 47 + end 48 + 49 + return M
-16
lua/yankbank/utils.lua
··· 1 - local M = {} 2 - 3 - --- get the last zero entry in a table 4 - --- 5 - ---@param t table 6 - ---@return integer? 7 - function M.last_zero_entry(t) 8 - for i = #t, 1, -1 do 9 - if t[i] == 0 then 10 - return i 11 - end 12 - end 13 - return nil 14 - end 15 - 16 - return M