How to use bracketed-paste-mode in Vim/Neovim when pasting a register in insert mode? - vim

When inserting code from a register in insert mode with Vim/Neovim it will not automatically use xterm-bracketed-paste(Vim) / bracketed-paste-mode(Neovim).
For example if I have yanked this function in a demo.js file:
function x() {
// comment
alert("hey");
}
and then paste it in insert mode with i<c-r>" it will be messed up:
function x() {
// comment
// alert("hey");
// }
//
Whereas pasting the same snippet from the system clipboard (i.e. with Ctrl+Shift+v) in insert mode works fine due to the bracketed paste feature.
I know that I can use :set paste before pasting. But then I either have to leave insert mode or - when mapped to a key - press a key to enable paste mode.
Is there a way to automate this?

:h <c-r> does state the following:
The text is inserted as if you typed it, but mappings and abbreviations
are not used.
So, it does not trigger any paste commands or callbacks or anything. It is just an automated way to type in text.
The answer to problems like this is always the same: Leave insert mode.
Vim is mode based, that is the fundament of the power of vim. Insert mode is not specialized to paste stuff (although I love <c-r>). There is a lot of stuff you can't to in insert mode.

I've tried the following mapping to paste the system clipboard in insert mode. So far it seems to do what I want.
inoremap <c-p> <c-o>:set paste<cr><c-r>+<c-o>:set nopaste<cr>

Related

YankRing in insert mode

I'm using vim with YankRing.
Is it possible to paste an element from the YankRing while being in insert mode?
(Like it is possible to paste an element from the usual registers with Ctrl-R + the name of the register.)
Thanks
(NB: I'm not familiar with that particular plugin, so my examples might seem silly.)
When in Insert mode, you can always use CTRL-O (see i_CTRL-O) to execute one Normal mode command and immediately get back into Insert mode. So it appears you can just press CTRL-O followed by CTRL-P to use YankRing. Same goes for command-line mode: CTRL-O followed by :YRShow, for example.

Undo a paste without undoing previous typing

In vim I frequently end up undoing more than I want to after a messed up paste from the system clipboard. Is there a better way?
To reproduce:
Open iTerm # or terminal
vi # open vim
i # enter insert mode
type some stuff
Cmd-V # paste the contents of the OS X clipboard
The paste is a mess because I haven't :set paste. So
Esc # enter command mode
u # undo
but that undoes my typing as well as my paste.
Is there a different undo I can use? Apart from remembering to :set paste before pasting is there a better way to do this in general?
This is not the answer you're looking for, but you really should stop using vim as a non-modal editor. If you want to paste then return to normal mode and use vim's paste commands.
Assuming that you have a vim version with clipboard access this should do the trick "+p. You can also facilitate this by setting your unnamed register to be the + (or *) register, such that pasting from clipboard becomes a simple p.
The following question has a great answer that includes all this information How to make vim paste from (and copy to) system's clipboard?.
I'm not sure there's anything you can do after the fact, but one solution is to hit Ctrl-G u in insert mode just before you paste. This breaks the undo block into two separate blocks - so the paste will be remembered as a separate undoable action.
Granted if you have to remember to do this, you might as well just use :set paste instead - but on the upside it's fewer keystrokes and you don't have to go to command mode first.
Take a look at this plugin, it can auto run :set paste! when you use Cmd-V(or Ctrl-V) to paste some text. And leave paste mode when you finished.
The following mappings create an additional undo point (via :help i_CTRL-G_u) before pasting in insert mode. This way, you can undo the paste separately.
inoremap <C-r> <C-g>u<C-r>
inoremap <C-v> <C-g>u<C-v>
Actually the solution is you have to go to command mode(e.g. Esc) first and re-enter the insert mode, but it only works if I type manually but it seems "randomly" stop working if I test it in ~/.vimrc. Google doesn't help at all.
I spends a lot of time try to fix this issue and I just figure out the reason in my case:
Don't map the paste key same with the terminal existing paste key
e.g. Ctrl+Shift+V will paste in my Konsole terminal, but if I assign this key <C-S-v> in ~/.vimrc, the "undo for only single paste instead of multiple pastes" will not working.
In my case, I have to use <C-v> instead of <C-S-v>:
inoremap <C-v> <Esc>"+pi<Esc>i<Right><Right>
Your case may difference, but the point is same: don't assign the same paste key conflicts with existing terminal emulator key.
I've 100% proved this conclusion by set my terminal paste key to Ctrl+V and now <C-v> stop working but <C-S-v> working.
Note also that the vim is too sensitive and strange. I figure out I have to use i and then 2 Right keys manually to make it works in the correct cursor position, that's means I have to put i and 2 Right keys in the ~/.vimrc too. Your case might difference, but the point is same, ensure the keys+order in ~/.vimrc 100% match with what you type manually.

Quickest way to paste block of text into the vi editor from an external source

For instance, copying a configuration section from a web page and then pasting it into a .conf file that you have open in vi.
Enter insert mode (Type i)
Type: Ctrl + Shift + v
Or if you use the system register, you can paste without being in insert mode:
"*p
This will paste the system's clipboard at the point of the cursor. No insert mode needed.
The real answer:
:set paste
Enter Insert Mode: hit i
Paste: Command + v or Control + v
ESC
:set nopaste
One thing to bear in mind: Sometimes Vim auto-indents text. This is mostly fine, but sometimes it messes up text that you paste into a document.
If your indentations are awry, remove the pasted text, type :set paste, paste the text in again, and when you're done, type :set nopaste.
The easiest way is just to copy the text and just right click where you want to paste it in Vim in INSERT mode.
If you are using gVim, hit Ctrl + R and then either * or + in insert mode. It will paste the last copied text.
Ctrl-V/ Apple-V? Just make sure you're in insert mode in vi (i)
Use your systems paste shortcut key while in Insert mode, or if your source is in another file, you can type :r <fileName>, and it will be pasted at the current location of your cursor.
The easiest way on *nix is by selecting it with the mouse and pasting it in Vim with a middle click, after having put vi in insert mode.
The middle click could be a both left-right key if you're using a touchpad.
The quickest way is to paste it using whatever paste key your system uses (e.g. ⌘-v for Macs, Ctrl-V for Windows, etc.) in insert mode.
Some terminals require you to use Shift-Ctrl-V. However you are able to paste onto the command-line is how you should paste into Vim. However, this can cause some problems with indentation, which is where :set paste comes in. The fastest way to get in and out of this is to set a pastetoggle (see :help pastetoggle). For example, I use
set pastetoggle=<leader>p
The reason to use a pastetoggle instead of a mapping is because if you set a mapping insert mode, it will read it literally when in paste mode. Thus if you :set paste, go into insert mode, and type in any imap the mapping will not be completed, but instead the literal characters will be inserted. With pastetoggle you can get around that since it's a built-in feature.
As others have said, if you're in insert mode, you can also use <C-r>*, but why? Your normal pasting flow is most likely better. Understanding the * register and <C-r> is an important skill however. You can read more about them at :help registers and :help i_CTRL-R. You could also use "*p, but if you're faster at typing that than your normal paste I'm impressed.
Of course you could map that to something else, but again... why? You should get used to quickly getting into insert mode with i, I, a, A, o, O, s, S, c, and C so that you can be precise.

How do you paste with vim without code being commented?

Everytime I paste in vim, every line is commented out.
Is there a way around this?
Before you paste, type this in normal mode:
:set paste
Then enter insert mode. You will see the status bar say insert (paste). Paste your code. Hit ESC to return to normal mode, and:
:set nopaste
You are no longer in paste mode.
Or, to avoid having to turn paste on and off, just put the text. Rather than going into insert mode and pasting, in command mode type:
"+p
The + buffer corresponds to the system clipboard.
If you insist on using paste, I'd suggest mapping something to toggle it. For example, :set pastetoggle=<F2> (wow, didn't realize there was a special option for that)

Pasting from the clipboard and automatically toggling ":set paste"

When I paste things from the clipboard, they're normally (always) multilined, and in those cases (and those cases only), I'd like :set paste to be triggered, since otherwise the tabbing will increase with each line (you've all seen it!).
Though the problem with :set paste is that it doesn't behave well with set smartindent, causing the cursor to jump to the beginning of a new line instead of at the correct indent. So I'd like to enable it for this instance only.
I'm using Mac, sshing to a Debian machine with Vim, and thus pasting in Insert mode using cmd + v.
I don't use a mac, but I believe I have the prefix right here: <D-v> should mean cmd-v. For insert mode:
:imap <D-v> ^O:set paste<Enter>^R+^O:set nopaste<Enter>
or really, just do this:
:imap <D-V> ^O"+p
The ^O and ^R are literal control-O and control-R, which you can type with ^V^O (control-v control-o) and ^V^R (control-v control-r). Control-O in insert mode allows you to execute one command then return to insert mode; here you can use it to put from the clipboard register.
This worked for me when I tested them mapped to a different key, so you should be all set.
There's no need to map anything when not in insert mode; you can just use "+p.
I have the following in my .vimrc:
inoremap <S-Insert> <ESC>:setl paste<CR>gi<C-R>+<ESC>:setl nopaste<CR>gi
gi is to start insert mode in the same position as where insert mode was stopped last time in the current buffer.
Update:
Jefromi posted a better solution. I have tinkered it a bit
inoremap <S-Insert> <ESC>"+p`]a
It inserts clipboard text and places the cursor right after it.
You're right in that you should only enable 'paste' when you need it. It does more than just affect indenting. You can read everything that it affects in its documentation. A related option that is very useful to ease the use of 'paste' is 'pastetoggle'.
If you were using X-forwarding and a terminal that can properly communicate mouse actions, you could also take advantage of the 'mouse' option. With :set mouse=a, Vim is made aware of what the mouse is doing and therefore won't perform automatic indentation when it receives a multi-line paste via a middle-button mouse click.
Even without the mouse capability, X-forwarding could help because Vim will do the same thing when manually pasting from the clipboard or selection registers ("+ and "* respectively).
This ought to be solvable with a Vim script. (I hate Vim scripting, so it would have to be a much more serious infliction to cause me to solve it myself.) Even with iTerm2's "paste slowly" mode, the default is to break the data to be pasted into 16 byte chunks and send one every 0.125 seconds. Therefore, you should be able to programmatically detect a 16 byte chunk of "keystrokes" and do something about it.
In pseudocode that would look like:
if too_fast_too_be_human():
set('pastemode', True)
else
set('pastemode', False)
# where either
def too_fast_too_be_human
char_threshold = 16
return len(input_buffer) > char_threshold
# or
def too_fast_too_be_human
static byte_times = []
char_threshold = 16
time_threshold = 0.125
byte_times.append(now())
while(len(byte_times) > char_threshold):
byte_times.unshift()
return (byte_times[-1] - byte_times[0]) < time_threshold
There are weaknesses to that, but it would work for most cases.
We can paste (insert mode) without messing up indentation using
Ctrl-r Ctrl-o Register
Ctrl-r Ctrl-o +
Ctrl-r Ctrl-o *
Ctrl-r Ctrl-o 0
CTRL-R CTRL-O {0-9a-z"%#*+/:.-=} *i_CTRL-R_CTRL-O*
Insert the contents of a register literally and don't
auto-indent. Does the same as pasting with the mouse
"MiddleMouse". When the register is linewise this will
insert the text above the current line, like with `P`.
Does not replace characters!
The '.' register (last inserted text) is still inserted as
typed.

Resources