1

Regenerate nvim config

This commit is contained in:
2024-06-02 03:29:20 +02:00
parent 75eea0c030
commit ef2e28883d
5576 changed files with 604886 additions and 503 deletions

View File

@ -0,0 +1,47 @@
name: Integration
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 7 * * 1'
jobs:
test:
name: Tests
runs-on: ubuntu-latest
strategy:
matrix:
nvim-versions: ['stable', 'nightly']
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: rhysd/action-setup-vim@v1
with:
neovim: true
version: ${{ matrix.nvim-versions }}
- name: Setup lua
uses: leafo/gh-actions-lua@v8
with:
luaVersion: '5.1.5'
- name: Setup luarocks
uses: leafo/gh-actions-luarocks@v4
- name: Install dependencies
run: |
luarocks install luacheck
- name: Run linter
run: luacheck lua/ spec/
- name: Run tests
run: make test
stylua:
name: Check codestyle
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: JohnnyMorganz/stylua-action@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: latest
args: --check .

View File

@ -0,0 +1,22 @@
name: panvimdoc
on:
push:
branches: [main]
jobs:
docs:
runs-on: ubuntu-latest
name: pandoc to vimdoc
steps:
- uses: actions/checkout@v2
- name: panvimdoc
uses: kdheepak/panvimdoc@main
with:
vimdoc: yanky
description: Improved Yank an Put functionalities for Neovim
version: 'NVIM v0.6.0'
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: 'chore: auto generate docs'
branch: ${{ github.head_ref }}

View File

@ -0,0 +1,3 @@
doc/tags
.spec
.luarc.json

View File

@ -0,0 +1 @@
globals = { "vim" }

View File

