Neovim plugin improving access to clipboard history (mirror)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: wip api improvements

+114 -22
+1 -1
.github/workflows/docs.yaml
··· 20 20 - name: Push changes 21 21 uses: stefanzweifel/git-auto-commit-action@v4 22 22 with: 23 - commit_message: "auto-generate vimdoc" 23 + commit_message: "doc: auto-generate vimdoc" 24 24 commit_user_name: "github-actions[bot]" 25 25 commit_user_email: "github-actions[bot]@users.noreply.github.com" 26 26 commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
+34 -4
lua/yankbank/api.lua
··· 26 26 --- add an entry to yankbank 27 27 ---@param yank_text string yank text to add to YANKS table 28 28 ---@param reg_type string register type "v", "V", or "^V" (visual, v-line, v-block respectively) 29 - function M.add_entry(yank_text, reg_type) 30 - require("yankbank.clipboard").add_yank(yank_text, reg_type) 29 + ---@param pin integer|boolean? 30 + function M.add_entry(yank_text, reg_type, pin) 31 + require("yankbank.clipboard").add_yank(yank_text, reg_type, pin) 31 32 end 32 33 33 34 --- remove entry from yankbank by index 34 35 ---@param i integer index to remove 35 36 function M.remove_entry(i) 36 37 local yank_text = table.remove(YB_YANKS, i) 37 - table.remove(YB_REG_TYPES, i) 38 + local reg_type = table.remove(YB_REG_TYPES, i) 38 39 if YB_OPTS.persist_type == "sqlite" then 39 - require("yankbank.persistence.sql").data().remove_match(yank_text) 40 + require("yankbank.persistence.sql") 41 + .data() 42 + .remove_match(yank_text, reg_type) 43 + end 44 + end 45 + 46 + --- pin entry to yankbank so that it won't be removed when its position exceeds the max number of entries 47 + --- 48 + ---@param i integer index to pin 49 + function M.pin_entry(i) 50 + -- TODO: check persistence mode, max_entries 51 + -- - add third table YB_PINS to keep track of pins 52 + -- TODO: show pins differently in popup 53 + if YB_OPTS.persist_type == "sqlite" then 54 + return require("yankbank.persistence.sql") 55 + .data() 56 + .pin(YB_YANKS[i], YB_REG_TYPES[i]) 57 + end 58 + end 59 + 60 + --- unpin bank entry 61 + --- 62 + ---@param i integer index to unpin 63 + function M.unpin_entry(i) 64 + -- TODO: check persistence mode, max_entries 65 + -- - in sql.lua, add 3rd field (bool) pinned 66 + if YB_OPTS.persist_type == "sqlite" then 67 + return require("yankbank.persistence.sql") 68 + .data() 69 + .unpin(YB_YANKS[i], YB_REG_TYPES[i]) 40 70 end 41 71 end 42 72
+6 -2
lua/yankbank/clipboard.lua
··· 6 6 --- Function to add yanked text to table 7 7 ---@param text string 8 8 ---@param reg_type string 9 - function M.add_yank(text, reg_type) 9 + ---@param pin integer|boolean? 10 + function M.add_yank(text, reg_type, pin) 10 11 -- avoid adding empty strings 11 12 if text == "" and text == " " and text == "\n" then 12 13 return ··· 16 17 for i, entry in ipairs(YB_YANKS) do 17 18 if entry == text then 18 19 -- remove matched entry so it can be inserted at 1st position 20 + -- TODO: pin handling in global tables 19 21 table.remove(YB_YANKS, i) 20 22 table.remove(YB_REG_TYPES, i) 21 23 break ··· 23 25 end 24 26 25 27 -- add entry to bank 28 + -- TODO: pin handling in global tables 26 29 table.insert(YB_YANKS, 1, text) 27 30 table.insert(YB_REG_TYPES, 1, reg_type) 28 31 29 32 -- trim table size if necessary 30 33 if #YB_YANKS > YB_OPTS.max_entries then 34 + -- TODO: pin handling in global tables 31 35 table.remove(YB_YANKS) 32 36 table.remove(YB_REG_TYPES) 33 37 end 34 38 35 39 -- add entry to persistent store 36 - persistence.add_entry(text, reg_type) 40 + persistence.add_entry(text, reg_type, pin) 37 41 end 38 42 39 43 --- autocommand to listen for yank events
+3 -2
lua/yankbank/persistence.lua
··· 5 5 ---add entry from bank to 6 6 ---@param entry string 7 7 ---@param reg_type string 8 - function M.add_entry(entry, reg_type) 8 + ---@param pin integer|boolean? 9 + function M.add_entry(entry, reg_type, pin) 9 10 if YB_OPTS.persist_type == "sqlite" then 10 - persistence:insert_yank(entry, reg_type) 11 + persistence:insert_yank(entry, reg_type, pin) 11 12 end 12 13 end 13 14
+70 -13
lua/yankbank/persistence/sql.lua
··· 14 14 -- yanked text should be unique and be primary key 15 15 yank_text = { "text", unique = true, primary = true, required = true }, 16 16 reg_type = { "text", required = true }, 17 + pinned = { "integer", required = true, default = 0 }, 17 18 }, 18 19 }) 19 20 ··· 23 24 --- insert yank entry into database 24 25 ---@param yank_text string yanked text 25 26 ---@param reg_type string register type 26 - function data:insert_yank(yank_text, reg_type) 27 + ---@param pin integer|boolean? pin status of inserted entry 28 + function data:insert_yank(yank_text, reg_type, pin) 27 29 -- attempt to remove entry if count > 0 (to move potential duplicate) 30 + local is_pinned = 0 28 31 if self:count() > 0 then 29 32 db:with_open(function() 33 + -- check if entry exists in db 34 + local res = db:select("bank", { 35 + where = { 36 + yank_text = yank_text, 37 + reg_type = reg_type, 38 + }, 39 + }) 40 + 41 + -- if result is empty, proceed to insertion 42 + if #res == 0 then 43 + return 44 + end 45 + 46 + -- entry found, get pin status 47 + is_pinned = res[1].pinned 48 + 49 + -- remove entry from db so it can be moved to first position 30 50 db:eval( 31 - "DELETE FROM bank WHERE yank_text = :yank_text", 32 - { yank_text = yank_text } 51 + "DELETE FROM bank WHERE yank_text = :yank_text and reg_type = :reg_type", 52 + { yank_text = yank_text, reg_type = reg_type } 33 53 ) 34 54 end) 35 55 end 36 56 57 + -- override is_pinned if pin param is set, default to is_pinned otherwise 58 + is_pinned = (pin == 1 or pin == true) and 1 59 + or (pin == 0 or pin == false) and 0 60 + or is_pinned 61 + 37 62 -- insert entry using the eval method with parameterized query to avoid error on 'data:insert()' 38 63 db:with_open(function() 39 64 db:eval( 40 - "INSERT INTO bank (yank_text, reg_type) VALUES (:yank_text, :reg_type)", 41 - { yank_text = yank_text, reg_type = reg_type } 65 + "INSERT INTO bank (yank_text, reg_type, pinned) VALUES (:yank_text, :reg_type, :pinned)", 66 + { yank_text = yank_text, reg_type = reg_type, pinned = is_pinned } 42 67 ) 43 68 end) 44 69 ··· 51 76 if self:count() > max_entries then 52 77 -- remove the oldest entry 53 78 local oldest_entry = db:with_open(function() 54 - return db:select( 55 - "bank", 56 - { order_by = { asc = "rowid" }, limit = { 1 } } 57 - )[1] 79 + return db:select("bank", { 80 + where = { pinned = 0 }, 81 + order_by = { asc = "rowid" }, 82 + limit = { 1 }, 83 + })[1] 58 84 end) 59 85 60 86 if oldest_entry then ··· 84 110 85 111 --- remove an entry from the banks table matching input text 86 112 ---@param text string 87 - function data.remove_match(text) 113 + ---@param reg_type string 114 + function data.remove_match(text, reg_type) 88 115 db:with_open(function() 89 116 return db:eval( 90 - "DELETE FROM bank WHERE yank_text = :yank_text", 91 - { yank_text = text } 117 + "DELETE FROM bank WHERE yank_text = :yank_text and reg_type = :reg_type", 118 + { yank_text = text, reg_type = reg_type } 119 + ) 120 + end) 121 + end 122 + 123 + --- pin entry in yankbank to prevent removal 124 + ---@param text string text to match and pin 125 + ---@param reg_type string reg_type corresponding to text 126 + ---@return boolean 127 + function data.pin(text, reg_type) 128 + return db:with_open(function() 129 + -- TODO: always returns true or nothing 130 + return ( 131 + db:eval( 132 + "UPDATE bank SET pinned = 1 WHERE yank_text = :yank_text and reg_type = :reg_type", 133 + { yank_text = text, reg_type = reg_type } 134 + ) 135 + ) 136 + end) 137 + end 138 + 139 + --- unpin entry in yankbank to prevent removal 140 + ---@param text string 141 + ---@param reg_type string reg_type corresponding to text 142 + ---@return boolean 143 + function data.unpin(text, reg_type) 144 + return db:with_open(function() 145 + -- TODO: always returns true or nothing 146 + return db:eval( 147 + "UPDATE bank SET pinned = 0 WHERE yank_text = :yank_text and reg_type = :reg_type", 148 + { yank_text = text, reg_type = reg_type } 92 149 ) 93 150 end) 94 151 end ··· 105 162 max_entries = YB_OPTS.max_entries 106 163 107 164 vim.api.nvim_create_user_command("YankBankClearDB", function() 108 - data:remove() 165 + data:drop() 109 166 YB_YANKS = {} 110 167 YB_REG_TYPES = {} 111 168 end, {})