Neovim plugin improving access to clipboard history (mirror)
at main 133 lines 3.8 kB view raw
1local M = {} 2 3local state = require("yankbank.state") 4 5--- get the last zero entry in a table 6--- 7---@param t table 8---@return integer? 9local 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 16end 17 18--- Function to add yanked text to table 19---@param text string 20---@param reg_type string 21---@param pin integer|boolean? 22function M.add_yank(text, reg_type, pin) 23 -- avoid adding empty strings 24 if text == "" and text == " " and text == "\n" then 25 return 26 end 27 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() 32 33 -- check for duplicate values already inserted 34 for i, entry in ipairs(yanks) do 35 if entry == text then 36 -- remove matched entry so it can be inserted at 1st position 37 table.remove(yanks, i) 38 table.remove(reg_types, i) 39 is_pinned = table.remove(pins, i) 40 break 41 end 42 end 43 44 -- override is_pinned if pin is set 45 is_pinned = (pin == 1 or pin == true) and 1 46 or (pin == 0 or pin == false) and 0 47 or is_pinned 48 49 -- add entry to bank 50 table.insert(yanks, 1, text) 51 table.insert(reg_types, 1, reg_type) 52 table.insert(pins, 1, is_pinned) 53 54 -- trim table size if necessary 55 local opts = state.get_opts() 56 if #yanks > opts.max_entries then 57 local i = last_zero_entry(pins) 58 59 if not i or i == 1 then 60 -- WARN: undefined behavior 61 print( 62 "Warning: all YankBank entries are pinned, insertion behavior is undefined when all entries are pinned." 63 ) 64 else 65 -- remove last non-pinned entry 66 table.remove(yanks, i) 67 table.remove(reg_types, i) 68 table.remove(pins, i) 69 end 70 end 71 72 -- update state 73 state.set_yanks(yanks) 74 state.set_reg_types(reg_types) 75 state.set_pins(pins) 76 77 -- add entry to persistent store 78 require("yankbank.persistence").add_entry(text, reg_type, pin) 79end 80 81--- autocommand to listen for yank events 82function M.setup_yank_autocmd() 83 vim.api.nvim_create_autocmd("TextYankPost", { 84 callback = function() 85 -- get register information 86 local rn = vim.v.event.regname 87 88 -- check changes were made to default register 89 if rn == "" or rn == "+" then 90 local reg_type = vim.fn.getregtype(rn) 91 local yank_text = vim.fn.getreg(rn) 92 93 if not yank_text or type(yank_text) ~= "string" then 94 return 95 end 96 97 if #yank_text <= 1 then 98 return 99 end 100 101 -- lazy load initialization when first yank happens 102 require("yankbank").ensure_initialized() 103 M.add_yank(yank_text, reg_type) 104 end 105 end, 106 }) 107 108 -- poll registers when vim is focused (check for new clipboard activity) 109 local opts = state.get_opts() 110 if opts.focus_gain_poll == true then 111 vim.api.nvim_create_autocmd("FocusGained", { 112 callback = function() 113 -- get register information 114 local reg_type = vim.fn.getregtype("+") 115 local yank_text = vim.fn.getreg("+") 116 117 if not yank_text or type(yank_text) ~= "string" then 118 return 119 end 120 121 if string.len(yank_text) <= 1 then 122 return 123 end 124 125 -- lazy load initialization when first focus gain happens 126 require("yankbank").ensure_initialized() 127 M.add_yank(yank_text, reg_type) 128 end, 129 }) 130 end 131end 132 133return M