@ -0,0 +1,3 @@
# Contributor Code of Conduct
[Don't be a jerk.](https://meta.wikimedia.org/wiki/Don%27t_be_a_jerk)

View File

@ -0,0 +1,12 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Copyright (C) 2022 Gilles Roustan <contact@gb-prod.fr>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@ -0,0 +1,4 @@
test:
@nvim --headless -u spec/init.lua -c "PlenaryBustedDirectory spec/ { minimal_init = 'spec//init.lua' }"

View File

@ -0,0 +1,794 @@
# 🍃 yanky.nvim
![Lua](https://img.shields.io/badge/Made%20with%20Lua-blueviolet.svg?style=for-the-badge&logo=lua)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/gbprod/yanky.nvim/integration.yml?branch=main&style=for-the-badge)](https://github.com/gbprod/yanky.nvim/actions/workflows/integration.yml)
The aim of `yanky.nvim` is to improve yank and put functionalities for Neovim.
French slogan:
> "Vas-y Yanky, c'est bon !" - Yanky Vincent
Or in English:
> "Yanky-ki-yay, motherf\*cker" - John McYanky
## ✨ Features
- 🖇️ Yank-ring
- 📜 Yank history picker
- 💡 Highlight put and yanked text
- ⤵️ Preserve cursor position on yank
- ⭐ Special put
- ⚓ Text object
## ⚡️ Requirements
Requires neovim > `0.9.0`.
## 📦 Installation
Install the plugin with your preferred package manager:
### [lazy.nvim](https://github.com/folke/lazy.nvim)
```lua
{
"gbprod/yanky.nvim",
opts = {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
},
}
```
<details>
<summary>More complete setup</summary>
```lua
{
"gbprod/yanky.nvim",
dependencies = {
{ "kkharji/sqlite.lua" }
},
opts = {
ring = { storage = "sqlite" },
},
keys = {
{ "<leader>p", function() require("telescope").extensions.yank_history.yank_history({ }) end, desc = "Open Yank History" },
{ "y", "<Plug>(YankyYank)", mode = { "n", "x" }, desc = "Yank text" },
{ "p", "<Plug>(YankyPutAfter)", mode = { "n", "x" }, desc = "Put yanked text after cursor" },
{ "P", "<Plug>(YankyPutBefore)", mode = { "n", "x" }, desc = "Put yanked text before cursor" },
{ "gp", "<Plug>(YankyGPutAfter)", mode = { "n", "x" }, desc = "Put yanked text after selection" },
{ "gP", "<Plug>(YankyGPutBefore)", mode = { "n", "x" }, desc = "Put yanked text before selection" },
{ "<c-p>", "<Plug>(YankyPreviousEntry)", desc = "Select previous entry through yank history" },
{ "<c-n>", "<Plug>(YankyNextEntry)", desc = "Select next entry through yank history" },
{ "]p", "<Plug>(YankyPutIndentAfterLinewise)", desc = "Put indented after cursor (linewise)" },
{ "[p", "<Plug>(YankyPutIndentBeforeLinewise)", desc = "Put indented before cursor (linewise)" },
{ "]P", "<Plug>(YankyPutIndentAfterLinewise)", desc = "Put indented after cursor (linewise)" },
{ "[P", "<Plug>(YankyPutIndentBeforeLinewise)", desc = "Put indented before cursor (linewise)" },
{ ">p", "<Plug>(YankyPutIndentAfterShiftRight)", desc = "Put and indent right" },
{ "<p", "<Plug>(YankyPutIndentAfterShiftLeft)", desc = "Put and indent left" },
{ ">P", "<Plug>(YankyPutIndentBeforeShiftRight)", desc = "Put before and indent right" },
{ "<P", "<Plug>(YankyPutIndentBeforeShiftLeft)", desc = "Put before and indent left" },
{ "=p", "<Plug>(YankyPutAfterFilter)", desc = "Put after applying a filter" },
{ "=P", "<Plug>(YankyPutBeforeFilter)", desc = "Put before applying a filter" },
},
}
```
</details>
### [packer](https://github.com/wbthomason/packer.nvim)
```lua
-- Lua
use("gbprod/yanky.nvim")
require("yanky").setup({
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
})
```
## ⚙️ Configuration
Yanky comes with the following defaults:
```lua
{
ring = {
history_length = 100,
storage = "shada",
storage_path = vim.fn.stdpath("data") .. "/databases/yanky.db", -- Only for sqlite storage
sync_with_numbered_registers = true,
cancel_event = "update",
ignore_registers = { "_" },
update_register_on_cycle = false,
},
picker = {
select = {
action = nil, -- nil to use default put action
},
telescope = {
use_default_mappings = true, -- if default mappings should be used
mappings = nil, -- nil to use default mappings or no mappings (see `use_default_mappings`)
},
},
system_clipboard = {
sync_with_ring = true,
clipboard_register = nil,
},
highlight = {
on_put = true,
on_yank = true,
timer = 500,
},
preserve_cursor_position = {
enabled = true,
},
textobj = {
enabled = true,
},
}
```
### ⌨️ Mappings
**This plugin contains no default mappings and will have no effect until you add your own maps to it.**
You should at least set those keymaps for yank ring usage:
```lua
vim.keymap.set({"n","x"}, "p", "<Plug>(YankyPutAfter)")
vim.keymap.set({"n","x"}, "P", "<Plug>(YankyPutBefore)")
vim.keymap.set({"n","x"}, "gp", "<Plug>(YankyGPutAfter)")
vim.keymap.set({"n","x"}, "gP", "<Plug>(YankyGPutBefore)")
vim.keymap.set("n", "<c-p>", "<Plug>(YankyPreviousEntry)")
vim.keymap.set("n", "<c-n>", "<Plug>(YankyNextEntry)")
```
And those keymaps for `tpope/vim-unimpaired` like usage:
```lua
vim.keymap.set("n", "]p", "<Plug>(YankyPutIndentAfterLinewise)")
vim.keymap.set("n", "[p", "<Plug>(YankyPutIndentBeforeLinewise)")
vim.keymap.set("n", "]P", "<Plug>(YankyPutIndentAfterLinewise)")
vim.keymap.set("n", "[P", "<Plug>(YankyPutIndentBeforeLinewise)")
vim.keymap.set("n", ">p", "<Plug>(YankyPutIndentAfterShiftRight)")
vim.keymap.set("n", "<p", "<Plug>(YankyPutIndentAfterShiftLeft)")
vim.keymap.set("n", ">P", "<Plug>(YankyPutIndentBeforeShiftRight)")
vim.keymap.set("n", "<P", "<Plug>(YankyPutIndentBeforeShiftLeft)")
vim.keymap.set("n", "=p", "<Plug>(YankyPutAfterFilter)")
vim.keymap.set("n", "=P", "<Plug>(YankyPutBeforeFilter)")
```
Some features requires specific mappings, refer to feature documentation section.
## 🖇️ Yank-ring
Yank-ring allows cycling throught yank history when putting text (like the Emacs
"kill-ring" feature). Yanky automatically maintain a history of yanks that you
can choose between when pasting.
### ⌨️ Mappings
```lua
vim.keymap.set("n", "<c-p>", "<Plug>(YankyPreviousEntry)")
vim.keymap.set("n", "<c-n>", "<Plug>(YankyNextEntry)")
```
With these mappings, after performing a paste, you can cycle through the history
by hitting `<c-n>` and `<c-p>`. Any modifications done after pasting will cancel
the possibility to cycle.
Note that the swap operations above will only affect the current paste and the
history will be unchanged.
### ⚙️ Configuration
```lua
require("yanky").setup({
ring = {
history_length = 100,
storage = "shada",
sync_with_numbered_registers = true,
cancel_event = "update",
ignore_registers = { "_" },
update_register_on_cycle = false,
},
system_clipboard = {
sync_with_ring = true,
},
})
```
#### `ring.history_length`
Default : `100`
Define the number of yanked items that will be saved and used for ring.
#### `ring.storage`
Default : `shada`
Available : `shada`, `sqlite` or `memory`
Define the storage mode for ring values.
Using `shada`, this will save pesistantly using Neovim ShaDa feature. This means
that history will be persisted between each session of Neovim.
You can also use this feature to sync the yank history across multiple running instances
of Neovim by updating shada file. If you execute `:wshada` in the first instance
and then `:rshada` in the second instance, the second instance will be synced with
the yank history in the first instance.
Using `memory`, each Neovim instance will have his own history and il will be
lost between sessions.
If you want to use `sqlite` as storage, you must add [`kkharji/sqlite.lua`](https://github.com/kkharji/sqlite.lua) as dependency:
```lua
use({
"gbprod/yanky.nvim",
requires = { "kkharji/sqlite.lua" }
})
```
Sqlite is more reliable than ShaDa but requires more dependencies. You can
change the storage path using `ring.storage_path` option.
### `ring.sync_with_numbered_registers`
Default : `true`
History can also be synchronized with numbered registers. Every time the yank
history changes the numbered registers 1 - 9 will be updated to sync with the
first 9 entries in the yank history. See [here](http://vimcasts.org/blog/2013/11/registers-the-good-the-bad-and-the-ugly-parts/)
for an explanation of why we would want do do this.
### `ring.cancel_event`
Default: `update`
Define the event used to cancel ring activation. `update` will cancel ring on
next buffer update, `move` will cancel ring when moving cursor or content
changed.
### `ring.ignore_registers `
Default: `{ "_" }`
Define registeres to be ignored. By default the black hole register is ignored.
### `system_clipboard.sync_with_ring`
Default: `true`
Yanky can automatically adds to ring history yanks that occurs outside of Neovim.
This works regardless to your `&clipboard` setting.
This means, if `&clipboard` is set to `unnamed` and/or `unnamedplus`, if you yank
something outside of Neovim, you can put it immediatly using `p` and it will be
added to your yank ring.
If `&clipboard` is empty, if you yank something outside of Neovim, this will be
the first value you'll have when cycling through the ring. Basicly, you can do
`p` and then `<c-p>` to paste yanked text.
Note that `clipboard == unnamed` uses the primary selection of the system (see
`:h clipbard` for more details) which is updated on selection, not on copy/yank.
Also note that the syncing happens when neovim gains focus.
### `system_clipboard.clipboard_register`
Default: `nil` use `&clipboard`
Choose the register that is synced with ring (from above). If `&clipboard` is
empty then `*` is used.
### `ring.update_register_on_cycle`
Default: `false`
Using the `update_register_on_cycle` option, when you cycle through the ring,
the contents of the register used to update will be updated with the last
content cycled.
### Commands
You can clear yank history using `YankyClearHistory` command.
## 📜 Yank history picker
This allows you to select an entry in your recorded yank history using default
`vim.ui.select` neovim prompt (you can use [stevearc/dressing.nvim](https://github.com/stevearc/dressing.nvim/)
to customize this) or the awesome [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim).
It uses the same history as yank ring, so, if you want to increase history size,
just use [`ring.history_length` option](#ringhistory_length).
See [Integrations](#-integrations) to have a completion with [nvim-cmp](https://github.com/hrsh7th/nvim-cmp).
### Yank history completions
Using [nvim-cmp](https://github.com/hrsh7th/nvim-cmp) and [cmp_yanky](https://github.com/chrisgrieser/cmp_yanky), you can also get suggestions from your yank history as you type in insert mode.
<details>
<summary>demonstration</summary>
<img src="https://github.com/chrisgrieser/cmp_yanky/assets/73286100/e1e62358-63d0-4261-88ed-47bb155576d2" alt="showcasing cmp-yanky" width=70%>
</details>
### ⚙️ Configuration
To use `vim.ui.select` picker, just call `YankyRingHistory` command.
To use the `yank_history` Telescope picker, register `yank_history` as a
Telescope extension in your Neovim config file.
```lua
:lua require("telescope").load_extension("yank_history")
```
After loading the extension, you can access the picker by running:
```vim
:Telescope yank_history
```
Or:
```lua
:lua require("telescope").extensions.yank_history.yank_history()
```
Set the Telescope option [`dynamic_preview_title`](https://github.com/nvim-telescope/telescope.nvim/blob/master/doc/telescope.txt)
to `true` if you want your Telescope preview window to have a
dynamic title showing the register's type.
Default configuration :
```lua
require("yanky").setup({
picker = {
select = {
action = nil, -- nil to use default put action
},
telescope = {
mappings = nil, -- nil to use default mappings
},
},
})
```
#### `picker.select.action`
Default : `nil`
This define the action that should be done when selecting an item in the
`vim.ui.select` prompt. If you let this option to `nil`, this will use the
default action : put selected item after cursor.
Available actions:
```lua
require("yanky.picker").actions.put("p") -- put after cursor
require("yanky.picker").actions.put("P") -- put before cursor
require("yanky.picker").actions.put("gp") -- put after cursor and leave the cursor after
require("yanky.picker").actions.put("gP") -- put before cursor and leave the cursor after
require("yanky.picker").actions.delete() -- delete entry from yank history
require("yanky.picker").actions.set_register(regname) -- fill register with selected value
require("yanky.picker").actions.put_and_set_register("p", regname) -- put and fill register with selected value
```
#### `picker.telescope.use_default_mappings`
Default : `true`
This define if default Telescope mappings should be use.
If you let this option to `true`, this will use the default mappings :
```lua
local utils = require("yanky.utils")
local mapping = require("yanky.telescope.mapping")
require("yanky").setup({
picker = {
telescope = {
mappings = {
default = mapping.put("p"),
i = {
["<c-g>"] = mapping.put("p"),
["<c-k>"] = mapping.put("P"),
["<c-x>"] = mapping.delete(),
["<c-r>"] = mapping.set_register(utils.get_default_register()),
},
n = {
p = mapping.put("p"),
P = mapping.put("P"),
d = mapping.delete(),
r = mapping.set_register(utils.get_default_register())
},
}
}
}
})
```
#### `picker.telescope.mappings`
Default : `nil`
This define or overrides the mappings available in Telescope.
If you set `use_default_mappings` to `true`, mappings will be merged with default mappings.
**Available actions:**
```lua
require("yanky.telescope.mapping").put("p") -- put after cursor
require("yanky.telescope.mapping").put("P") -- put before cursor
require("yanky.telescope.mapping").put("gp") -- put after cursor and leave the cursor after
require("yanky.telescope.mapping").put("gP") -- put before cursor and leave the cursor after
require("yanky.telescope.mapping").delete() -- delete entry from yank history
require("yanky.telescope.mapping").set_register(regname) -- fill register {regname} with selected value
```
You can also use any of available [special puts](https://github.com/gbprod/yanky.nvim#%EF%B8%8F-special-put) like this:
```lua
require("yanky.telescope.mapping").special_put("{{ name of the special put }}")
-- eg.
require("yanky.telescope.mapping").special_put("YankyPutAfterCharwiseJoined")
```
## 💡 Highlight put and yanked text
This will give you a visual feedback on put and yank text
by highlighting this.
### Configuration
```lua
require("yanky").setup({
highlight = {
on_put = true,
on_yank = true,
timer = 500,
},
})
```
You can override `YankyPut` highlight to change colors.
#### `highlight.on_put`
Default : `true`
Define if highlight put text feature is enabled.
#### `highlight.on_yank`
Default : `true`
Define if highlight yanked text feature is enabled.
#### `highlight.timer`
Default : `500`
Define the duration of highlight.
## ⤵️ Preserve cursor position on yank
By default in Neovim, when yanking text, cursor moves to the start of the yanked
text. Could be annoying especially when yanking a large text object such as a
paragraph or a large text object.
With this feature, yank will function exactly the same as previously with the one
difference being that the cursor position will not change after performing a yank.
### ⌨️ Mappings
```lua
vim.keymap.set({"n","x"}, "y", "<Plug>(YankyYank)")
```
### ⚙️ Configuration
```lua
require("yanky").setup({
preserve_cursor_position = {
enabled = true,
},
})
```
#### `preserve_cursor_position.enabled`
Default : `true`
Define if cursor position should be preserved on yank. This works only if mappings
has been defined.
## ⭐ Special put
Yanky comes with special put moves (inspired by
[tpope/vim-unimpaired](https://github.com/tpope/vim-unimpaired/blob/master/doc/unimpaired.txt#L100)):
- Linewise put: this will force put above or below the current line ;
- Shift right/left put: will put above or below the current line and increasing
or decreasing indent ;
- Filter put: will put above or below the current line and reindenting.
### ⌨️ Mappings
For basic usage (like with [tpope/vim-unimpaired](https://github.com/tpope/vim-unimpaired/blob/master/doc/unimpaired.txt#L100)),
you can use those bindings:
```lua
vim.keymap.set("n", "]p", "<Plug>(YankyPutIndentAfterLinewise)")
vim.keymap.set("n", "[p", "<Plug>(YankyPutIndentBeforeLinewise)")
vim.keymap.set("n", "]P", "<Plug>(YankyPutIndentAfterLinewise)")
vim.keymap.set("n", "[P", "<Plug>(YankyPutIndentBeforeLinewise)")
vim.keymap.set("n", ">p", "<Plug>(YankyPutIndentAfterShiftRight)")
vim.keymap.set("n", "<p", "<Plug>(YankyPutIndentAfterShiftLeft)")
vim.keymap.set("n", ">P", "<Plug>(YankyPutIndentBeforeShiftRight)")
vim.keymap.set("n", "<P", "<Plug>(YankyPutIndentBeforeShiftLeft)")
vim.keymap.set("n", "=p", "<Plug>(YankyPutAfterFilter)")
vim.keymap.set("n", "=P", "<Plug>(YankyPutBeforeFilter)")
```
To go further, Plug mappings are constructed like this: `Yanky(put-type)(modifier)(rewriter)`.
`put-type` can be:
- `PutAfter`: put after your cursor (as [`p`](https://neovim.io/doc/user/change.html#put) key) ;
- `PutBefore`: put before your cursor (as [`P`](https://neovim.io/doc/user/change.html#P) key) ;
- `GPutAfter`: like `PutAfter` but leave the cursor after the new text (as [`gp`](https://neovim.io/doc/user/change.html#gp) key) ;
- `GPutBefore`: like `PutBefore` but leave the cursor after the new text (as [`gP`](https://neovim.io/doc/user/change.html#gP) key) ;
- `PutIndentAfter`: like `PutAfter` but adjust the indent to the current line (as [`]p`](https://neovim.io/doc/user/change.html#]p) key) ;
- `PutIndentBefore`: like `PutBefore` but adjust the indent to the current line (as [`[p`](https://neovim.io/doc/user/change.html#[p) key) ;
`modifier` (optional) can be:
- `Linewise`: put in linewise mode ;
- `Charwise`: put in charwise mode ;
- `Blockwise`: put in blockwise mode ;
- `ShiftRight`: increase indent ;
- `ShiftLeft`: decrease indent.
`rewriter` (optional) can be:
- `Joined`: put lines trimed and joined.
<details>
<summary><b>All special puts</b></summary>
```vim
<Plug>(YankyPutAfter)
<Plug>(YankyPutAfterBlockwise)
<Plug>(YankyPutAfterBlockwiseJoined)
<Plug>(YankyPutAfterCharwise)
<Plug>(YankyPutAfterCharwiseJoined)
<Plug>(YankyPutAfterFilter)
<Plug>(YankyPutAfterFilterJoined)
<Plug>(YankyPutAfterJoined)
<Plug>(YankyPutAfterLinewise)
<Plug>(YankyPutAfterLinewiseJoined)
<Plug>(YankyPutAfterShiftLeft)
<Plug>(YankyPutAfterShiftLeftJoined)
<Plug>(YankyPutAfterShiftRight)
<Plug>(YankyPutAfterShiftRightJoined)
<Plug>(YankyPutBefore)
<Plug>(YankyPutBeforeBlockwise)
<Plug>(YankyPutBeforeBlockwiseJoined)
<Plug>(YankyPutBeforeCharwise)
<Plug>(YankyPutBeforeCharwiseJoined)
<Plug>(YankyPutBeforeFilter)
<Plug>(YankyPutBeforeFilterJoined)
<Plug>(YankyPutBeforeJoined)
<Plug>(YankyPutBeforeLinewise)
<Plug>(YankyPutBeforeLinewiseJoined)
<Plug>(YankyPutBeforeShiftLeft)
<Plug>(YankyPutBeforeShiftLeftJoined)
<Plug>(YankyPutBeforeShiftRight)
<Plug>(YankyPutBeforeShiftRightJoined)
<Plug>(YankyGPutAfter)
<Plug>(YankyGPutAfterBlockwise)
<Plug>(YankyGPutAfterBlockwiseJoined)
<Plug>(YankyGPutAfterCharwise)
<Plug>(YankyGPutAfterCharwiseJoined)
<Plug>(YankyGPutAfterFilter)
<Plug>(YankyGPutAfterFilterJoined)
<Plug>(YankyGPutAfterJoined)
<Plug>(YankyGPutAfterLinewise)
<Plug>(YankyGPutAfterLinewiseJoined)
<Plug>(YankyGPutAfterShiftLeft)
<Plug>(YankyGPutAfterShiftLeftJoined)
<Plug>(YankyGPutAfterShiftRight)
<Plug>(YankyGPutAfterShiftRightJoined)
<Plug>(YankyGPutBefore)
<Plug>(YankyGPutBeforeBlockwise)
<Plug>(YankyGPutBeforeBlockwiseJoined)
<Plug>(YankyGPutBeforeCharwise)
<Plug>(YankyGPutBeforeCharwiseJoined)
<Plug>(YankyGPutBeforeFilter)
<Plug>(YankyGPutBeforeFilterJoined)
<Plug>(YankyGPutBeforeJoined)
<Plug>(YankyGPutBeforeLinewise)
<Plug>(YankyGPutBeforeLinewiseJoined)
<Plug>(YankyGPutBeforeShiftLeft)
<Plug>(YankyGPutBeforeShiftLeftJoined)
<Plug>(YankyGPutBeforeShiftRight)
<Plug>(YankyGPutBeforeShiftRightJoined)
<Plug>(YankyPutIndentAfter)
<Plug>(YankyPutIndentAfterBlockwise)
<Plug>(YankyPutIndentAfterBlockwiseJoined)
<Plug>(YankyPutIndentAfterCharwise)
<Plug>(YankyPutIndentAfterCharwiseJoined)
<Plug>(YankyPutIndentAfterFilter)
<Plug>(YankyPutIndentAfterFilterJoined)
<Plug>(YankyPutIndentAfterJoined)
<Plug>(YankyPutIndentAfterLinewise)
<Plug>(YankyPutIndentAfterLinewiseJoined)
<Plug>(YankyPutIndentAfterShiftLeft)
<Plug>(YankyPutIndentAfterShiftLeftJoined)
<Plug>(YankyPutIndentAfterShiftRight)
<Plug>(YankyPutIndentAfterShiftRightJoined)
<Plug>(YankyPutIndentBefore)
<Plug>(YankyPutIndentBeforeBlockwise)
<Plug>(YankyPutIndentBeforeBlockwiseJoined)
<Plug>(YankyPutIndentBeforeCharwise)
<Plug>(YankyPutIndentBeforeCharwiseJoined)
<Plug>(YankyPutIndentBeforeFilter)
<Plug>(YankyPutIndentBeforeFilterJoined)
<Plug>(YankyPutIndentBeforeJoined)
<Plug>(YankyPutIndentBeforeLinewise)
<Plug>(YankyPutIndentBeforeLinewiseJoined)
<Plug>(YankyPutIndentBeforeShiftLeft)
<Plug>(YankyPutIndentBeforeShiftLeftJoined)
<Plug>(YankyPutIndentBeforeShiftRight)
<Plug>(YankyPutIndentBeforeShiftRightJoined)
```
</details>
## ⚓ Text object
Yanky comes with a text object corresponding to last put text. To use it, you
have to enable it in settings and set a keymap.
### ⚙️ Configuration
```lua
require("yanky").setup({
textobj = {
enabled = true,
},
})
```
### ⌨️ Mappings
```lua
vim.keymap.set({ "o", "x" }, "lp", function()
require("yanky.textobj").last_put()
end, {})
```
## 🎨 Colors
| Description | Group | Default |
| ------------------------------- | ----------- | -------------- |
| Highlight color for put text | YankyPut | link to Search |
| Highlight color for yanked text | YankyYanked | link to Search |
## 🤝 Integrations
<details>
<summary><b>gbprod/substitute.nvim</b></summary>
To enable [gbprod/substitute.nvim](https://github.com/gbprod/substitute.nvim)
swap when performing a substitution, you can add this to your setup:
```lua
require("substitute").setup({
on_substitute = require("yanky.integration").substitute(),
})
```
</details>
<details>
<summary><b>hrsh7th/nvim-cmp</b></summary>
Using [hrsh7th/nvim-cmp](https://github.com/hrsh7th/nvim-cmp) and [chrisgrieser/cmp_yanky](https://github.com/chrisgrieser/cmp_yanky), you can also get suggestions from your yank history as you type in insert mode.
<img src="https://github.com/chrisgrieser/cmp_yanky/assets/73286100/e1e62358-63d0-4261-88ed-47bb155576d2" alt="showcasing cmp-yanky" width=70%>
</details>
<details>
<summary><b>anuvyklack/hydra.nvim</b></summary>
To work with [anuvyklack/hydra.nvim](https://github.com/anuvyklack/hydra.nvim)
only setup <C-n>/<C-p> mapping when yanky is activated, you can add this to your setup:
```lua
local Hydra = require("hydra")
local function t(str)
return api.nvim_replace_termcodes(str, true, true, true)
end
local yanky_hydra = Hydra({
name = "Yank ring",
mode = "n",
heads = {
{ "p", "<Plug>(YankyPutAfter)", { desc = "After" } },
{ "P", "<Plug>(YankyPutBefore)", { desc = "Before" } },
{ "<c-p>", "<Plug>(YankyPreviousEntry)", { private = true, desc = "↑" } },
{ "<c-n>", "<Plug>(YankyNextEntry)", { private = true, desc = "↓" } },
},
})
-- choose/change the mappings if you want
for key, putAction in pairs({
["p"] = "<Plug>(YankyPutAfter)",
["P"] = "<Plug>(YankyPutBefore)",
["gp"] = "<Plug>(YankyGPutAfter)",
["gP"] = "<Plug>(YankyGPutBefore)",
}) do
vim.keymap.set({ "n", "x" }, key, function()
vim.fn.feedkeys(t(putAction))
yanky_hydra:activate()
end)
end
-- choose/change the mappings if you want
for key, putAction in pairs({
["]p"] = "<Plug>(YankyPutIndentAfterLinewise)",
["[p"] = "<Plug>(YankyPutIndentBeforeLinewise)",
["]P"] = "<Plug>(YankyPutIndentAfterLinewise)",
["[P"] = "<Plug>(YankyPutIndentBeforeLinewise)",
[">p"] = "<Plug>(YankyPutIndentAfterShiftRight)",
["<p"] = "<Plug>(YankyPutIndentAfterShiftLeft)",
[">P"] = "<Plug>(YankyPutIndentBeforeShiftRight)",
["<P"] = "<Plug>(YankyPutIndentBeforeShiftLeft)",
["=p"] = "<Plug>(YankyPutAfterFilter)",
["=P"] = "<Plug>(YankyPutBeforeFilter)",
}) do
vim.keymap.set("n", key, function()
vim.fn.feedkeys(t(putAction))
yanky_hydra:activate()
end)
end
```
</details>
## 🎉 Credits
This plugin is mostly a lua version of [svermeulen/vim-yoink](https://github.com/svermeulen/vim-yoink)
awesome plugin.
Other inspiration :
- [bfredl/nvim-miniyank](https://github.com/bfredl/nvim-miniyank)
- [maxbrunsfeld/vim-yankstack](https://github.com/maxbrunsfeld/vim-yankstack)
- [svermeulen/vim-easyclip](https://github.com/svermeulen/vim-easyclip)
- [bkoropoff/yankee.vim](https://github.com/bkoropoff/yankee.vim)
- [svban/YankAssassin.vim](https://github.com/svban/YankAssassin.vim)
- [tpope/vim-unimpaired](https://github.com/tpope/vim-unimpaired)
- [inkarkat/vim-UnconditionalPaste](https://github.com/inkarkat/vim-UnconditionalPaste)

View File

@ -0,0 +1,861 @@
*yanky.txt* Improved Yank an Put functionalities for Neovim
==============================================================================
Table of Contents *yanky-table-of-contents*
1. 🍃 yanky.nvim |yanky-🍃-yanky.nvim|
- ✨ Features |yanky-🍃-yanky.nvim-✨-features|
- ⚡️ Requirements |yanky-🍃-yanky.nvim-⚡️-requirements|
- 📦 Installation |yanky-🍃-yanky.nvim-📦-installation|
- ⚙️ Configuration |yanky-🍃-yanky.nvim-⚙️-configuration|
- 🖇️ Yank-ring |yanky-🍃-yanky.nvim-🖇️-yank-ring|
- 📜 Yank history picker |yanky-🍃-yanky.nvim-📜-yank-history-picker|
- 💡 Highlight put and yanked text|yanky-🍃-yanky.nvim-💡-highlight-put-and-yanked-text|
- ⤵️ Preserve cursor position on yank|yanky-🍃-yanky.nvim-⤵️-preserve-cursor-position-on-yank|
- ⭐ Special put |yanky-🍃-yanky.nvim-⭐-special-put|
- ⚓ Text object |yanky-🍃-yanky.nvim-⚓-text-object|
- 🎨 Colors |yanky-🍃-yanky.nvim-🎨-colors|
- 🤝 Integrations |yanky-🍃-yanky.nvim-🤝-integrations|
- 🎉 Credits |yanky-🍃-yanky.nvim-🎉-credits|
2. Links |yanky-links|
==============================================================================
1. 🍃 yanky.nvim *yanky-🍃-yanky.nvim*
<https://github.com/gbprod/yanky.nvim/actions/workflows/integration.yml>
The aim of `yanky.nvim` is to improve yank and put functionalities for Neovim.
French slogan:
"Vas-y Yanky, cest bon !" - Yanky Vincent
Or in English:
"Yanky-ki-yay, motherf*cker" - John McYanky
✨ FEATURES *yanky-🍃-yanky.nvim-✨-features*
- 🖇️ Yank-ring
- 📜 Yank history picker
- 💡 Highlight put and yanked text
- ⤵️ Preserve cursor position on yank
- ⭐ Special put
- ⚓ Text object
⚡️ REQUIREMENTS *yanky-🍃-yanky.nvim-⚡️-requirements*
Requires neovim > `0.9.0`.
📦 INSTALLATION *yanky-🍃-yanky.nvim-📦-installation*
Install the plugin with your preferred package manager:
LAZY.NVIM ~
>lua
{
"gbprod/yanky.nvim",
opts = {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
},
}
<
More complete setup ~
>lua
{
"gbprod/yanky.nvim",
dependencies = {
{ "kkharji/sqlite.lua" }
},
opts = {
ring = { storage = "sqlite" },
},
keys = {
{ "<leader>p", function() require("telescope").extensions.yank_history.yank_history({ }) end, desc = "Open Yank History" },
{ "y", "<Plug>(YankyYank)", mode = { "n", "x" }, desc = "Yank text" },
{ "p", "<Plug>(YankyPutAfter)", mode = { "n", "x" }, desc = "Put yanked text after cursor" },
{ "P", "<Plug>(YankyPutBefore)", mode = { "n", "x" }, desc = "Put yanked text before cursor" },
{ "gp", "<Plug>(YankyGPutAfter)", mode = { "n", "x" }, desc = "Put yanked text after selection" },
{ "gP", "<Plug>(YankyGPutBefore)", mode = { "n", "x" }, desc = "Put yanked text before selection" },
{ "<c-p>", "<Plug>(YankyPreviousEntry)", desc = "Select previous entry through yank history" },
{ "<c-n>", "<Plug>(YankyNextEntry)", desc = "Select next entry through yank history" },
{ "]p", "<Plug>(YankyPutIndentAfterLinewise)", desc = "Put indented after cursor (linewise)" },
{ "[p", "<Plug>(YankyPutIndentBeforeLinewise)", desc = "Put indented before cursor (linewise)" },
{ "]P", "<Plug>(YankyPutIndentAfterLinewise)", desc = "Put indented after cursor (linewise)" },
{ "[P", "<Plug>(YankyPutIndentBeforeLinewise)", desc = "Put indented before cursor (linewise)" },
{ ">p", "<Plug>(YankyPutIndentAfterShiftRight)", desc = "Put and indent right" },
{ "<p", "<Plug>(YankyPutIndentAfterShiftLeft)", desc = "Put and indent left" },
{ ">P", "<Plug>(YankyPutIndentBeforeShiftRight)", desc = "Put before and indent right" },
{ "<P", "<Plug>(YankyPutIndentBeforeShiftLeft)", desc = "Put before and indent left" },
{ "=p", "<Plug>(YankyPutAfterFilter)", desc = "Put after applying a filter" },
{ "=P", "<Plug>(YankyPutBeforeFilter)", desc = "Put before applying a filter" },
},
}
<
PACKER ~
>lua
-- Lua
use("gbprod/yanky.nvim")
require("yanky").setup({
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
})
<
⚙️ CONFIGURATION *yanky-🍃-yanky.nvim-⚙️-configuration*
Yanky comes with the following defaults:
>lua
{
ring = {
history_length = 100,
storage = "shada",
storage_path = vim.fn.stdpath("data") .. "/databases/yanky.db", -- Only for sqlite storage
sync_with_numbered_registers = true,
cancel_event = "update",
ignore_registers = { "_" },
update_register_on_cycle = false,
},
picker = {
select = {
action = nil, -- nil to use default put action
},
telescope = {
use_default_mappings = true, -- if default mappings should be used
mappings = nil, -- nil to use default mappings or no mappings (see `use_default_mappings`)
},
},
system_clipboard = {
sync_with_ring = true,
clipboard_register = nil,
},
highlight = {
on_put = true,
on_yank = true,
timer = 500,
},
preserve_cursor_position = {
enabled = true,
},
textobj = {
enabled = true,
},
}
<
⌨️ MAPPINGS ~
**This plugin contains no default mappings and will have no effect until you
add your own maps to it.** You should at least set those keymaps for yank ring
usage:
>lua
vim.keymap.set({"n","x"}, "p", "<Plug>(YankyPutAfter)")
vim.keymap.set({"n","x"}, "P", "<Plug>(YankyPutBefore)")
vim.keymap.set({"n","x"}, "gp", "<Plug>(YankyGPutAfter)")
vim.keymap.set({"n","x"}, "gP", "<Plug>(YankyGPutBefore)")
vim.keymap.set("n", "<c-p>", "<Plug>(YankyPreviousEntry)")
vim.keymap.set("n", "<c-n>", "<Plug>(YankyNextEntry)")
<
And those keymaps for `tpope/vim-unimpaired` like usage:
>lua
vim.keymap.set("n", "]p", "<Plug>(YankyPutIndentAfterLinewise)")
vim.keymap.set("n", "[p", "<Plug>(YankyPutIndentBeforeLinewise)")
vim.keymap.set("n", "]P", "<Plug>(YankyPutIndentAfterLinewise)")
vim.keymap.set("n", "[P", "<Plug>(YankyPutIndentBeforeLinewise)")
vim.keymap.set("n", ">p", "<Plug>(YankyPutIndentAfterShiftRight)")
vim.keymap.set("n", "<p", "<Plug>(YankyPutIndentAfterShiftLeft)")
vim.keymap.set("n", ">P", "<Plug>(YankyPutIndentBeforeShiftRight)")
vim.keymap.set("n", "<P", "<Plug>(YankyPutIndentBeforeShiftLeft)")
vim.keymap.set("n", "=p", "<Plug>(YankyPutAfterFilter)")
vim.keymap.set("n", "=P", "<Plug>(YankyPutBeforeFilter)")
<
Some features requires specific mappings, refer to feature documentation
section.
🖇️ YANK-RING *yanky-🍃-yanky.nvim-🖇️-yank-ring*
Yank-ring allows cycling throught yank history when putting text (like the
Emacs "kill-ring" feature). Yanky automatically maintain a history of yanks
that you can choose between when pasting.
⌨️ MAPPINGS ~
>lua
vim.keymap.set("n", "<c-p>", "<Plug>(YankyPreviousEntry)")
vim.keymap.set("n", "<c-n>", "<Plug>(YankyNextEntry)")
<
With these mappings, after performing a paste, you can cycle through the
history by hitting `<c-n>` and `<c-p>`. Any modifications done after pasting
will cancel the possibility to cycle.
Note that the swap operations above will only affect the current paste and the
history will be unchanged.
⚙️ CONFIGURATION ~
>lua
require("yanky").setup({
ring = {
history_length = 100,
storage = "shada",
sync_with_numbered_registers = true,
cancel_event = "update",
ignore_registers = { "_" },
update_register_on_cycle = false,
},
system_clipboard = {
sync_with_ring = true,
},
})
<
RING.HISTORY_LENGTH
Default : `100`
Define the number of yanked items that will be saved and used for ring.
RING.STORAGE
Default : `shada`
Available : `shada`, `sqlite` or `memory`
Define the storage mode for ring values.
Using `shada`, this will save pesistantly using Neovim ShaDa feature. This
means that history will be persisted between each session of Neovim.
You can also use this feature to sync the yank history across multiple running
instances of Neovim by updating shada file. If you execute `:wshada` in the
first instance and then `:rshada` in the second instance, the second instance
will be synced with the yank history in the first instance.
Using `memory`, each Neovim instance will have his own history and il will be
lost between sessions.
If you want to use `sqlite` as storage, you must add `kkharji/sqlite.lua`
<https://github.com/kkharji/sqlite.lua> as dependency:
>lua
use({
"gbprod/yanky.nvim",
requires = { "kkharji/sqlite.lua" }
})
<
Sqlite is more reliable than ShaDa but requires more dependencies. You can
change the storage path using `ring.storage_path` option.
RING.SYNC_WITH_NUMBERED_REGISTERS ~
Default : `true`
History can also be synchronized with numbered registers. Every time the yank
history changes the numbered registers 1 - 9 will be updated to sync with the
first 9 entries in the yank history. See here
<http://vimcasts.org/blog/2013/11/registers-the-good-the-bad-and-the-ugly-parts/>
for an explanation of why we would want do do this.
RING.CANCEL_EVENT ~
Default: `update`
Define the event used to cancel ring activation. `update` will cancel ring on
next buffer update, `move` will cancel ring when moving cursor or content
changed.
RING.IGNORE_REGISTERS ~
Default: `{ "_" }`
Define registeres to be ignored. By default the black hole register is ignored.
SYSTEM_CLIPBOARD.SYNC_WITH_RING ~
Default: `true`
Yanky can automatically adds to ring history yanks that occurs outside of
Neovim. This works regardless to your `&clipboard` setting.
This means, if `&clipboard` is set to `unnamed` and/or `unnamedplus`, if you
yank something outside of Neovim, you can put it immediatly using `p` and it
will be added to your yank ring.
If `&clipboard` is empty, if you yank something outside of Neovim, this will be
the first value youll have when cycling through the ring. Basicly, you can
do `p` and then `<c-p>` to paste yanked text.
Note that `clipboard == unnamed` uses the primary selection of the system (see
|clipbard| for more details) which is updated on selection, not on copy/yank.
Also note that the syncing happens when neovim gains focus.
SYSTEM_CLIPBOARD.CLIPBOARD_REGISTER ~
Default: `nil` use `&clipboard`
Choose the register that is synced with ring (from above). If `&clipboard` is
empty then `*` is used.
RING.UPDATE_REGISTER_ON_CYCLE ~
Default: `false`
Using the `update_register_on_cycle` option, when you cycle through the ring,
the contents of the register used to update will be updated with the last
content cycled.
COMMANDS ~
You can clear yank history using `YankyClearHistory` command.
📜 YANK HISTORY PICKER *yanky-🍃-yanky.nvim-📜-yank-history-picker*
This allows you to select an entry in your recorded yank history using default
`vim.ui.select` neovim prompt (you can use stevearc/dressing.nvim
<https://github.com/stevearc/dressing.nvim/> to customize this) or the awesome
telescope.nvim <https://github.com/nvim-telescope/telescope.nvim>.
It uses the same history as yank ring, so, if you want to increase history
size, just use |yanky-`ring.history_length`-option|.
See |yanky-integrations| to have a completion with nvim-cmp
<https://github.com/hrsh7th/nvim-cmp>.
YANK HISTORY COMPLETIONS ~
Using nvim-cmp <https://github.com/hrsh7th/nvim-cmp> and cmp_yanky
<https://github.com/chrisgrieser/cmp_yanky>, you can also get suggestions from
your yank history as you type in insert mode.
demonstration ~
⚙️ CONFIGURATION ~
To use `vim.ui.select` picker, just call `YankyRingHistory` command.
To use the `yank_history` Telescope picker, register `yank_history` as a
Telescope extension in your Neovim config file.
>lua
:lua require("telescope").load_extension("yank_history")
<
After loading the extension, you can access the picker by running:
>vim
:Telescope yank_history
<
Or:
>lua
:lua require("telescope").extensions.yank_history.yank_history()
<
Set the Telescope option `dynamic_preview_title`
<https://github.com/nvim-telescope/telescope.nvim/blob/master/doc/telescope.txt>
to `true` if you want your Telescope preview window to have a dynamic title
showing the registers type.
Default configuration :
>lua
require("yanky").setup({
picker = {
select = {
action = nil, -- nil to use default put action
},
telescope = {
mappings = nil, -- nil to use default mappings
},
},
})
<
PICKER.SELECT.ACTION
Default : `nil`
This define the action that should be done when selecting an item in the
`vim.ui.select` prompt. If you let this option to `nil`, this will use the
default action : put selected item after cursor.
Available actions:
>lua
require("yanky.picker").actions.put("p") -- put after cursor
require("yanky.picker").actions.put("P") -- put before cursor
require("yanky.picker").actions.put("gp") -- put after cursor and leave the cursor after
require("yanky.picker").actions.put("gP") -- put before cursor and leave the cursor after
require("yanky.picker").actions.delete() -- delete entry from yank history
require("yanky.picker").actions.set_register(regname) -- fill register with selected value
require("yanky.picker").actions.put_and_set_register("p", regname) -- put and fill register with selected value
<
PICKER.TELESCOPE.USE_DEFAULT_MAPPINGS
Default : `true`
This define if default Telescope mappings should be use.
If you let this option to `true`, this will use the default mappings :
>lua
local utils = require("yanky.utils")
local mapping = require("yanky.telescope.mapping")
require("yanky").setup({
picker = {
telescope = {
mappings = {
default = mapping.put("p"),
i = {
["<c-g>"] = mapping.put("p"),
["<c-k>"] = mapping.put("P"),
["<c-x>"] = mapping.delete(),
["<c-r>"] = mapping.set_register(utils.get_default_register()),
},
n = {
p = mapping.put("p"),
P = mapping.put("P"),
d = mapping.delete(),
r = mapping.set_register(utils.get_default_register())
},
}
}
}
})
<
PICKER.TELESCOPE.MAPPINGS
Default : `nil`
This define or overrides the mappings available in Telescope.
If you set `use_default_mappings` to `true`, mappings will be merged with
default mappings.
**Available actions:**
>lua
require("yanky.telescope.mapping").put("p") -- put after cursor
require("yanky.telescope.mapping").put("P") -- put before cursor
require("yanky.telescope.mapping").put("gp") -- put after cursor and leave the cursor after
require("yanky.telescope.mapping").put("gP") -- put before cursor and leave the cursor after
require("yanky.telescope.mapping").delete() -- delete entry from yank history
require("yanky.telescope.mapping").set_register(regname) -- fill register {regname} with selected value
<
You can also use any of available special puts
<https://github.com/gbprod/yanky.nvim#%EF%B8%8F-special-put> like this:
>lua
require("yanky.telescope.mapping").special_put("{{ name of the special put }}")
-- eg.
require("yanky.telescope.mapping").special_put("YankyPutAfterCharwiseJoined")
<
💡 HIGHLIGHT PUT AND YANKED TEXT*yanky-🍃-yanky.nvim-💡-highlight-put-and-yanked-text*
This will give you a visual feedback on put and yank text by highlighting this.
### Configuration
>lua
require("yanky").setup({
highlight = {
on_put = true,
on_yank = true,
timer = 500,
},
})
<
You can override `YankyPut` highlight to change colors.
HIGHLIGHT.ON_PUT
Default : `true`
Define if highlight put text feature is enabled.
HIGHLIGHT.ON_YANK
Default : `true`
Define if highlight yanked text feature is enabled.
HIGHLIGHT.TIMER
Default : `500`
Define the duration of highlight.
⤵️ PRESERVE CURSOR POSITION ON YANK*yanky-🍃-yanky.nvim-⤵️-preserve-cursor-position-on-yank*
By default in Neovim, when yanking text, cursor moves to the start of the
yanked text. Could be annoying especially when yanking a large text object such
as a paragraph or a large text object.
With this feature, yank will function exactly the same as previously with the
one difference being that the cursor position will not change after performing
a yank.
⌨️ MAPPINGS ~
>lua
vim.keymap.set({"n","x"}, "y", "<Plug>(YankyYank)")
<
⚙️ CONFIGURATION ~
>lua
require("yanky").setup({
preserve_cursor_position = {
enabled = true,
},
})
<
PRESERVE_CURSOR_POSITION.ENABLED
Default : `true`
Define if cursor position should be preserved on yank. This works only if
mappings has been defined.
⭐ SPECIAL PUT *yanky-🍃-yanky.nvim-⭐-special-put*
Yanky comes with special put moves (inspired by tpope/vim-unimpaired
<https://github.com/tpope/vim-unimpaired/blob/master/doc/unimpaired.txt#L100>):
- Linewise put: this will force put above or below the current line ;
- Shift right/left put: will put above or below the current line and increasing
or decreasing indent ;
- Filter put: will put above or below the current line and reindenting.
⌨️ MAPPINGS ~
For basic usage (like with tpope/vim-unimpaired
<https://github.com/tpope/vim-unimpaired/blob/master/doc/unimpaired.txt#L100>),
you can use those bindings:
>lua
vim.keymap.set("n", "]p", "<Plug>(YankyPutIndentAfterLinewise)")
vim.keymap.set("n", "[p", "<Plug>(YankyPutIndentBeforeLinewise)")
vim.keymap.set("n", "]P", "<Plug>(YankyPutIndentAfterLinewise)")
vim.keymap.set("n", "[P", "<Plug>(YankyPutIndentBeforeLinewise)")
vim.keymap.set("n", ">p", "<Plug>(YankyPutIndentAfterShiftRight)")
vim.keymap.set("n", "<p", "<Plug>(YankyPutIndentAfterShiftLeft)")
vim.keymap.set("n", ">P", "<Plug>(YankyPutIndentBeforeShiftRight)")
vim.keymap.set("n", "<P", "<Plug>(YankyPutIndentBeforeShiftLeft)")
vim.keymap.set("n", "=p", "<Plug>(YankyPutAfterFilter)")
vim.keymap.set("n", "=P", "<Plug>(YankyPutBeforeFilter)")
<
To go further, Plug mappings are constructed like this:
`Yanky(put-type)(modifier)(rewriter)`.
`put-type` can be:
- `PutAfter`: put after your cursor (as |`p`| key) ;
- `PutBefore`: put before your cursor (as |`P`| key) ;
- `GPutAfter`: like `PutAfter` but leave the cursor after the new text (as |`gp`| key) ;
- `GPutBefore`: like `PutBefore` but leave the cursor after the new text (as |`gP`| key) ;
- `PutIndentAfter`: like `PutAfter` but adjust the indent to the current line (as |`]p`| key) ;
- `PutIndentBefore`: like `PutBefore` but adjust the indent to the current line (as |`[p`| key) ;
`modifier` (optional) can be:
- `Linewise`: put in linewise mode ;
- `Charwise`: put in charwise mode ;
- `Blockwise`: put in blockwise mode ;
- `ShiftRight`: increase indent ;
- `ShiftLeft`: decrease indent.
`rewriter` (optional) can be:
- `Joined`: put lines trimed and joined.
All special puts ~
>vim
<Plug>(YankyPutAfter)
<Plug>(YankyPutAfterBlockwise)
<Plug>(YankyPutAfterBlockwiseJoined)
<Plug>(YankyPutAfterCharwise)
<Plug>(YankyPutAfterCharwiseJoined)
<Plug>(YankyPutAfterFilter)
<Plug>(YankyPutAfterFilterJoined)
<Plug>(YankyPutAfterJoined)
<Plug>(YankyPutAfterLinewise)
<Plug>(YankyPutAfterLinewiseJoined)
<Plug>(YankyPutAfterShiftLeft)
<Plug>(YankyPutAfterShiftLeftJoined)
<Plug>(YankyPutAfterShiftRight)
<Plug>(YankyPutAfterShiftRightJoined)
<Plug>(YankyPutBefore)
<Plug>(YankyPutBeforeBlockwise)
<Plug>(YankyPutBeforeBlockwiseJoined)
<Plug>(YankyPutBeforeCharwise)
<Plug>(YankyPutBeforeCharwiseJoined)
<Plug>(YankyPutBeforeFilter)
<Plug>(YankyPutBeforeFilterJoined)
<Plug>(YankyPutBeforeJoined)
<Plug>(YankyPutBeforeLinewise)
<Plug>(YankyPutBeforeLinewiseJoined)
<Plug>(YankyPutBeforeShiftLeft)
<Plug>(YankyPutBeforeShiftLeftJoined)
<Plug>(YankyPutBeforeShiftRight)
<Plug>(YankyPutBeforeShiftRightJoined)
<Plug>(YankyGPutAfter)
<Plug>(YankyGPutAfterBlockwise)
<Plug>(YankyGPutAfterBlockwiseJoined)
<Plug>(YankyGPutAfterCharwise)
<Plug>(YankyGPutAfterCharwiseJoined)
<Plug>(YankyGPutAfterFilter)
<Plug>(YankyGPutAfterFilterJoined)
<Plug>(YankyGPutAfterJoined)
<Plug>(YankyGPutAfterLinewise)
<Plug>(YankyGPutAfterLinewiseJoined)
<Plug>(YankyGPutAfterShiftLeft)
<Plug>(YankyGPutAfterShiftLeftJoined)
<Plug>(YankyGPutAfterShiftRight)
<Plug>(YankyGPutAfterShiftRightJoined)
<Plug>(YankyGPutBefore)
<Plug>(YankyGPutBeforeBlockwise)
<Plug>(YankyGPutBeforeBlockwiseJoined)
<Plug>(YankyGPutBeforeCharwise)
<Plug>(YankyGPutBeforeCharwiseJoined)
<Plug>(YankyGPutBeforeFilter)
<Plug>(YankyGPutBeforeFilterJoined)
<Plug>(YankyGPutBeforeJoined)
<Plug>(YankyGPutBeforeLinewise)
<Plug>(YankyGPutBeforeLinewiseJoined)
<Plug>(YankyGPutBeforeShiftLeft)
<Plug>(YankyGPutBeforeShiftLeftJoined)
<Plug>(YankyGPutBeforeShiftRight)
<Plug>(YankyGPutBeforeShiftRightJoined)
<Plug>(YankyPutIndentAfter)
<Plug>(YankyPutIndentAfterBlockwise)
<Plug>(YankyPutIndentAfterBlockwiseJoined)
<Plug>(YankyPutIndentAfterCharwise)
<Plug>(YankyPutIndentAfterCharwiseJoined)
<Plug>(YankyPutIndentAfterFilter)
<Plug>(YankyPutIndentAfterFilterJoined)
<Plug>(YankyPutIndentAfterJoined)
<Plug>(YankyPutIndentAfterLinewise)
<Plug>(YankyPutIndentAfterLinewiseJoined)
<Plug>(YankyPutIndentAfterShiftLeft)
<Plug>(YankyPutIndentAfterShiftLeftJoined)
<Plug>(YankyPutIndentAfterShiftRight)
<Plug>(YankyPutIndentAfterShiftRightJoined)
<Plug>(YankyPutIndentBefore)
<Plug>(YankyPutIndentBeforeBlockwise)
<Plug>(YankyPutIndentBeforeBlockwiseJoined)
<Plug>(YankyPutIndentBeforeCharwise)
<Plug>(YankyPutIndentBeforeCharwiseJoined)
<Plug>(YankyPutIndentBeforeFilter)
<Plug>(YankyPutIndentBeforeFilterJoined)
<Plug>(YankyPutIndentBeforeJoined)
<Plug>(YankyPutIndentBeforeLinewise)
<Plug>(YankyPutIndentBeforeLinewiseJoined)
<Plug>(YankyPutIndentBeforeShiftLeft)
<Plug>(YankyPutIndentBeforeShiftLeftJoined)
<Plug>(YankyPutIndentBeforeShiftRight)
<Plug>(YankyPutIndentBeforeShiftRightJoined)
<
⚓ TEXT OBJECT *yanky-🍃-yanky.nvim-⚓-text-object*
Yanky comes with a text object corresponding to last put text. To use it, you
have to enable it in settings and set a keymap.
⚙️ CONFIGURATION ~
>lua
require("yanky").setup({
textobj = {
enabled = true,
},
})
<
⌨️ MAPPINGS ~
>lua
vim.keymap.set({ "o", "x" }, "lp", function()
require("yanky.textobj").last_put()
end, {})
<
🎨 COLORS *yanky-🍃-yanky.nvim-🎨-colors*
Description Group Default
--------------------------------- ------------- ----------------
Highlight color for put text YankyPut link to Search
Highlight color for yanked text YankyYanked link to Search
🤝 INTEGRATIONS *yanky-🍃-yanky.nvim-🤝-integrations*
gbprod/substitute.nvim ~
To enable gbprod/substitute.nvim <https://github.com/gbprod/substitute.nvim>
swap when performing a substitution, you can add this to your setup:
>lua
require("substitute").setup({
on_substitute = require("yanky.integration").substitute(),
})
<
hrsh7th/nvim-cmp ~
Using hrsh7th/nvim-cmp <https://github.com/hrsh7th/nvim-cmp> and
chrisgrieser/cmp_yanky <https://github.com/chrisgrieser/cmp_yanky>, you can
also get suggestions from your yank history as you type in insert mode.
anuvyklack/hydra.nvim ~
To work with anuvyklack/hydra.nvim <https://github.com/anuvyklack/hydra.nvim>
only setup / mapping when yanky is activated, you can add this to your setup:
>lua
local Hydra = require("hydra")
local function t(str)
return api.nvim_replace_termcodes(str, true, true, true)
end
local yanky_hydra = Hydra({
name = "Yank ring",
mode = "n",
heads = {
{ "p", "<Plug>(YankyPutAfter)", { desc = "After" } },
{ "P", "<Plug>(YankyPutBefore)", { desc = "Before" } },
{ "<c-p>", "<Plug>(YankyPreviousEntry)", { private = true, desc = "↑" } },
{ "<c-n>", "<Plug>(YankyNextEntry)", { private = true, desc = "↓" } },
},
})
-- choose/change the mappings if you want
for key, putAction in pairs({
["p"] = "<Plug>(YankyPutAfter)",
["P"] = "<Plug>(YankyPutBefore)",
["gp"] = "<Plug>(YankyGPutAfter)",
["gP"] = "<Plug>(YankyGPutBefore)",
}) do
vim.keymap.set({ "n", "x" }, key, function()
vim.fn.feedkeys(t(putAction))
yanky_hydra:activate()
end)
end
-- choose/change the mappings if you want
for key, putAction in pairs({
["]p"] = "<Plug>(YankyPutIndentAfterLinewise)",
["[p"] = "<Plug>(YankyPutIndentBeforeLinewise)",
["]P"] = "<Plug>(YankyPutIndentAfterLinewise)",
["[P"] = "<Plug>(YankyPutIndentBeforeLinewise)",
[">p"] = "<Plug>(YankyPutIndentAfterShiftRight)",
["<p"] = "<Plug>(YankyPutIndentAfterShiftLeft)",
[">P"] = "<Plug>(YankyPutIndentBeforeShiftRight)",
["<P"] = "<Plug>(YankyPutIndentBeforeShiftLeft)",
["=p"] = "<Plug>(YankyPutAfterFilter)",
["=P"] = "<Plug>(YankyPutBeforeFilter)",
}) do
vim.keymap.set("n", key, function()
vim.fn.feedkeys(t(putAction))
yanky_hydra:activate()
end)
end
<
🎉 CREDITS *yanky-🍃-yanky.nvim-🎉-credits*
This plugin is mostly a lua version of svermeulen/vim-yoink
<https://github.com/svermeulen/vim-yoink> awesome plugin.
Other inspiration :
- bfredl/nvim-miniyank <https://github.com/bfredl/nvim-miniyank>
- maxbrunsfeld/vim-yankstack <https://github.com/maxbrunsfeld/vim-yankstack>
- svermeulen/vim-easyclip <https://github.com/svermeulen/vim-easyclip>
- bkoropoff/yankee.vim <https://github.com/bkoropoff/yankee.vim>
- svban/YankAssassin.vim <https://github.com/svban/YankAssassin.vim>
- tpope/vim-unimpaired <https://github.com/tpope/vim-unimpaired>
- inkarkat/vim-UnconditionalPaste <https://github.com/inkarkat/vim-UnconditionalPaste>
==============================================================================
2. Links *yanky-links*
1. *Lua*: https://img.shields.io/badge/Made%20with%20Lua-blueviolet.svg?style=for-the-badge&logo=lua
2. *GitHub Workflow Status*: https://img.shields.io/github/actions/workflow/status/gbprod/yanky.nvim/integration.yml?branch=main&style=for-the-badge
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -0,0 +1,6 @@
local telescope = require("telescope")
local get_exports = require("yanky.telescope.yank_history").get_exports
return telescope.register_extension({
exports = get_exports(),
})

View File

@ -0,0 +1,404 @@
local utils = require("yanky.utils")
local highlight = require("yanky.highlight")
local system_clipboard = require("yanky.system_clipboard")
local preserve_cursor = require("yanky.preserve_cursor")
local picker = require("yanky.picker")
local textobj = require("yanky.textobj")
local yanky = {}
yanky.ring = {
state = nil,
is_cycling = false,
callback = nil,
}
yanky.direction = {
FORWARD = 1,
BACKWARD = -1,
}
yanky.type = {
PUT_BEFORE = "P",
PUT_AFTER = "p",
GPUT_BEFORE = "gP",
GPUT_AFTER = "gp",
PUT_INDENT_AFTER = "]p",
PUT_INDENT_BEFORE = "[p",
}
function yanky.setup(options)
yanky.config = require("yanky.config")
yanky.config.setup(options)
yanky.history = require("yanky.history")
yanky.history.setup()
system_clipboard.setup()
highlight.setup()
preserve_cursor.setup()
picker.setup()
local yanky_augroup = vim.api.nvim_create_augroup("Yanky", { clear = true })
vim.api.nvim_create_autocmd("TextYankPost", {
group = yanky_augroup,
pattern = "*",
callback = function(_)
yanky.on_yank()
end,
})
if vim.v.vim_did_enter == 1 then
yanky.init_history()
else
vim.api.nvim_create_autocmd("VimEnter", {
group = yanky_augroup,
pattern = "*",
callback = yanky.init_history,
})
end
vim.api.nvim_create_user_command("YankyClearHistory", yanky.clear_history, {})
end
function yanky.init_history()
yanky.history.push(utils.get_register_info(utils.get_default_register()))
yanky.history.sync_with_numbered_registers()
end
local function do_put(state, _)
if state.is_visual then
vim.cmd([[execute "normal! \<esc>"]])
end
local ok, val = pcall(
vim.cmd,
string.format(
'silent normal! %s"%s%s%s',
state.is_visual and "gv" or "",
state.register ~= "=" and state.register or "=" .. vim.api.nvim_replace_termcodes("<CR>", true, false, true),
state.count,
state.type
)
)
if not ok then
vim.notify(val, vim.log.levels.WARN)
return
end
highlight.highlight_put(state)
end
function yanky.put(type, is_visual, callback)
if not vim.tbl_contains(vim.tbl_values(yanky.type), type) then
vim.notify("Invalid type " .. type, vim.log.levels.ERROR)
return
end
yanky.ring.state = nil
yanky.ring.is_cycling = false
yanky.ring.callback = callback or do_put
-- On Yank event is not triggered when put from expression register,
-- To allows cycling, we must store value here
if vim.v.register == "=" then
local entry = utils.get_register_info("=")
entry.filetype = vim.bo.filetype
yanky.history.push(entry)
end
yanky.init_ring(type, vim.v.register, vim.v.count, is_visual, yanky.ring.callback)
end
function yanky.clear_ring()
if yanky.can_cycle() and nil ~= yanky.ring.state.augroup then
vim.api.nvim_clear_autocmds({ group = yanky.ring.state.augroup })
end
yanky.ring.state = nil
yanky.ring.is_cycling = false
end
function yanky.attach_cancel()
if yanky.config.options.ring.cancel_event == "move" then
yanky.ring.state.augroup = vim.api.nvim_create_augroup("YankyRingClear", { clear = true })
vim.schedule(function()
vim.api.nvim_create_autocmd("CursorMoved", {
group = yanky.ring.state.augroup,
buffer = 0,
callback = yanky.clear_ring,
})
end)
else
vim.api.nvim_buf_attach(0, false, {
on_lines = function(_)
yanky.clear_ring()
return true
end,
})
end
end
function yanky.init_ring(type, register, count, is_visual, callback)
register = (register ~= '"' and register ~= "_") and register or utils.get_default_register()
local reg_content = vim.fn.getreg(register)
if nil == reg_content or "" == reg_content then
vim.notify(string.format('Register "%s" is empty', register), vim.log.levels.WARN)
return
end
local new_state = {
type = type,
register = register,
count = count > 0 and count or 1,
is_visual = is_visual,
use_repeat = callback == nil,
}
if nil ~= callback then
callback(new_state, do_put)
end
yanky.ring.state = new_state
yanky.ring.is_cycling = false
yanky.attach_cancel()
if yanky.config.options.textobj.enabled then
textobj.save_put()
end
end
function yanky.can_cycle()
return nil ~= yanky.ring.state
end
function yanky.cycle(direction)
if not yanky.can_cycle() then
vim.notify("Your last action was not put, ignoring cycle", vim.log.levels.INFO)
return
end
direction = direction or yanky.direction.FORWARD
if not vim.tbl_contains(vim.tbl_values(yanky.direction), direction) then
vim.notify("Invalid direction for cycle", vim.log.levels.ERROR)
return
end
if nil ~= yanky.ring.state.augroup then
vim.api.nvim_clear_autocmds({ group = yanky.ring.state.augroup })
end
if not yanky.ring.is_cycling then
yanky.history.reset()
local reg = utils.get_register_info(yanky.ring.state.register)
local first = yanky.history.first()
if nil ~= first and reg.regcontents == first.regcontents and reg.regtype == first.regtype then
yanky.history.skip()
end
end
local new_state = yanky.ring.state
local next_content
if direction == yanky.direction.FORWARD then
next_content = yanky.history.next()
if nil == next_content then
vim.notify("Reached oldest item", vim.log.levels.INFO)
yanky.attach_cancel()
return
end
else
next_content = yanky.history.previous()
if nil == next_content then
vim.notify("Reached first item", vim.log.levels.INFO)
yanky.attach_cancel()
return
end
end
yanky.ring.state.register = yanky.ring.state.register ~= "=" and yanky.ring.state.register
or utils.get_default_register()
utils.use_temporary_register(yanky.ring.state.register, next_content, function()
if new_state.use_repeat then
local ok, val = pcall(vim.cmd, "silent normal! u.")
if not ok then
vim.notify(val, vim.log.levels.WARN)
yanky.attach_cancel()
return
end
highlight.highlight_put(new_state)
else
local ok, val = pcall(vim.cmd, "silent normal! u")
if not ok then
vim.notify(val, vim.log.levels.WARN)
yanky.attach_cancel()
return
end
yanky.ring.callback(new_state, do_put)
end
end)
if yanky.config.options.ring.update_register_on_cycle then
vim.fn.setreg(new_state.register, next_content.regcontents, next_content.regtype)
end
yanky.ring.is_cycling = true
yanky.ring.state = new_state
yanky.attach_cancel()
end
function yanky.on_yank()
if vim.tbl_contains(yanky.config.options.ring.ignore_registers, vim.v.register) then
return
end
-- Only historize first delete in visual mode
if vim.v.event.visual and vim.v.event.operator == "d" and yanky.ring.is_cycling then
return
end
local entry = utils.get_register_info(vim.v.event.regname)
entry.filetype = vim.bo.filetype
yanky.history.push(entry)
preserve_cursor.on_yank()
end
function yanky.yank(options)
options = options or {}
preserve_cursor.yank()
return string.format("%sy", options.register and '"' .. options.register or "")
end
function yanky.clear_history()
yanky.history.clear()
end
function yanky.register_plugs()
local yanky_wrappers = require("yanky.wrappers")
vim.keymap.set("n", "<Plug>(YankyCycleForward)", function()
yanky.cycle(1)
end, { silent = true })
vim.keymap.set("n", "<Plug>(YankyCycleBackward)", function()
yanky.cycle(-1)
end, { silent = true })
vim.keymap.set("n", "<Plug>(YankyPreviousEntry)", function()
yanky.cycle(1)
end, { silent = true })
vim.keymap.set("n", "<Plug>(YankyNextEntry)", function()
yanky.cycle(-1)
end, { silent = true })
vim.keymap.set({ "n", "x" }, "<Plug>(YankyYank)", yanky.yank, { silent = true, expr = true })
for type, type_text in pairs({
p = "PutAfter",
P = "PutBefore",
gp = "GPutAfter",
gP = "GPutBefore",
["]p"] = "PutIndentAfter",
["[p"] = "PutIndentBefore",
}) do
vim.keymap.set("n", string.format("<Plug>(Yanky%s)", type_text), function()
yanky.put(type, false)
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%s)", type_text), function()
yanky.put(type, true)
end, { silent = true })
vim.keymap.set("n", string.format("<Plug>(Yanky%sJoined)", type_text), function()
yanky.put(type, false, yanky_wrappers.trim_and_join_lines())
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%sJoined)", type_text), function()
yanky.put(type, true, yanky_wrappers.trim_and_join_lines())
end, { silent = true })
vim.keymap.set("n", string.format("<Plug>(Yanky%sLinewise)", type_text), function()
yanky.put(type, false, yanky_wrappers.linewise())
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%sLinewise)", type_text), function()
yanky.put(type, true, yanky_wrappers.linewise())
end, { silent = true })
vim.keymap.set("n", string.format("<Plug>(Yanky%sLinewiseJoined)", type_text), function()
yanky.put(type, false, yanky_wrappers.linewise(yanky_wrappers.trim_and_join_lines()))
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%sLinewiseJoined)", type_text), function()
yanky.put(type, true, yanky_wrappers.linewise(yanky_wrappers.trim_and_join_lines()))
end, { silent = true })
vim.keymap.set("n", string.format("<Plug>(Yanky%sCharwise)", type_text), function()
yanky.put(type, false, yanky_wrappers.charwise())
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%sCharwise)", type_text), function()
yanky.put(type, true, yanky_wrappers.charwise())
end, { silent = true })
vim.keymap.set("n", string.format("<Plug>(Yanky%sCharwiseJoined)", type_text), function()
yanky.put(type, false, yanky_wrappers.charwise(yanky_wrappers.trim_and_join_lines()))
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%sCharwiseJoined)", type_text), function()
yanky.put(type, true, yanky_wrappers.charwise(yanky_wrappers.trim_and_join_lines()))
end, { silent = true })
vim.keymap.set("n", string.format("<Plug>(Yanky%sBlockwise)", type_text), function()
yanky.put(type, false, yanky_wrappers.blockwise())
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%sBlockwise)", type_text), function()
yanky.put(type, true, yanky_wrappers.blockwise())
end, { silent = true })
vim.keymap.set("n", string.format("<Plug>(Yanky%sBlockwiseJoined)", type_text), function()
yanky.put(type, false, yanky_wrappers.blockwise(yanky_wrappers.trim_and_join_lines()))
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%sBlockwiseJoined)", type_text), function()
yanky.put(type, true, yanky_wrappers.blockwise(yanky_wrappers.trim_and_join_lines()))
end, { silent = true })
for change, change_text in pairs({ [">>"] = "ShiftRight", ["<<"] = "ShiftLeft", ["=="] = "Filter" }) do
vim.keymap.set("n", string.format("<Plug>(Yanky%s%s)", type_text, change_text), function()
yanky.put(type, false, yanky_wrappers.linewise(yanky_wrappers.change(change)))
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%s%s)", type_text, change_text), function()
yanky.put(type, true, yanky_wrappers.linewise(yanky_wrappers.change(change)))
end, { silent = true })
vim.keymap.set("n", string.format("<Plug>(Yanky%s%sJoined)", type_text, change_text), function()
yanky.put(
type,
false,
yanky_wrappers.linewise(yanky_wrappers.trim_and_join_lines(yanky_wrappers.change(change)))
)
end, { silent = true })
vim.keymap.set("x", string.format("<Plug>(Yanky%s%sJoined)", type_text, change_text), function()
yanky.put(
type,
true,
yanky_wrappers.linewise(yanky_wrappers.trim_and_join_lines(yanky_wrappers.change(change)))
)
end, { silent = true })
end
end
end
return yanky

View File

@ -0,0 +1,45 @@
local config = {}
config.options = {}
local default_values = {
ring = {
history_length = 100,
storage = "shada",
storage_path = vim.fn.stdpath("data") .. "/databases/yanky.db",
sync_with_numbered_registers = true,
ignore_registers = { "_" },
cancel_event = "update",
update_register_on_cycle = false,
},
system_clipboard = {
sync_with_ring = true,
clipboard_register = nil,
},
highlight = {
on_put = true,
on_yank = true,
timer = 500,
},
preserve_cursor_position = {
enabled = true,
},
picker = {
select = {
action = nil,
},
telescope = {
use_default_mappings = true,
mappings = nil,
},
},
textobj = {
enabled = false,
},
}
function config.setup(options)
config.options = vim.tbl_deep_extend("force", default_values, options or {})
end
return config

View File

@ -0,0 +1,64 @@
local highlight = {}
function highlight.setup()
highlight.config = require("yanky.config").options.highlight
if highlight.config.on_put then
highlight.hl_put = vim.api.nvim_create_namespace("yanky.put")
highlight.timer = vim.loop.new_timer()
vim.api.nvim_set_hl(0, "YankyPut", { link = "Search", default = true })
end
if highlight.config.on_yank then
vim.api.nvim_create_autocmd("TextYankPost", {
pattern = "*",
callback = function(_)
pcall(vim.highlight.on_yank, { higroup = "YankyYanked", timeout = highlight.config.timer })
end,
})
vim.api.nvim_set_hl(0, "YankyYanked", { link = "Search", default = true })
end
end
local function get_region()
local start = vim.api.nvim_buf_get_mark(0, "[")
local finish = vim.api.nvim_buf_get_mark(0, "]")
return {
start_row = start[1] - 1,
start_col = start[2],
end_row = finish[1] - 1,
end_col = finish[2],
}
end
function highlight.highlight_put(state)
if not highlight.config.on_put then
return
end
highlight.timer:stop()
vim.api.nvim_buf_clear_namespace(0, highlight.hl_put, 0, -1)
local region = get_region()
vim.highlight.range(
0,
highlight.hl_put,
"YankyPut",
{ region.start_row, region.start_col },
{ region.end_row, region.end_col },
{ regtype = vim.fn.getregtype(state.register), inclusive = true }
)
highlight.timer:start(
highlight.config.timer,
0,
vim.schedule_wrap(function()
vim.api.nvim_buf_clear_namespace(0, highlight.hl_put, 0, -1)
end)
)
end
return highlight

View File

@ -0,0 +1,85 @@
local history = {
storage = nil,
position = 1,
config = nil,
}
function history.setup()
history.config = require("yanky.config").options.ring
history.storage = require("yanky.storage." .. history.config.storage)
if false == history.storage.setup() then
history.storage = require("yanky.storage.memory")
end
end
function history.push(item)
local prev = history.storage.get(1)
if prev ~= nil and prev.regcontents == item.regcontents and prev.regtype == item.regtype then
return
end
history.storage.push(item)
history.sync_with_numbered_registers()
end
function history.sync_with_numbered_registers()
if history.config.sync_with_numbered_registers then
for i = 1, math.min(history.storage.length(), 9) do
local reg = history.storage.get(i)
vim.fn.setreg(i, reg.regcontents, reg.regtype)
end
end
end
function history.first()
if history.storage.length() <= 0 then
return nil
end
return history.storage.get(1)
end
function history.skip()
history.position = history.position + 1
end
function history.next()
local new_position = history.position + 1
if new_position > history.storage.length() then
return nil
end
history.position = new_position
return history.storage.get(history.position)
end
function history.previous()
if history.position == 1 then
return nil
end
history.position = history.position - 1
return history.storage.get(history.position)
end
function history.reset()
history.position = 0
end
function history.all()
return history.storage.all()
end
function history.clear()
history.storage.clear()
history.position = 1
end
function history.delete(index)
history.storage.delete(index)
end
return history

View File

@ -0,0 +1,13 @@
local yanky = require("yanky")
local integration = {}
function integration.substitute()
return function(event)
local is_visual = require("substitute.utils").is_visual(event.vmode)
yanky.init_ring("p", event.register, event.count, is_visual)
end
end
return integration

View File

@ -0,0 +1,86 @@
local utils = require("yanky.utils")
local picker = {
actions = {},
}
function picker.setup()
vim.api.nvim_create_user_command("YankyRingHistory", picker.select_in_history, {})
end
function picker.select_in_history()
local history = {}
for index, value in pairs(require("yanky.history").all()) do
value.history_index = index
history[index] = value
end
local config = require("yanky.config").options.picker.select
local action = config.action or require("yanky.picker").actions.put("p", false)
vim.ui.select(history, {
prompt = "Ring history",
format_item = function(item)
return item.regcontents and item.regcontents:gsub("\n", "\\n") or ""
end,
}, action)
end
function picker.actions.put(type, is_visual)
local yanky = require("yanky")
if not vim.tbl_contains(vim.tbl_values(yanky.type), type) then
vim.notify("Invalid type " .. type, vim.log.levels.ERROR)
return
end
return function(next_content)
if nil == next_content then
return
end
utils.use_temporary_register(utils.get_default_register(), next_content, function()
yanky.put(type, is_visual)
end)
end
end
function picker.actions.delete()
return function(content)
if nil == content then
return
end
local yanky = require("yanky")
yanky.history.delete(content.history_index)
end
end
function picker.actions.set_register(register)
return function(content)
if nil == content then
return
end
vim.fn.setreg(register, content.regcontents, content.regtype)
end
end
function picker.actions.special_put(name, is_visual)
if "" == vim.fn.maparg(string.format("<Plug>(%s)", name), "n") then
vim.notify("Invalid special put " .. type, vim.log.levels.ERROR)
return
end
return function(next_content)
if nil == next_content then
return
end
utils.use_temporary_register(utils.get_default_register(), next_content, function()
vim.fn.maparg(string.format("<Plug>(%s)", name), is_visual and "x" or "n", false, true).callback()
end)
end
end
return picker

View File

@ -0,0 +1,50 @@
local preserve_cursor = {}
preserve_cursor.state = {
cusor_position = nil,
win_state = nil,
}
function preserve_cursor.setup()
preserve_cursor.config = require("yanky.config").options.preserve_cursor_position
end
function preserve_cursor.on_yank()
if not preserve_cursor.config.enabled then
return
end
if nil ~= preserve_cursor.state.cusor_position then
vim.fn.setpos(".", preserve_cursor.state.cusor_position)
vim.fn.winrestview(preserve_cursor.state.win_state)
preserve_cursor.state = {
cusor_position = nil,
win_state = nil,
}
end
end
function preserve_cursor.yank()
if not preserve_cursor.config.enabled then
return
end
preserve_cursor.state = {
cusor_position = vim.fn.getpos("."),
win_state = vim.fn.winsaveview(),
}
vim.api.nvim_buf_attach(0, false, {
on_lines = function()
preserve_cursor.state = {
cusor_position = nil,
win_state = nil,
}
return true
end,
})
end
return preserve_cursor

View File

@ -0,0 +1,37 @@
local memory = {
state = {},
}
function memory.setup()
memory.config = require("yanky.config").options.ring
end
function memory.push(item)
table.insert(memory.state, 1, item)
if #memory.state > memory.config.history_length then
table.remove(memory.state)
end
end
function memory.get(n)
return memory.state[n]
end
function memory.length()
return #memory.state
end
function memory.all()
return memory.state
end
function memory.clear()
memory.state = {}
end
function memory.delete(index)
table.remove(memory.state, index)
end
return memory

View File

@ -0,0 +1,53 @@
local shada = {}
function shada.setup()
shada.config = require("yanky.config").options.ring
end
function shada.push(item)
local copy = vim.deepcopy(vim.g.YANKY_HISTORY)
table.insert(copy, 1, item)
if #copy > shada.config.history_length then
table.remove(copy)
end
vim.g.YANKY_HISTORY = copy
end
function shada.get(n)
if nil == vim.g.YANKY_HISTORY then
vim.g.YANKY_HISTORY = {}
end
return vim.g.YANKY_HISTORY[n]
end
function shada.length()
if nil == vim.g.YANKY_HISTORY then
vim.g.YANKY_HISTORY = {}
end
return #vim.g.YANKY_HISTORY
end
function shada.all()
if nil == vim.g.YANKY_HISTORY then
vim.g.YANKY_HISTORY = {}
end
return vim.g.YANKY_HISTORY
end
function shada.clear()
vim.g.YANKY_HISTORY = {}
end
function shada.delete(index)
local copy = vim.deepcopy(vim.g.YANKY_HISTORY)
table.remove(copy, index)
vim.g.YANKY_HISTORY = copy
end
return shada

View File

@ -0,0 +1,90 @@
local sqlite = {
db = nil,
}
function sqlite.setup()
sqlite.config = require("yanky.config").options.ring
local has_sqlite, connection = pcall(require, "sqlite")
if not has_sqlite then
if type(connection) ~= "string" then
vim.notify("Couldn't find sqlite.lua.", vim.log.levels.ERROR, {})
else
vim.notify("Found sqlite.lua: but got the following error: " .. connection)
end
return false
end
vim.fn.mkdir(string.match(sqlite.config.storage_path, "(.*[/\\])"), "p")
sqlite.db = connection:open(sqlite.config.storage_path)
if not sqlite.db then
vim.notify("Error in opening DB", vim.log.levels.ERROR)
return
end
if not sqlite.db:exists("history") then
sqlite.db:create("history", {
id = { "integer", "primary", "key", "autoincrement" },
regcontents = "text",
regtype = "text",
filetype = "text",
})
end
sqlite.db:close()
end
function sqlite.push(item)
sqlite.db:with_open(function()
sqlite.db:eval(
"INSERT INTO history (filetype, regcontents, regtype) VALUES (:filetype, :regcontents, :regtype)",
item
)
sqlite.db:eval(
string.format(
"DELETE FROM history WHERE id NOT IN (SELECT id FROM history ORDER BY id DESC LIMIT %s)",
sqlite.config.history_length
)
)
end)
end
function sqlite.get(index)
return sqlite.db:with_open(function()
return sqlite.db:select("history", { order_by = { desc = "id" }, limit = { 1, index - 1 } })[1]
end)
end
function sqlite.length()
return sqlite.db:with_open(function()
return sqlite.db:tbl("history"):count()
end)
end
function sqlite.all()
return sqlite.db:with_open(function()
return sqlite.db:select("history", { order_by = { desc = "id" } })
end)
end
function sqlite.clear()
return sqlite.db:with_open(function()
return sqlite.db:delete("history")
end)
end
function sqlite.delete(index)
return sqlite.db:with_open(function()
return sqlite.db:eval(
string.format(
"DELETE FROM history WHERE id IN (SELECT id FROM history ORDER BY id DESC LIMIT 1 OFFSET %s)",
index - 1
)
)
end)
end
return sqlite

View File

@ -0,0 +1,64 @@
local utils = require("yanky.utils")
local system_clipboard = {
state = {
reg_info_on_focus_lost = nil,
},
}
function system_clipboard.setup()
system_clipboard.config = require("yanky.config").options.system_clipboard
system_clipboard.config.clipboard_register = system_clipboard.config.clipboard_register or utils.get_system_register()
system_clipboard.history = require("yanky.history")
if system_clipboard.config.sync_with_ring then
local yanky_clipboard_augroup = vim.api.nvim_create_augroup("YankySyncClipboard", { clear = true })
local fetching = false
vim.api.nvim_create_autocmd("FocusGained", {
group = yanky_clipboard_augroup,
pattern = "*",
callback = function(_)
if fetching then
return
end
fetching = true
local ok, err = pcall(system_clipboard.on_focus_gained)
vim.schedule(function()
fetching = false
end)
if not ok then
error(err)
end
end,
})
vim.api.nvim_create_autocmd("FocusLost", {
group = yanky_clipboard_augroup,
pattern = "*",
callback = function(_)
if fetching then
return
end
system_clipboard.on_focus_lost()
end,
})
end
end
function system_clipboard.on_focus_lost()
system_clipboard.state.reg_info_on_focus_lost = utils.get_register_info(system_clipboard.config.clipboard_register)
end
function system_clipboard.on_focus_gained()
local new_reg_info = utils.get_register_info(system_clipboard.config.clipboard_register)
if
system_clipboard.state.reg_info_on_focus_lost ~= nil
and not vim.deep_equal(system_clipboard.state.reg_info_on_focus_lost, new_reg_info)
then
system_clipboard.history.push(new_reg_info)
end
system_clipboard.state.reg_info_on_focus_lost = nil
end
return system_clipboard

View File

@ -0,0 +1,103 @@
local picker = require("yanky.picker")
local utils = require("yanky.utils")
local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")
local mapping = {
state = { is_visual = false },
}
function mapping.put(type)
return function(prompt_bufnr)
if vim.api.nvim_buf_is_valid(prompt_bufnr) then
actions.close(prompt_bufnr)
end
local selection = action_state.get_selected_entry()
-- fix cursor position since
-- https://github.com/nvim-telescope/telescope.nvim/commit/3eb90430b61b78b707e8ffe0cfe49138daaddbcc
local cursor_pos = nil
if vim.api.nvim_get_mode().mode == "i" then
cursor_pos = vim.api.nvim_win_get_cursor(0)
end
vim.schedule(function()
if nil ~= cursor_pos then
vim.api.nvim_win_set_cursor(0, { cursor_pos[1], math.max(cursor_pos[2] - 1, 0) })
end
picker.actions.put(type, mapping.state.is_visual)(selection.value)
end)
end
end
function mapping.special_put(name)
return function(prompt_bufnr)
if vim.api.nvim_buf_is_valid(prompt_bufnr) then
actions.close(prompt_bufnr)
end
local selection = action_state.get_selected_entry()
-- fix cursor position since
-- https://github.com/nvim-telescope/telescope.nvim/commit/3eb90430b61b78b707e8ffe0cfe49138daaddbcc
local cursor_pos = nil
if vim.api.nvim_get_mode().mode == "i" then
cursor_pos = vim.api.nvim_win_get_cursor(0)
end
vim.schedule(function()
if nil ~= cursor_pos then
vim.api.nvim_win_set_cursor(0, { cursor_pos[1], math.max(cursor_pos[2] - 1, 0) })
end
picker.actions.special_put(name, mapping.state.is_visual)(selection.value)
end)
end
end
function mapping.delete()
return function(prompt_bufnr)
local current_picker = action_state.get_current_picker(prompt_bufnr)
current_picker:delete_selection(function(selection)
picker.actions.delete()(selection.value)
end)
end
end
function mapping.set_register(register)
return function(prompt_bufnr)
if vim.api.nvim_buf_is_valid(prompt_bufnr) then
actions.close(prompt_bufnr)
end
local selection = action_state.get_selected_entry()
vim.schedule(function()
picker.actions.set_register(register)(selection.value)
end)
end
end
function mapping.put_and_set_register(type, register)
return function(prompt_bufnr)
mapping.put(type)(prompt_bufnr)
mapping.set_register(register)(prompt_bufnr)
end
end
function mapping.get_defaults()
return {
default = mapping.put("p"),
i = {
["<c-g>"] = mapping.put("p"),
["<c-k>"] = mapping.put("P"),
["<c-x>"] = mapping.delete(),
["<c-r>"] = mapping.set_register(utils.get_default_register()),
},
n = {
p = mapping.put("p"),
P = mapping.put("P"),
d = mapping.delete(),
r = mapping.set_register(utils.get_default_register()),
},
}
end
return mapping

View File

@ -0,0 +1,128 @@
local pickers = require("telescope.pickers")
local finders = require("telescope.finders")
local previewers = require("telescope.previewers")
local actions = require("telescope.actions")
local entry_display = require("telescope.pickers.entry_display")
local conf = require("telescope.config").values
local mapping = require("yanky.telescope.mapping")
local config = require("yanky.config")
local yank_history = {}
function yank_history.get_exports()
return {
yank_history = yank_history.yank_history,
}
end
local regtype_to_text = function(regtype)
if "v" == regtype then
return "charwise"
end
if "V" == regtype then
return "linewise"
end
return "blockwise"
end
local format_title = function(entry)
return regtype_to_text(entry.value.regtype)
end
function yank_history.previewer()
return previewers.new_buffer_previewer({
dyn_title = function(_, entry)
return format_title(entry)
end,
define_preview = function(self, entry)
vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, true, vim.split(entry.value.regcontents, "\n"))
if entry.value.filetype ~= nil then
vim.bo[self.state.bufnr].filetype = entry.value.filetype
end
end,
})
end
function yank_history.attach_mappings(_, map)
local mappings = config.options.picker.telescope.use_default_mappings
and vim.tbl_deep_extend("force", mapping.get_defaults(), config.options.picker.telescope.mappings or {})
or (config.options.picker.telescope.mappings or {})
if mappings.default then
actions.select_default:replace(mappings.default)
end
for _, mode in pairs({ "i", "n" }) do
if mappings[mode] then
for keys, action in pairs(mappings[mode]) do
map(mode, keys, action)
end
end
end
return true
end
function yank_history.gen_from_history(opts)
local displayer = entry_display.create({
separator = " ",
items = {
{ width = #tostring(opts.history_length) },
{ remaining = true },
},
})
local make_display = function(entry)
local content = entry.content
return displayer({
{ entry.value.history_index, "TelescopeResultsNumber" },
content:gsub("\n", "\\n"),
})
end
return function(entry)
return {
valid = true,
value = entry,
ordinal = entry.regcontents,
content = entry.regcontents,
display = make_display,
}
end
end
function yank_history.yank_history(opts)
local is_visual = vim.fn.mode() == "v" or vim.fn.mode() == "V"
if is_visual then
vim.cmd([[execute "normal! \<esc>"]])
end
mapping.state.is_visual = is_visual
opts = opts or {}
local history = {}
for index, value in pairs(require("yanky.history").all()) do
value.history_index = index
history[index] = value
end
opts.history_length = #history
pickers
.new(opts, {
prompt_title = "Yank history",
finder = finders.new_table({
results = history,
entry_maker = yank_history.gen_from_history(opts),
}),
attach_mappings = yank_history.attach_mappings,
previewer = yank_history.previewer(),
sorter = conf.generic_sorter(opts),
})
:find()
end
return yank_history

View File

@ -0,0 +1,63 @@
local textobj = {
state = nil,
}
local function get_region(regtype)
local start = vim.api.nvim_buf_get_mark(0, "[")
local finish = vim.api.nvim_buf_get_mark(0, "]")
return {
start_row = start[1],
start_col = "V" ~= regtype and start[2] or 0,
end_row = finish[1],
end_col = "V" ~= regtype and finish[2] or vim.fn.col("$"),
}
end
local function is_visual_mode()
return nil ~= vim.fn.mode():find("v")
end
local function set_selection(startpos, endpos)
vim.api.nvim_win_set_cursor(0, startpos)
if is_visual_mode() then
vim.cmd("normal! o")
else
vim.cmd("normal! v")
end
vim.api.nvim_win_set_cursor(0, endpos)
end
function textobj.save_put()
vim.b.yanky_textobj = {
region = get_region(vim.fn.getregtype(vim.v.register)),
regtype = vim.fn.getregtype(vim.v.register),
}
vim.api.nvim_buf_attach(0, false, {
on_lines = function(_, _, _, first_line)
if vim.b.yanky_textobj and (first_line <= vim.b.yanky_textobj.region.end_row) then
vim.b.yanky_textobj = nil
return true
end
end,
})
end
function textobj.last_put()
if nil == vim.b.yanky_textobj then
vim.notify("No last put text-object", vim.log.levels.INFO)
return
end
set_selection({
vim.b.yanky_textobj.region.start_row,
vim.b.yanky_textobj.region.start_col,
}, {
vim.b.yanky_textobj.region.end_row,
vim.b.yanky_textobj.region.end_col,
})
end
return textobj

View File

@ -0,0 +1,45 @@
local utils = {}
function utils.get_default_register()
local clipboard_tool = vim.fn["provider#clipboard#Executable"]()
if not clipboard_tool or "" == clipboard_tool then
return '"'
end
local clipboard_flags = vim.split(vim.api.nvim_get_option("clipboard"), ",")
if vim.tbl_contains(clipboard_flags, "unnamedplus") then
return "+"
end
if vim.tbl_contains(clipboard_flags, "unnamed") then
return "*"
end
return '"'
end
function utils.get_system_register()
local clipboardFlags = vim.split(vim.api.nvim_get_option("clipboard"), ",")
if vim.tbl_contains(clipboardFlags, "unnamedplus") then
return "+"
end
return "*"
end
function utils.get_register_info(register)
return {
regcontents = vim.fn.getreg(register),
regtype = vim.fn.getregtype(register),
}
end
function utils.use_temporary_register(register, register_info, callback)
local current_register_info = utils.get_register_info(register)
vim.fn.setreg(register, register_info.regcontents, register_info.regtype)
callback()
vim.fn.setreg(register, current_register_info.regcontents, current_register_info.regtype)
end
return utils

View File

@ -0,0 +1,101 @@
local wrappers = {}
function wrappers.linewise(next)
return function(state, callback)
local body = vim.fn.getreg(state.register)
local type = vim.fn.getregtype(state.register)
vim.fn.setreg(state.register, body, "l")
if nil == next then
callback(state)
else
next(state, callback)
end
vim.fn.setreg(state.register, body, type)
end
end
function wrappers.charwise(next)
return function(state, callback)
local body = vim.fn.getreg(state.register)
local type = vim.fn.getregtype(state.register)
local reformated_body = body:gsub("\n$", "")
vim.fn.setreg(state.register, reformated_body, "c")
if nil == next then
callback(state)
else
next(state, callback)
end
vim.fn.setreg(state.register, body, type)
end
end
function wrappers.blockwise(next)
return function(state, callback)
local body = vim.fn.getreg(state.register)
local type = vim.fn.getregtype(state.register)
vim.fn.setreg(state.register, body, "b")
if nil == next then
callback(state)
else
next(state, callback)
end
vim.fn.setreg(state.register, body, type)
end
end
function wrappers.trim_and_join_lines(next)
return function(state, callback)
local body = vim.fn.getreg(state.register)
local reformated_body = body:gsub("%s*\r?\n%s*", " "):gsub("^%s*", ""):gsub("%s*$", "")
vim.fn.setreg(state.register, reformated_body, vim.fn.getregtype(state.register))
if nil == next then
callback(state)
else
next(state, callback)
end
vim.fn.setreg(state.register, body, vim.fn.getregtype(state.register))
end
end
function wrappers.change(change, next)
return function(state, callback)
if nil == next then
callback(state)
else
next(state, callback)
end
-- local line_len = vim.api.nvim_get_current_line():len()
local cursor_pos = vim.api.nvim_win_get_cursor(0)
vim.cmd(string.format("silent '[,']normal! %s", change))
vim.api.nvim_win_set_cursor(0, cursor_pos)
vim.cmd(string.format("silent normal! %s", (state.type == "gp" or state.type == "gP") and "0" or "^"))
end
end
function wrappers.set_cursor_pos(pos, next)
return function(state, callback)
if nil == next then
callback(state)
else
next(state, callback)
end
vim.cmd(string.format("silent normal! %s", pos))
end
end
return wrappers

View File

@ -0,0 +1 @@
require("yanky").register_plugs()

View File

@ -0,0 +1,54 @@
local M = {}
function M.root(root)
local f = debug.getinfo(1, "S").source:sub(2)
return vim.fn.fnamemodify(f, ":p:h:h") .. "/" .. (root or "")
end
---@param plugin string
function M.load(plugin)
local name = plugin:match(".*/(.*)")
local package_root = M.root(".spec/site/pack/deps/start/")
if not vim.loop.fs_stat(package_root .. name) then
print("Installing " .. plugin)
vim.fn.mkdir(package_root, "p")
vim.fn.system({
"git",
"clone",
"--depth=1",
"https://github.com/" .. plugin .. ".git",
package_root .. "/" .. name,
})
end
end
function M.setup()
vim.cmd([[set runtimepath=$VIMRUNTIME]])
vim.opt.runtimepath:append(M.root())
vim.opt.packpath = { M.root(".spec/site") }
M.load("nvim-lua/plenary.nvim")
vim.api.nvim_set_option("clipboard", "")
require("yanky").setup({ ring = { storage = "memory" } })
require("yanky").register_plugs()
vim.keymap.set("n", "p", "<Plug>(YankyPutAfter)", {})
vim.keymap.set("n", "P", "<Plug>(YankyPutBefore)", {})
vim.keymap.set("x", "p", "<Plug>(YankyPutAfter)", {})
vim.keymap.set("x", "P", "<Plug>(YankyPutBefore)", {})
vim.keymap.set("n", "gp", "<Plug>(YankyGPutAfter)", {})
vim.keymap.set("n", "gP", "<Plug>(YankyGPutBefore)", {})
vim.keymap.set("x", "gp", "<Plug>(YankyGPutAfter)", {})
vim.keymap.set("x", "gP", "<Plug>(YankyGPutBefore)", {})
vim.keymap.set("n", ",p", "<Plug>(YankyCycleForward)", {})
vim.keymap.set("n", ",P", "<Plug>(YankyCycleBackward)", {})
vim.keymap.set("n", "y", "<Plug>(YankyYank)", {})
vim.keymap.set("x", "y", "<Plug>(YankyYank)", {})
end
M.setup()

View File

@ -0,0 +1,77 @@
local yanky = require("yanky")
local function get_buf_lines()
local result = vim.api.nvim_buf_get_lines(0, 0, vim.api.nvim_buf_line_count(0), false)
return result
end
local function execute_keys(feedkeys)
local keys = vim.api.nvim_replace_termcodes(feedkeys, true, false, true)
vim.api.nvim_feedkeys(keys, "x!", false)
end
local function setup()
yanky.setup({ ring = { storage = "memory" } })
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_command("buffer " .. buf)
vim.api.nvim_buf_set_lines(0, 0, -1, true, {
"void test() {",
" int a = 1;",
" int b = 2;",
" for (int i = 0; i < 10; ++i) {",
" cout << a;",
" cout << b;",
" }",
"}",
})
vim.cmd("set ft=c")
end
describe("Special Put", function()
before_each(setup)
it("should PutAfterFilter", function()
vim.cmd("5")
execute_keys("2yy")
vim.cmd("3")
vim.cmd('execute "normal \\<Plug>(YankyPutAfterFilter)"')
assert.are.same({
"void test() {",
" int a = 1;",
" int b = 2;",
" cout << a;",
" cout << b;",
" for (int i = 0; i < 10; ++i) {",
" cout << a;",
" cout << b;",
" }",
"}",
}, get_buf_lines())
assert.are.same({ 4, 4 }, vim.api.nvim_win_get_cursor(0))
end)
it("should GPutBeforeFilter", function()
vim.cmd("5")
execute_keys("2yy")
vim.cmd("4")
vim.cmd('execute "normal \\<Plug>(YankyGPutBeforeFilter)"')
assert.are.same({
"void test() {",
" int a = 1;",
" int b = 2;",
" cout << a;",
" cout << b;",
" for (int i = 0; i < 10; ++i) {",
" cout << a;",
" cout << b;",
" }",
"}",
}, get_buf_lines())
assert.are.same({ 6, 0 }, vim.api.nvim_win_get_cursor(0))
end)
end)

View File

@ -0,0 +1,29 @@
local yanky = require("yanky")
-- local system_clipboard = require("yanky.system_clipboard")
-- local utils = require("yanky.utils")
describe("Sync clipbard", function()
before_each(function()
yanky.setup({
ring = {
storage = "memory",
},
system_clipboard = {
sync_with_ring = true,
},
})
end)
it("should add system clipboard to history on focus", function()
-- vim.fn.setreg("*", "default_value", "V")
-- system_clipboard.on_focus_lost()
--
-- vim.fn.setreg("*", "new_value", "v")
-- system_clipboard.on_focus_gained()
--
-- assert.are.same({
-- regcontents = "new_value",
-- regtype = "v",
-- }, yanky.history.first())
end)
end)

View File

@ -0,0 +1,116 @@
local yanky = require("yanky")
local function execute_keys(feedkeys)
local keys = vim.api.nvim_replace_termcodes(feedkeys, true, false, true)
vim.api.nvim_feedkeys(keys, "x!", false)
end
local function get_buf_lines()
local result = vim.api.nvim_buf_get_lines(0, 0, vim.api.nvim_buf_line_count(0), false)
return result
end
local function setup()
yanky.setup({ ring = { storage = "memory" } })
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_command("buffer " .. buf)
vim.api.nvim_buf_set_lines(0, 0, -1, true, { "Lorem", "ipsum", "dolor", "sit", "amet" })
execute_keys("i<BS><C-G>u<esc>") -- Breaks undo sequence, don't know why I should do that
end
describe("Cycle", function()
before_each(setup)
it("should work in charwise mode", function()
execute_keys("yw")
execute_keys("j")
execute_keys("yw")
execute_keys("ll")
execute_keys("p")
assert.are.same({ "Lorem", "ipsipsumum", "dolor", "sit", "amet" }, get_buf_lines())
execute_keys(",p")
assert.are.same({ "Lorem", "ipsLoremum", "dolor", "sit", "amet" }, get_buf_lines())
execute_keys(",P")
assert.are.same({ "Lorem", "ipsipsumum", "dolor", "sit", "amet" }, get_buf_lines())
execute_keys(",P")
assert.are.same({ "Lorem", "ipsipsumum", "dolor", "sit", "amet" }, get_buf_lines())
end)
it("should work in linewise mode", function()
execute_keys("yy")
execute_keys("j")
execute_keys("yw")
execute_keys("j")
execute_keys("yy")
execute_keys("p")
assert.are.same({ "Lorem", "ipsum", "dolor", "dolor", "sit", "amet" }, get_buf_lines())
execute_keys(",p")
assert.are.same({ "Lorem", "ipsum", "dipsumolor", "sit", "amet" }, get_buf_lines())
execute_keys(",p")
assert.are.same({ "Lorem", "ipsum", "dolor", "Lorem", "sit", "amet" }, get_buf_lines())
end)
it("should work in visual mode", function()
execute_keys("yy")
execute_keys("j")
execute_keys("yw")
execute_keys("j")
execute_keys("yy")
execute_keys("v3l")
execute_keys("p")
assert.are.same({ "Lorem", "ipsum", "", "dolor", "r", "sit", "amet" }, get_buf_lines())
-- Should not do that but cant manage to make it works now
execute_keys(",p")
assert.are.same({ "Lorem", "ipsum", "", "dolor", "r", "sit", "amet" }, get_buf_lines())
execute_keys(",p")
assert.are.same({ "Lorem", "ipsum", "ipsumr", "sit", "amet" }, get_buf_lines())
execute_keys(",p")
assert.are.same({ "Lorem", "ipsum", "", "Lorem", "r", "sit", "amet" }, get_buf_lines())
execute_keys(",P")
assert.are.same({ "Lorem", "ipsum", "ipsumr", "sit", "amet" }, get_buf_lines())
execute_keys(",P")
assert.are.same({ "Lorem", "ipsum", "", "dolor", "r", "sit", "amet" }, get_buf_lines())
execute_keys(",P")
assert.are.same({ "Lorem", "ipsum", "dolor", "sit", "amet" }, get_buf_lines())
execute_keys(",P")
assert.are.same({ "Lorem", "ipsum", "dolor", "sit", "amet" }, get_buf_lines())
end)
it("should work in visual-block mode", function()
execute_keys("yy")
execute_keys("j")
execute_keys("yw")
execute_keys("j")
execute_keys("yy")
execute_keys("gg<c-v>jl")
execute_keys("p")
assert.are.same({ "rem", "sum", "dolor", "dolor", "sit", "amet" }, get_buf_lines())
-- Should not do that but cant manage to make it works now
execute_keys(",p")
assert.are.same({ "rem", "sum", "dolor", "dolor", "sit", "amet" }, get_buf_lines())
execute_keys(",p")
assert.are.same({ "ipsumrem", "ipsumsum", "dolor", "sit", "amet" }, get_buf_lines())
end)
end)

View File

@ -0,0 +1,155 @@
local yanky = require("yanky")
local function get_buf_lines()
local result = vim.api.nvim_buf_get_lines(0, 0, vim.api.nvim_buf_line_count(0), false)
return result
end
local function execute_keys(feedkeys)
local keys = vim.api.nvim_replace_termcodes(feedkeys, true, false, true)
vim.api.nvim_feedkeys(keys, "x!", false)
end
local function setup()
yanky.setup({ ring = { storage = "memory" } })
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_command("buffer " .. buf)
vim.api.nvim_buf_set_lines(0, 0, -1, true, { "Lorem", "ipsum", "dolor", "sit", "amet" })
end
describe("Put in charwise mode", function()
before_each(setup)
it("should paste after word in charwise mode", function()
execute_keys("yw")
execute_keys("jll")
execute_keys("p")
assert.are.same({ "Lorem", "ipsLoremum", "dolor", "sit", "amet" }, get_buf_lines())
end)
it("should paste before word in charwise mode", function()
execute_keys("lyw")
execute_keys("jjll")
execute_keys("P")
assert.are.same({ "Lorem", "ipsum", "doloremor", "sit", "amet" }, get_buf_lines())
end)
it("should be repeatable in charwise mode", function()
execute_keys("yw")
execute_keys("jll")
execute_keys("3p")
assert.are.same({ "Lorem", "ipsLoremLoremLoremum", "dolor", "sit", "amet" }, get_buf_lines())
end)
it("should use specified register in charwise mode", function()
vim.fn.setreg("a", "REGISTRED", "c")
execute_keys("jll")
execute_keys('"ap')
assert.are.same({ "Lorem", "ipsREGISTREDum", "dolor", "sit", "amet" }, get_buf_lines())
end)
end)
describe("Put in linewise mode", function()
before_each(setup)
it("should paste after in linewise mode", function()
execute_keys("yy")
execute_keys("jll")
execute_keys("p")
assert.are.same({ "Lorem", "ipsum", "Lorem", "dolor", "sit", "amet" }, get_buf_lines())
end)
it("should paste before in linewise mode", function()
execute_keys("yy")
execute_keys("jll")
execute_keys("P")
assert.are.same({ "Lorem", "Lorem", "ipsum", "dolor", "sit", "amet" }, get_buf_lines())
end)
it("should be repeatable in linewise mode", function()
execute_keys("2yy")
execute_keys("jll")
execute_keys("3p")
assert.are.same(
{ "Lorem", "ipsum", "Lorem", "ipsum", "Lorem", "ipsum", "Lorem", "ipsum", "dolor", "sit", "amet" },
get_buf_lines()
)
end)
it("should use specified register in linewise mode", function()
vim.fn.setreg("b", "REGISTRED", "l")
execute_keys("jll")
execute_keys('"bp')
assert.are.same({ "Lorem", "ipsum", "REGISTRED", "dolor", "sit", "amet" }, get_buf_lines())
end)
end)
describe("Put in blocwise mode", function()
before_each(setup)
it("should paste after", function()
execute_keys("<c-v>jjlly")
execute_keys("gg^")
execute_keys("jll")
execute_keys("p")
assert.are.same({ "Lorem", "ipsLorum", "dolipsor", "sitdol", "amet" }, get_buf_lines())
end)
it("should paste before", function()
execute_keys("<c-v>jjlly")
execute_keys("gg^")
execute_keys("jll")
execute_keys("P")
assert.are.same({ "Lorem", "ipLorsum", "doipslor", "sidolt", "amet" }, get_buf_lines())
end)
it("should be repeatable", function()
execute_keys("<c-v>jjlly")
execute_keys("gg^")
execute_keys("jll")
execute_keys("3p")
assert.are.same({ "Lorem", "ipsLorLorLorum", "dolipsipsipsor", "sitdoldoldol", "amet" }, get_buf_lines())
end)
end)
describe("Put in visual mode", function()
before_each(setup)
it("should paste after", function()
execute_keys("y3l")
execute_keys("jvll")
execute_keys("p")
assert.are.same({ "Lorem", "Lorum", "dolor", "sit", "amet" }, get_buf_lines())
end)
it("should paste in linewise visual selection", function()
execute_keys("y3l")
execute_keys("jV")
execute_keys("p")
assert.are.same({ "Lorem", "Lor", "dolor", "sit", "amet" }, get_buf_lines())
end)
it("should be repeatable", function()
execute_keys("y3l")
execute_keys("j")
execute_keys("vll")
execute_keys("3p")
assert.are.same({ "Lorem", "LorLorLorum", "dolor", "sit", "amet" }, get_buf_lines())
end)
end)

View File

@ -0,0 +1,7 @@
column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
no_call_parentheses = false