Why does Vim indent pasted code incorrectly?
Solution 1
There're two reasons:
For pasting in vim
while auto-indent is enabled, you must change to paste mode by typing:
:set paste
Then you can change to insert mode and paste your code. After pasting is done, type:
:set nopaste
to turn off paste mode. Since this is a common and frequent action, vim
offers toggling paste mode:
set pastetoggle=<F2>
You can change F2
to whatever key you want, and now you can turn pasting on and off easily.
To turn off auto-insert of comments, you can add these lines to your vimrc:
augroup auto_comment
au!
au FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o
augroup END
vim
also provides a pasting register for you to paste text from the system clipboard. You can use "*p
or "+p
depending on your system. On a system without X11, such as OSX or Windows, you have to use the *
register. On an X11 system, like Linux, you can use both.
Further reading
Solution 2
Use the vim paste. What you want is to paste what is on the clipboard buffer "+p
This selects the +
and pastes it in place.
If you're using Linux, *
is the X/middle-click buffer (the last selected text).
Then vim knows it's a paste.
Otherwise vim thinks you have typed the keys being pasted and does its own auto-indentation (on top of your copied indentation) all the way to the end of the paste.
As a note for this to work over SSH you need to set the option for your clipboard to be shared -Y
See man ssh
for more details.
Solution 3
The tabs were inserted because you have autoindent turned on and you can disable that behavior by turning off autoindent (:set noai
) before you paste into terminal.
The commented lines are produced by auto commenting and can be disabled by turning that off.
Alternative to those you should get the desired behavior using the toggles :set paste
, pasting your formatted code and :set nopaste
to restore normal behavior.
Solution 4
When you paste, you send a stream of characters. VIM has features that alter this stream to make life easier for humans. :set paste is a workaround disable all stream alterations, can be re-enabled with :set nopaste. This all goes back to the one true editor, ed(1) :)
Solution 5
The reason has been explained very well by the other posters. Here I would like to provide a solution which handles the situation automatically.
With the following in your ~\.vimrc
let &t_SI .= "\<Esc>[?2004h"
let &t_EI .= "\<Esc>[?2004l"
inoremap <special> <expr> <Esc>[200~ XTermPasteBegin()
function! XTermPasteBegin()
set pastetoggle=<Esc>[201~
set paste
return ""
endfunction
you can paste freely without worrying about the auto-indentions.
If you work in tmux, then you have to write instead the following
function! WrapForTmux(s)
if !exists('$TMUX')
return a:s
endif
let tmux_start = "\<Esc>Ptmux;"
let tmux_end = "\<Esc>\\"
return tmux_start . substitute(a:s, "\<Esc>", "\<Esc>\<Esc>", 'g') . tmux_end
endfunction
let &t_SI .= WrapForTmux("\<Esc>[?2004h")
let &t_EI .= WrapForTmux("\<Esc>[?2004l")
function! XTermPasteBegin()
set pastetoggle=<Esc>[201~
set paste
return ""
endfunction
inoremap <special> <expr> <Esc>[200~ XTermPasteBegin()
The source is Coderwall if you would like to read more.
If you work in screen
the equivalent wrap-function is:
function! WrapForScreen(s)
if exists('$TMUX') || match($TERM, "screen")==-1
return a:s
endif
let screen_start = "\<Esc>P"
let screen_end = "\<Esc>\\"
return screen_start . a:s . screen_end
endfunction
Found in stapelberg's .vimrc
.
Related videos on Youtube
elbarna
Updated on September 18, 2022Comments
-
elbarna over 1 year
In Vim, if I paste this script:
#!/bin/sh VAR=1 while ((VAR < 10)) do echo "VAR1 is now $VAR" ((VAR = VAR +2)) done echo "finish"
I get these strange results:
#!/bin/sh #VAR=1 #while ((VAR < 10)) # do # echo "VAR1 is now $VAR" # ((VAR = VAR +2)) # done # echo "finish" #
Hash signs (#) and tabs have appeared. Why?
-
Eric Renouf about 9 yearsThis might be a better question for vi.stackexchange.com
-
Eric Renouf about 9 years@qix my thought was this is a question about how vim works, which is a common tool to be used on *nix, but *nix isn't a requirement for using vim
-
Eric Renouf about 9 years@JaredBurrows I sure hope it makes it
-
DaleHarris541 about 9 yearsHow are you triggering the paste? With the mouse?
-
elbarna about 9 yearsNo,ctrl+v keyboard on xfce console
-
-
Caja about 9 yearsI have been using Vim forever and never knew about this. Many thanks.
-
egmont about 9 yearsMost modern graphical terminal emulators support a feature called "bracketed paste mode". Vim can ask the terminal to enable this mode, which, in turn, will surround pasted text with certain escape sequences. Vim can recognize this and turn off wrapping/indenting for the duration of the paste. Long story stort: pasting will "work as expected". I'm not a vim user, but a quick websearch will sure tell you how to configure this mode.
-
Michael Durrant about 9 yearsI added set paste to my .vimrc so it is always on which has seemed to work for some time now. Why would I ever need to turn it off / toggle it ?
-
David Lord about 9 yearsThat would be if you ever want to use auto indent/comment, which can be pretty useful when you're writing/editing code rather than copying it.
-
ODYodel about 9 years@MichaelDurrant
set paste
should never be in your vimrc. It disables or resets a lot of things, including insert mode mappings, command line mappings, abbreviations, textwidth, wrapmargin, autoindent, smartindent, softtabstop, formatoptions, indentexpr, and a couple of others.:h paste
has the whole list. Most people use some or all of these things and wonder why there settings are ignored. -
wurtel about 9 yearsIt looks like this only works for the graphical vim (
gvim
); vim running in a terminal emulator pastes the last deleted text with "*p, not the current selection. -
exussum about 9 yearsalso check
vim --version
se see if it was compiled with clipboard support+xterm_clipboard
should be in the output -
cuonglm about 9 years@wurtel: Maybe you have set clipboard with
unnamed
string. -
Kos about 9 years+1, my vimrc has
set clipboard=unnamedplus
so that yanking and pasting uses system clipboard (register+
) by default. Works for me (xubuntu) for both vim and gvim -
DaleHarris541 about 9 yearsIt may be worth discussing the interaction with
set mouse
, which can automatically enter and leave paste mode when pasting with mouse click. -
Random832 about 9 years
"+
works fine on both Windows and OSX, I use it every day. Generally the two are identical on systems that don't have X11. -
Janac Meena over 6 yearsThis doesn't work in gvim 80 on Windows 10
-
cuonglm over 6 years@JanacMeena gvim is different.
-
Itamar Katz almost 5 yearsAfter I
set paste
and do the paste, my tab width changes to 8 spaces, and I have tosource ~/.vimrc
to set it back to 4 spaces. Is there a way to avoid it? -
Quasímodo over 3 yearsWould you please extend your answer to include insert mode paste? I for one have always used
Ctrl-R +
, but that also screws indentation.Ctrl-R Ctrl-O +
is the correct way to go. -
exussum over 3 yearsPaste mode shouldnt be needed if pasting direct like this
-
Quasímodo over 3 yearsMy point is: There are ways to paste in insert mode with
Ctrl-R
. One of those preserves indentation. If you would not like to expand on that, I'll add a separate answer, but I think information is better if it is not shattered around. -
NeilG over 2 yearsI haven't tried it yet but this looks good - very short little plugin to automatically toggle paste mode when pasting in terminal: github.com/ConradIrwin/vim-bracketed-paste