Emacs-style kill-ring for VSCode that is designed to work with VSCodeVim.
Paste the most recent thing you copied with p, and — immediately after — cycle
backward and forward through your clipboard history with [p / ]p to correct
the paste in place. It is the emacs yank / yank-pop workflow, wired for vim
keybindings.
What it does
- Every copy/cut/yank (from vim, from VSCode, or from any other application) is captured into a ring of recent entries.
p/Ppaste the current ring entry.- Right after a paste,
[pwalks to older entries and]pwalks back toward newer ones, replacing the just-pasted text each time. This lets you "fix" a paste without deleting and re-pasting. - A picker (
killring.showRing, bound toAlt+Yby default) lists the whole ring so you can jump straight to any entry.
Requirements
This extension captures whatever lands on the system clipboard. For your vim yanks and cuts to be captured, VSCodeVim must route the unnamed register through the system clipboard:
// settings.json
"vim.useSystemClipboard": true
Setup with VSCodeVim
An extension cannot inject bindings into vim.normalModeKeyBindings, so add the
recommended wiring to your own settings.json. Paste (p/P) stays native
so vim keeps its linewise/charwise behavior; you only bind the cycle chords:
// settings.json
"vim.normalModeKeyBindings": [
{ "before": ["[", "p"], "commands": ["killring.pastePop"] },
{ "before": ["]", "p"], "commands": ["killring.pastePopNext"] }
]
[p / ]p only do anything while the cursor is still inside the text you just
pasted; anywhere else they are no-ops (they will not shadow other bindings).
Rebinding
The commands are plain VSCode commands, so bind them however you like:
| Command | Purpose |
|---|---|
killring.pastePop |
Cycle to older entry (yank-pop) |
killring.pastePopNext |
Cycle to newer entry |
killring.showRing |
Open the ring picker |
killring.clear |
Empty the ring |
How capture works
VSCode has no "clipboard changed" event, so the ring is filled two ways:
- Polling the clipboard on a timer (
killring.pollInterval, default250ms) — this catches copies you stage but never paste, and copies made in other apps. - Lazy ingest at paste time — guarantees the value you are about to paste is in the ring.
Together these mean anything you copy is remembered, whether or not you ever paste it. (The only theoretical gap is two distinct copies made within a single poll interval that are both never pasted.)
Settings
| Setting | Default | Description |
|---|---|---|
killring.maxSize |
60 |
Maximum entries kept in the ring; oldest are evicted first. |
killring.pollInterval |
250 |
Clipboard poll interval in ms. 0 disables polling. |
Behavior notes
- Pointer semantics match emacs: a fresh copy resets to the newest entry; a
plain
ppastes from wherever the pointer is; popping moves the pointer and wraps at the ends. So after popping to an older entry (without copying anything new), the nextprepeats that older entry. - Consecutive duplicates are collapsed — copying the same text twice in a row does not create two entries.
- Linewise vs charwise: paste is native vim, so linewise/charwise behavior
is exactly vim's. When you cycle with
[p/]p, the replacement mirrors the newline shape of the paste it replaces, so a linewise paste stays linewise as you cycle.
How paste-pop works
Paste (p/P) is left to native VSCodeVim — the system clipboard loses vim's
linewise/charwise register mode, so only vim can paste it correctly. The
extension observes the last single-insertion edit; when you press [p/]p
while the cursor is still inside that inserted text, it confirms the text was a
paste of the current ring entry and swaps it for the previous/next entry.
Known limitations (v1)
- Paste-pop only follows a plain
p/P. Because paste is native,3pand.-repeat work normally — but a multi-insertion paste (a blockwiseCtrl-vpaste, or a counted3p) produces several edits at once, which the observer skips; those can be pasted but not cycled. - Paste-pop starts only while the cursor is still inside the just-pasted
text; move away and
[p/]pbecome no-ops. - Visual-mode and insert-mode pastes are left to native vim/VSCode; the
ring still captures their clipboard effects, but
[p/]ponly correct a normal-mode paste. - The ring is in-memory only — it is not persisted across restarts and is not shared live between windows.
License
MIT