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

Configure Feed

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

chore: merged main

ptdewey f34afe83 8f1283dd

+249 -33
+26
.github/workflows/docs.yaml
··· 1 + name: Generate Vimdoc 2 + 3 + on: 4 + push: 5 + branches: 6 + - main 7 + 8 + jobs: 9 + docs: 10 + runs-on: ubuntu-latest 11 + steps: 12 + - uses: actions/checkout@v3 13 + - name: panvimdoc 14 + uses: kdheepak/panvimdoc@main 15 + with: 16 + vimdoc: yankbank-nvim 17 + version: "Neovim >= 0.7.0" 18 + demojify: true 19 + treesitter: true 20 + - name: Push changes 21 + uses: stefanzweifel/git-auto-commit-action@v4 22 + with: 23 + commit_message: "auto-generate vimdoc" 24 + commit_user_name: "github-actions[bot]" 25 + commit_user_email: "github-actions[bot]@users.noreply.github.com" 26 + commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
+3 -3
.github/workflows/pr_check.yaml
··· 7 7 stylua: 8 8 name: Stylua 9 9 runs-on: ubuntu-22.04 10 - steps: 10 + steps: 11 11 - uses: actions/checkout@v3 12 12 - uses: JohnnyMorganz/stylua-action@v3 13 13 with: ··· 22 22 - uses: actions/checkout@v3 23 23 24 24 - name: Prepare 25 - run: | 25 + run: | 26 26 sudo apt-get update 27 27 sudo apt-get install -y luarocks 28 28 sudo luarocks install luacheck 29 - 29 + 30 30 - name: Lint 31 31 run: sudo make lint
+19 -13
README.md
··· 5 5 ## What it Does 6 6 7 7 YankBank stores the N recent yanks into the unnamed register ("), then populates a popup window with these recent yanks, allowing for quick access to recent yank history. 8 - Upon opening the popup menu, the current contents of the unnamedplus (+) register are also added to the menu (if they are different than the current contents of the unnamed register). 8 + Upon opening the popup menu, the current contents of the unnamedplus (+) register are also added to the menu (if they are different from the current contents of the unnamed register). 9 9 10 10 Choosing an entry from the menu (by hitting enter) will paste it into the currently open buffer at the cursor position. 11 11 12 12 ### Screenshots 13 - 14 - <!-- ![YankBank popup window](assets/screenshot-1.png) --> 15 13 16 14 ![YankBank popup window zoomed](assets/screenshot-2.png) 17 15 ··· 54 52 | keymaps.yank | string | `"yy"` | 55 53 | keymaps.close | table of strings | `{ "<Esc>", "<C-c>", "q" }` | 56 54 | num_behavior | string defining jump behavior "prefix" or "jump" | `"prefix"` | 55 + | focus_gain_poll | boolean | `nil` | 57 56 | registers | table container for register overrides | `{ }` | 58 57 | registers.yank_register | default register to yank from popup to | `"+"` | 59 - | persist_type | string defining persistence type "memory", "sql", or "file" | `"memory"` | 58 + | persist_type | string defining persistence type "memory" or "sqlite" | `"memory"` | 60 59 | persist_path | string defining path for persistence file/db file | `"~/.local/share/nvim/lazy/yankbank-nvim"` (if installed with lazy) | 61 60 62 61 63 - If no separator is desired, pass in an empty string for sep: 62 + #### Example Configuration 63 + 64 64 ```lua 65 65 config = function() 66 66 require('yankbank').setup({ 67 - max_entries = 12, 67 + max_entries = 9, 68 68 sep = "", 69 + num_behavior = "prefix", 70 + focus_gain_poll = true, 69 71 keymaps = { 70 72 navigation_next = "j", 71 73 navigation_prev = "k", 72 74 }, 73 75 num_behavior = "prefix", 74 - persist_type = "memory", 76 + persist_type = "sqlite", 77 + registers = { 78 + yank_register = "+", 79 + }, 75 80 }) 76 81 end, 77 82 ``` 78 83 79 - 84 + If no separator is desired, pass in an empty string for `sep` 80 85 81 86 The 'num_behavior' option defines in-popup navigation behavior when hitting number keys. 82 87 - `num_behavior = "prefix"` works similar to traditional vim navigation with '3j' moving down 3 entries in the bank. ··· 84 89 - Note: If 'max_entries' is a two-digit number, there will be a delay upon pressing numbers that prefix a valid entry. 85 90 86 91 #### Persistence 87 - If persistence between sessions is desired, there is a choice between a sqlite database and a file. 88 - Both file and sqlite will (by default) create a persistent store for recent yanks in the plugin root directory. 89 - File-based persistence requires no added dependencies, but to utilize sqlite, `"kkharji/sqlite.lua"` must be added as a dependency in your config: 92 + If persistence between sessions is desired, sqlite.lua will be used to create a persistent store for recent yanks in the plugin root directory. 93 + To utilize sqlite persistence, `"kkharji/sqlite.lua"` must be added as a dependency in your config, and `persist_type` must be set to `"sqlite"`: 90 94 91 95 ```lua 92 96 -- lazy ··· 95 99 dependencies = "kkharji/sqlite.lua", 96 100 config = function() 97 101 require('yankbank').setup({ 102 + -- other options... 98 103 persist_type = "sqlite" 99 - persist_path = "/tmp/yankbank.db", 100 104 }) 101 105 end, 102 106 } 103 107 ``` 104 108 109 + The 'focus_gain_poll' option allows for enabling an additional autocommand that watches for focus gains (refocusing Neovim window), and checks for changes in the unnamedplus ('+') register, adding to yankbank when new contents are found. This allows for automatically adding text copied from other sources (like a browser) to the yankbank without the bank opening trigger. Off by default, but I highly recommend enabling it (`focus_gain_poll = true`) 110 + 105 111 ## Usage 106 112 107 113 The popup menu can be opened with the command:`:YankBank`, an entry is pasted at the current cursor position by hitting enter, and the menu can be closed by hitting escape, ctrl-c, or q. ··· 118 124 - Polling on unnamedplus register to populate bank in more intuitive manner (could be enabled as option) 119 125 - nvim-cmp integration 120 126 - fzf integration 121 - - Setup options configuring which registers are included 127 + - telescope integration 122 128 123 129 ## Alternatives 124 130
+152
doc/yankbank-nvim.txt
··· 1 + *yankbank-nvim.txt* For Neovim >= 0.7.0 Last change: 2024 June 14 2 + 3 + ============================================================================== 4 + Table of Contents *yankbank-nvim-table-of-contents* 5 + 6 + 1. YankBank |yankbank-nvim-yankbank| 7 + - What it Does |yankbank-nvim-yankbank-what-it-does| 8 + - Installation and Setup |yankbank-nvim-yankbank-installation-and-setup| 9 + - Usage |yankbank-nvim-yankbank-usage| 10 + - Potential Improvements |yankbank-nvim-yankbank-potential-improvements| 11 + - Alternatives |yankbank-nvim-yankbank-alternatives| 12 + 2. Links |yankbank-nvim-links| 13 + 14 + ============================================================================== 15 + 1. YankBank *yankbank-nvim-yankbank* 16 + 17 + A Neovim plugin for keeping track of more recent yanks and deletions and 18 + exposing them in a quick access menu. 19 + 20 + 21 + WHAT IT DOES *yankbank-nvim-yankbank-what-it-does* 22 + 23 + YankBank stores the N recent yanks into the unnamed register (“), then 24 + populates a popup window with these recent yanks, allowing for quick access to 25 + recent yank history. Upon opening the popup menu, the current contents of the 26 + unnamedplus (+) register are also added to the menu (if they are different from 27 + the current contents of the unnamed register). 28 + 29 + Choosing an entry from the menu (by hitting enter) will paste it into the 30 + currently open buffer at the cursor position. 31 + 32 + 33 + SCREENSHOTS ~ 34 + 35 + The menu is specific to the current session, and will only contain the contents 36 + of the current unnamedplus register upon opening in a completely new session. 37 + It will be populated further for each yank or deletion in that session. 38 + 39 + 40 + INSTALLATION AND SETUP *yankbank-nvim-yankbank-installation-and-setup* 41 + 42 + Lazy: 43 + 44 + >lua 45 + { 46 + "ptdewey/yankbank-nvim", 47 + config = function() 48 + require('yankbank').setup() 49 + end, 50 + } 51 + < 52 + 53 + Packer: 54 + 55 + >lua 56 + use { 57 + 'ptdewey/yankbank-nvim', 58 + config = function() 59 + require('yankbank').setup() 60 + end, 61 + } 62 + < 63 + 64 + 65 + SETUP OPTIONS ~ 66 + 67 + The setup function also supports taking in a table of options: | Option | Type 68 + | Default | 69 + |————-|——————————————–|—————-| 70 + | max_entries | integer number of entries to show in popup | `10` | | sep | 71 + string separator to show between table entries | `"-----"` | | keymaps | table 72 + containing keymap overrides | `{}` | | keymaps.navigation_next | string | `"j"` 73 + | | keymaps.navigation_prev | string | `"k"` | | keymaps.paste | string | 74 + `"<CR>"` | | keymaps.yank | string | `"yy"` | | keymaps.close | table of 75 + strings | `{ "<Esc>", "<C-c>", "q" }` | | num_behavior | string defining jump 76 + behavior "prefix" or "jump" | `"prefix"` | | focus_gain_poll | boolean | `nil` 77 + | | registers | table container for register overrides | `{ }` | | 78 + registers.yank_register | default register to yank from popup to | `"+"` | 79 + 80 + 81 + EXAMPLE CONFIGURATION 82 + 83 + >lua 84 + config = function() 85 + require('yankbank').setup({ 86 + max_entries = 9, 87 + sep = "", 88 + num_behavior = "prefix", 89 + focus_gain_poll = true, 90 + keymaps = { 91 + navigation_next = "j", 92 + navigation_prev = "k", 93 + }, 94 + registers = { 95 + yank_register = "+", 96 + }, 97 + }) 98 + end, 99 + < 100 + 101 + If no separator is desired, pass in an empty string for `sep` 102 + 103 + The 'num_behavior' option defines in-popup navigation behavior when hitting 104 + number keys. - `num_behavior = "prefix"` works similar to traditional vim 105 + navigation with '3j' moving down 3 entries in the bank. - `num_behavior = 106 + "jump"` jumps to entry matching the pressed number key (i.e. '3' jumps to 107 + entry 3) - Note: If 'max_entries' is a two-digit number, there will be a delay 108 + upon pressing numbers that prefix a valid entry. 109 + 110 + The 'focus_gain_poll' option allows for enabling an additional autocommand that 111 + watches for focus gains (refocusing Neovim window), and checks for changes in 112 + the unnamedplus ('+') register, adding to yankbank when new contents are found. 113 + This allows for automatically adding text copied from other sources (like a 114 + browser) to the yankbank without the bank opening trigger. Off by default, but 115 + I highly recommend enabling it (`focus_gain_poll = true`) 116 + 117 + 118 + USAGE *yankbank-nvim-yankbank-usage* 119 + 120 + The popup menu can be opened with the command:`:YankBank`, an entry is pasted 121 + at the current cursor position by hitting enter, and the menu can be closed by 122 + hitting escape, ctrl-c, or q. An entry from the menu can also be yanked into 123 + the unnamedplus register by hitting yy. 124 + 125 + I would personally also recommend setting a keybind to open the menu. 126 + 127 + >lua 128 + -- map to '<leader>y' 129 + vim.keymap.set("n", "<leader>y", "<cmd>YankBank<CR>", { noremap = true }) 130 + < 131 + 132 + 133 + POTENTIAL IMPROVEMENTS *yankbank-nvim-yankbank-potential-improvements* 134 + 135 + - Persistence between sessions (through either sqlite database or just a file) 136 + - nvim-cmp integration 137 + - fzf integration 138 + 139 + 140 + ALTERNATIVES *yankbank-nvim-yankbank-alternatives* 141 + 142 + - nvim-neoclip <https://github.com/AckslD/nvim-neoclip.lua> 143 + - yanky.nvim <https://github.com/gbprod/yanky.nvim> 144 + 145 + ============================================================================== 146 + 2. Links *yankbank-nvim-links* 147 + 148 + 1. *YankBank popup window zoomed*: assets/screenshot-2.png 149 + 150 + Generated by panvimdoc <https://github.com/kdheepak/panvimdoc> 151 + 152 + vim:tw=78:ts=8:noet:ft=help:norl:
+31 -8
lua/yankbank/clipboard.lua
··· 13 13 -- avoid adding empty strings 14 14 -- TODO: could block adding single characters here 15 15 if text == "" or text == " " or text == "\n" then 16 + -- if text == "" and text == " " and text == "\n" then -- NOTE: which is correct between and/or here? 16 17 return 17 18 end 18 19 19 20 -- do not update with duplicate values 20 - -- BUG: there seems to be some issues here when trying to add on pipup open 21 21 for _, entry in ipairs(yanks) do 22 22 if entry == text then 23 23 return ··· 36 36 persistence.add_entry(text, reg_type, opts) 37 37 end 38 38 39 - -- TODO: autocmd for focus gained (check system clipboard?) 40 - 41 39 -- autocommand to listen for yank events 42 40 ---@param yanks table 43 41 ---@param reg_types table ··· 47 45 callback = function() 48 46 -- get register information 49 47 local rn = vim.v.event.regname 50 - -- local reg_type = vim.fn.getregtype("+") 51 48 52 49 -- check changes wwere made to default register 53 - if vim.v.event.regname == "" or vim.v.event.regname == "+" then 50 + if rn == "" or rn == "+" then 54 51 local reg_type = vim.fn.getregtype(rn) 55 - local yanked_text = vim.fn.getreg(rn) 56 - if #yanked_text <= 1 then 52 + local yank_text = vim.fn.getreg(rn) 53 + 54 + if not yank_text or type(yank_text) ~= "string" then 57 55 return 58 56 end 59 - M.add_yank(yanks, reg_types, yanked_text, reg_type, opts) 57 + 58 + if #yank_text <= 1 then 59 + return 60 + end 61 + M.add_yank(yanks, reg_types, yank_text, reg_type, opts.max_entries) 60 62 end 61 63 end, 62 64 }) 65 + 66 + -- poll registers when vim is focused (check for new clipboard activity) 67 + if opts.focus_gain_poll == true then 68 + vim.api.nvim_create_autocmd("FocusGained", { 69 + callback = function() 70 + -- get register information 71 + local reg_type = vim.fn.getregtype("+") 72 + local yank_text = vim.fn.getreg("+") 73 + 74 + if not yank_text or type(yank_text) ~= "string" then 75 + return 76 + end 77 + 78 + if string.len(yank_text) <= 1 then 79 + return 80 + end 81 + 82 + M.add_yank(yanks, reg_types, yank_text, reg_type, opts.max_entries) 83 + end, 84 + }) 85 + end 63 86 end 64 87 65 88 return M
+15 -8
lua/yankbank/init.lua
··· 9 9 local yanks = {} 10 10 local reg_types = {} 11 11 12 - -- YANKS = {} 13 - -- REG_TYPES = {} 14 - 15 - local plugin_path = debug.getinfo(1).source:sub(2):match("(.*/).*/.*/") or "./" 16 - 17 12 -- default plugin options 18 13 local default_opts = { 19 14 max_entries = 10, 20 15 sep = "-----", 16 + focus_gain_poll = false, 17 + num_behavior = "prefix", 18 + registers = { 19 + yank_register = "+", 20 + }, 21 21 persist_type = "memory", 22 - persist_path = plugin_path .. "bank.txt", 22 + keymaps = {}, 23 23 } 24 24 25 + local plugin_path = debug.getinfo(1).source:sub(2):match("(.*/).*/.*/") or "./" 26 + 25 27 --- wrapper function for main plugin functionality 26 28 ---@param opts table 27 29 --- TODO: read from persistent database if sql persist is set (allow multi-session sync) 28 30 local function show_yank_bank(opts) 29 - -- create and fill buffer 31 + -- Parse command arguments directly if args are provided as a string 32 + opts = opts or default_opts 33 + 34 + -- initialize buffer and populate bank 30 35 local bufnr, display_lines, line_yank_map = menu.create_and_fill_buffer(yanks, reg_types, opts) 31 36 32 37 -- handle empty bank case ··· 34 39 return 35 40 end 36 41 42 + -- open window and set keybinds 37 43 local win_id = menu.open_window(bufnr, display_lines) 38 44 menu.set_keymaps(win_id, bufnr, yanks, reg_types, line_yank_map, opts) 39 45 end ··· 42 48 ---@param opts table? 43 49 function M.setup(opts) 44 50 -- merge opts with default options table 45 - opts = vim.tbl_deep_extend("force", default_opts, opts or {}) 51 + -- opts = vim.tbl_deep_extend("force", default_opts, opts or {}) 52 + opts = opts or default_opts 46 53 47 54 -- enable persistence based on opts (needs to be called before autocmd setup) 48 55 yanks, reg_types = persistence.setup(opts)
+2 -1
lua/yankbank/menu.lua
··· 112 112 local k = vim.tbl_deep_extend("force", default_keymaps, opts.keymaps or {}) 113 113 114 114 -- merge default and options keymap tables 115 - opts.registers = vim.tbl_deep_extend("force", default_registers, opts.registers or {}) 115 + opts.registers = 116 + vim.tbl_deep_extend("force", default_registers, opts.registers or {}) 116 117 117 118 -- check table for number behavior option (prefix or jump, default to prefix) 118 119 opts.num_behavior = opts.num_behavior or "prefix"
+1
lua/yankbank/persistence/sql.lua
··· 69 69 function M.setup(opts) 70 70 max_entries = opts.max_entries 71 71 72 + -- TODO: move database into plugin directory instead to allow easier uninstall 72 73 if vim.fn.isdirectory(dbdir) == 0 then 73 74 vim.fn.mkdir(dbdir, "p") 74 75 end