Why does Vim always manage to clip off at least a couple of characters when copying and pasting? - vim

Vim always manages to clip off at least of couple of characters when I copy something from a text file, such as a public rsa key for example.
Generally, I open a text file in my computer, highlight the text, copy it to my clipboard. I go into my terminal (with Vim already open) and then:
i (for insert)
ctrl+shift+v
Am I doing something wrong?
I've double checked, and triple checked, this, and I am absolutely sure that I highlighted all of the text that I needed to copy. Other times it works fine. There does not seem to be any consistency in regards to when it happens.
Anyone experience this?

This usually happens because something in the pasted text triggers a key mapping unexpectedly. This is what paste mode is for.
Do this before pasting:
:set paste
And turn it off after:
:set nopaste
This can be annoying to type frequently, so there is a way to map it to a key combination. I use ,p for this, and have this in my .vimrc:
set pastetoggle=,p
(Yes, I use an actual comma here, not <Leader>. That's because <Leader> won't work here, as this isn't technically a mapping.)
This is a toggle, so you can use it to turn the mode on and off. It works in both normal mode and insert mode.
You do want to turn it off after the paste. Since paste mode disables your insert mappings, you don't want to leave it on all the time.
You can read more about the paste option with :help 'paste.

The annoyance of toggling to and form paste mode can be avoided by using "+p or "*p. (You're putting the quoteplus register).
More often than not, I prefer "+P, since this leaves my cursor at the end of properly formatted put. see :help quoteplus for details. So the whole workflow is:
outside of vim: copy to clipboard
inside of vim: "+P

Related

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.

Pasting text in vim. A tedious operation?

I've been using vim for somewhat longer than a year now and during this time I have never feel really comfortable with the way vim works with yanking and pasting text (or maybe it is just me not using it in the most efficient way)
For example, I have the word "World" yanked onto a register, and I want to paste it after "Hello". (Note that there are no spaces on either of the words). So, what I would do is
Hello
|
Place cursor here, and press "p". Then, what I will end up with is
HelloWorld
So, in order to avoid this, I have always to swith into insert mode, insert a espace, and go back into normal mode (or either make sure that the yanked word has a space before it). Be as it may, this is quite annoying behaviour I can't think of a solution for... Am I missing something here?
Suggestions will be appreciated.
Thanks
option zero
just live with what you have now.
option one
create a mapping for your workflow. for example
nnoremap <leader>p i<space><esc>p
option two
:set ve=all
then you could move your cursor to anywhere and paste
option three
you could in insert mode use <c-o> do normal mode stuff or <c-r> to get register values
I recommend option zero
You can use the Smartput : Adjust spaces and commas when putting text plugin for that. It modifies the p / P commands (this can be toggled on / off).

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.

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.

Copy and paste from external source

I use vim (Actually gvim on windows) as my main text editor. In my work flow I have to copy sentences to/from various external sources, therefore I use clipboard=unnamed to save me key strokes (p instead of "*p).
I copy text from an outer source and I want to paste it over two different places in vim. I mark the first one (v) and then use p to paste over it. The problem is that at this point I lose the original buffer and can't paste it in the second place. It does not exist in the unnamed buffer, the * buffer or the numbered buffers. My guess is that pasting over selection is putting the "pasted over" text in the unnamed buffer.
How can I paste my original string in two locations? i.e. prevent it from getting lost from the buffers.
Thanks.
Try this:
:vmap p "_xP
vmap means to make a mapping that only applies in visual mode.
p is the key to create the mapping for.
"_ is the black hole register. This is used in any situation where you want to delete text without affecting any registers.
xP means delete the selected text, then paste before the resulting cursor position.
You could set up a mapping to ease your pain:
:vmap <F5> "zxP
This will delete the visually selected text, but put it in a different register, so the clipboard isn't affected. Change <F5> to whatever is easiest for you.
I don't know if I misunderstand you but I tried what you are doing and I have no problem in doing that with the + drop-register.
My workflow:
copy a sentence in an external application (ie. browser)
visual select a sentence in vim and replaced it with "+p or p (with clipboard=unnamed set)
visually select another sentence and replace it with "+p
Sadly when pasting the second time you have to explicitly paste from the + register. Therefore I would recommend a mapping for p/P instead of using clipboard=unnamed
nmap p "+p
Try using
:registers
to see the contents of the different registers.
I don't know how to do that on Windows. With KDE, the clipboard has a history that you can select from, so you could do the paste, select the previous selection from the clipboard, and paste in the new location.
That said, it sounds like it might make more sense for you to have it in only one location, then write a script to take that input and create the output you need. Can you elaborate more on what it is you are trying to accomplish?
Check the value of the 'guioptions' options. Make sure the 'a' flag is not set. Also, check that the 'clipboard' option and verify that neither the 'unnamed' or 'autoselect' flags are set.
:set go-=a
:set clipboard-=unnamed

Resources