Clean Paste in Neovim: Paste Text Without Newlines and Leading Whitespace
on Dragoș Străinu's blogWhen I work on a web project, I find myself copy-pasting HTML tags or Components from one place to another.
Here are some use cases:
<!-- 1: Copy html tag to another parent -->
<div id="1">
<div class="copy-paste">
<h2>Copy me to div#2</h2>
<div>Here is another child element</div>
</div>
</div>
<div id="2"></div>
<!-- 2: Copy component to another parent -->
<div id="1">
<Component
className="copy-paste"
title="Copy me to div#2"
description="Here is the description"
/>
</div>
<div id="2"></div>
<!-- 3: component as prop -->
<div id="1">
<Component
className="copy-paste"
title="Move me to Container header"
description="Here is the description"
/>
</div>
<Container header={} />
<!-- 4: Return component -->
<div id="1">
<Component
className="copy-paste"
title="Move me to Container header"
description="Here is the description"
/>
</div>
return ();
For the first use case, I can put the cursor inside
<div class="copy-paste">
and do yat
or vaty
(yank around tag) to copy the HTML tag, then move inside <div id="2"></div>
and paste.
But for the other use cases, this does not work because
<Component />
is self-closing and Neovim can't select with t
(tag).
So most often I just use SHIFT+V
to enter in visual mode on the whole line, move N lines below, select the HTML tag or Component, then use y
to copy the selection.
Now because of SHIFT+V
, the yanked text includes newlines and leading whitespace, and when I paste I get this result:
<!-- 1: Copy html tag to another parent -->
<div id="1">
<div class="copy-paste">
<h2>Copy me to div#2</h2>
<div>Here is another child element</div>
</div>
</div>
<div id="2"></div>
<div class="copy-paste">
<h2>Copy me to div#2</h2>
<div>Here is another child element</div>
</div>
So I created a keymap to paste the text without newlines and leading whitespace:
-- Map yp to paste yanked line without newlines and without leading whitespace
vim.keymap.set("n", "yp", function()
-- Get content from register 0 (most recent yank)
local yanked_text = vim.fn.getreg("0")
-- Remove trailing newline if present
yanked_text = yanked_text:gsub("\n$", "")
-- Remove leading whitespace
yanked_text = yanked_text:gsub("^%s+", "")
-- Store in register p
vim.fn.setreg("p", yanked_text)
-- Paste from register p
return '"pp'
end, { expr = true })
You can change the keymap to cp
(clean paste) or <leader>p
.
The result when using this keymap is:
<!-- 1: Copy html tag to another parent -->
<div id="1">
<div class="copy-paste">
<h2>Copy me to div#2</h2>
<div>Here is another child element</div>
</div>
</div>
<div id="2"><div class="copy-paste">
<h2>Copy me to div#2</h2>
<div>Here is another child element</div>
</div></div>
And next, I just let my formatter do the job:
<!-- 1: Copy html tag to another parent -->
<div id="1">
<div class="copy-paste">
<h2>Copy me to div#2</h2>
<div>Here is another child element</div>
</div>
</div>
<div id="2">
<div class="copy-paste">
<h2>Copy me to div#2</h2>
<div>Here is another child element</div>
</div>
</div>
This also works for other use cases:
<!-- 4: Return component -->
<div id="1">
<Component
className="copy-paste"
title="Move me to Container header"
description="Here is the description"
/>
</div>
return (<Component
className="copy-paste"
title="Move me to Container header"
description="Here is the description"
/>);