This is a story about Bob 👷.
Bob loves vim ❤️.
Bob likes to yank ©️.
Bob knows about registers but sometimes forgets them ®️.
This is what happens to Bob everyday 🚧:
- Bob yanks some line. 😀
- Bob yanks another line. 🤔
- Bob realises he actually wanted the first. 🙁
- But it is gone and Bob is now sad. 😢
Don't be like Bob, use neoclip! 🎉
neoclip
is a clipboard manager for neovim inspired by for example clipmenu
.
It records everything that gets yanked in your vim session (up to a limit which is by default 1000 entries but can be configured).
You can then select an entry in the history using telescope
which then gets populated in a register of your choice.
That's it!
Oh, some more things, you can define an optional filter if you don't want some things to be saved and custom actions to take.
Hold on, neoclip
optionally also supports persistent history between sessions powered by sqlite.lua
.
use {
"AckslD/nvim-neoclip.lua",
config = function()
require('neoclip').setup()
end,
}
When require('neoclip').setup()
is called, only the autocommand (for TextYankPost
event) is setup to save yanked things. This means that telescope
is not required at this point if you lazy load it.
If you want to use persistent history between sessions you also need sqlite.lua
installed, for example by:
use {
"AckslD/nvim-neoclip.lua",
requires = {'tami5/sqlite.lua', module = 'sqlite'},
config = function()
require('neoclip').setup()
end,
}
You can configure neoclip
by passing a table to setup
(all are optional).
The following are the defaults and the keys are explained below:
use {
"AckslD/nvim-neoclip.lua",
config = function()
require('neoclip').setup({
history = 1000,
enable_persistant_history = false,
db_path = vim.fn.stdpath("data") .. "/databases/neoclip.sqlite3",
filter = nil,
preview = true,
default_register = '"',
content_spec_column = false,
on_paste = {
set_reg = false,
},
keys = {
i = {
select = '<cr>',
paste = '<c-p>',
paste_behind = '<c-k>',
custom = {},
},
n = {
select = '<cr>',
paste = 'p',
paste_behind = 'P',
custom = {},
},
},
})
end,
}
history
: The max number of entries to store (default 1000).enable_persistant_history
: If set totrue
the history is stored onVimLeavePre
usingsqlite.lua
and lazy loaded when querying.db_path
: The path to the sqlite database to store history ifenable_persistant_history=true
. Defaults tovim.fn.stdpath("data") .. "/databases/neoclip.sqlite3
which on my system is~/.local/share/nvim/databases/neoclip.sqlite3
filter
: A function to filter what entries to store (default all are stored). This function filter should returntrue
(include the yanked entry) orfalse
(don't include it) based on a table as the only argument, which has the following keys:event
: The event fromTextYankPost
(see:help TextYankPost
for which keys it contains).filetype
: The filetype of the buffer where the yank happened.buffer_name
: The name of the buffer where the yank happened.
preview
: Whether to show a preview (default) of the current entry or not. Useful for for example multiline yanks. When yanking the filetype is recorded in order to enable correct syntax highlighting in the preview. NOTE: in order to use the dynamic title showing the type of content and number of lines you need to configuretelescope
with thedynamic_preview_title = true
option.default_register
: What register to by default when not specifying (e.g.Telescope neoclip
). Can be a string such as'"'
(single register) or a table of strings such as{'"', '+', '*'}
.content_spec_colunm
: Can be set totrue
(defaultfalse
) to use instead of the preview. It will only show the type and number of lines next to the first line of the entry.on_paste
:set_reg
: if the register when pressing the key to paste directly.
keys
: keys to use for the different actions in inserti
and normal moden
. You can also use thecustom
entry to specify custom actions to take on certain key-presses, see below for more details. NOTE: these are only set in thetelescope
buffer and you need to setup your own keybindings to for example opentelescope
.
See screenshot section below for how the settings above might affect the looks.
You can specify custom actions in the keys
entry in the settings.
For example you can do:
require('neoclip').setup({
...
keys = {
...
n = {
...
custom = {
['<space>'] = function(opts)
print(vim.inspect(opts))
end,
},
},
},
})
which when pressing <space>
in normal mode will print something like:
{
register_names = { '"' },
entry = {
contents = { "which when pressing `<space>` in normal mode will print something like:" },
filetype = "markdown",
regtype = "l"
}
}
to do your custom action and also populate a register and/or paste you can call neoclip
s built-in handlers, such as:
require('neoclip').setup({
...
keys = {
...
n = {
...
custom = {
['<space>'] = function(opts)
-- do your stuff
-- ...
local handlers = require('neoclip.handlers')
-- optionally set the registers with the entry
-- handlers.set_registers(opts.register_names, opts.entry)
-- optionally paste entry
-- handlers.paste(opts.entry, 'p')
-- optionally paste entry behind
-- handlers.paste(opts.entry, 'P')
end,
},
},
},
})
Yank all you want and then do:
:Telescope neoclip
which will show you a history of the yanks that happened in the current session.
If you pick (default <cr>
) one this will then replace the current "
(unnamed) register.
If you instead want to directly paste it you can press by default <c-p>
in insert mode and p
in normal.
Paste behind is by default <c-k>
and P
respectively.
If you want to replace another register with an entry from the history you can do for example:
:Telescope neoclip a
which will replace register a
.
The register [0-9a-z]
and default
("
) are supported.
The following special registers are support:
"
:Telescope neoclip unnamed
*
:Telescope neoclip star
+
:Telescope neoclip plus
and Telescope neoclip
(and Telescope neoclip default
) will use what you set default_register
in the setup
.
You can also specify more registers to populate in a single command with the extra
keyword argument which
supports registers separated by comma, for example:
:Telescope neoclip a extra=star,plus,b
If you temporarily don't want neoclip
to record anything you can use the following calls:
:lua require('neoclip').start()
:lua require('neoclip').stop()
:lua require('neoclip').toggle()
- If you lazy load
telescope
withpacker
with for example the keymodule = telescope
, then it's better to use e.g.:lua require('telescope').extensions.neoclip.default()
than:Telescope neoclip
(or:lua require('telescope').extensions.neoclip['<reg>']()
over:Telescope neoclip <reg>
) for keybindings since it will properly loadtelescope
before calling the extension.
- For some plugin managers it seems necessary to do
before being able to call
:lua require('telescope').load_extension('neoclip')
:Telescope neoclip
(packer does not seem to need this). However,:lua require('telescope').extensions.neoclip.default()
seems to work without having to load. - If using
packer
, don't forget toPackerCompile
after adding the plugin.