将文本粘贴到Vim中时关闭自动缩进


1186

我正在努力学习Vim。

当我从剪贴板将代码粘贴到文档中时,在每一行的开头都有多余的空格:

line
  line
    line

我知道您可以关闭自动缩进,但由于其他设置有冲突或其他原因(在我的.vimrc中看起来很明显,但是取出它们似乎并不重要),我无法使它起作用。

如何在粘贴代码时关闭自动缩进功能,但是在编写代码时仍然具有vim自动缩进功能?这是我的.vimrc文件:

set expandtab  
set tabstop=2  
set shiftwidth=2  
set autoindent  
set smartindent  
set bg=dark  
set nowrap  

4
FWIW,vim 8.0.210为括号内的粘贴添加了本机支持,因此它将避免缩进粘贴的文本。
sh1

对于新文件,为了避免摆弄vim的粘贴/粘贴操作,可以cat > mynewfile.txtEnter键,粘贴文本,再次按Enter键,然后按Ctr + D进行保存。现在已创建文件,您可以使用编辑它vim mynewfile.txt
ccpizza

Answers:


2064

更新:更好的答案在这里:https : //stackoverflow.com/a/38258720/62202

要在粘贴代码时关闭自动缩进,有一种特殊的“粘贴”模式。

类型

:set paste

然后粘贴您的代码。请注意,工具提示中的文本现在显示为-- INSERT (paste) --

粘贴代码后,请关闭粘贴模式,以使键入时的自动缩进可以再次正常使用。

:set nopaste

但是,我总是觉得很麻烦。这就是为什么我要进行映射<F3>,以便在编辑文本时可以在粘贴和nopaste模式之间切换 我添加到.vimrc

set pastetoggle=<F3>

38
这并不比:set noai跟随容易:set ai。的建议:r! cat较短。
Leopd 2010年

68
我认为set paste绝对容易。它比noai甚至甚至更具语义noautoindent,当您精通触摸打字员时,键入“ noai”和“ paste”所花费的时间几乎相同,而这甚至更为重要。
Victor Zamanian

52
:set noai并非始终有效,这取决于如何根据OP配置其他与缩进相关的设置。 :set paste似乎是一次同时进行多项设置的简写。
MarkHu 2013年

13
晚了聚会,但set copyindent会无缝地为您处理。
Matt Ryan

33
:set paste还会禁用其他功能,例如大括号补全,粘贴代码时也不需要。
Manuel Faux 2014年

263

为避免粘贴时出现不良效果,需要设置一个选项:

set paste

.vimrc中的一个有用命令是set pastetoggle=<F10>或其他按钮,用于轻松在粘贴和nopaste之间切换。


13
最后!我一直在输入:set paste /:set nopaste,多么愚蠢!谢谢。
imwilsonxu

4
从实际的角度来看,您的答案比公认的答案更有用
Lynob 2015年

8
另一个选择是在您的vimrc中添加一个宏:nmap <silent> <leader>p :set paste<CR>"*p:set nopaste<CR>
克里斯(Chris)

不错的建议@Chris-粘贴单键序列而不会出现缩进问题!
RichVel

如果我永远不想进入粘贴模式怎么办?有没有办法永久禁用?
maxwell

132

我通常先使用内容,:r! cat然后再粘贴。( shift + insert )CTRL+D

无需启用和禁用,直接使用。


我喜欢这个直接使用的选项。不过,我仍在学习如何阅读网页上的vim语法。您的步骤是什么意思?特别是,假设我在系统剪贴板上有东西,我该按什么将其粘贴到vim文档中?
jvriesem 2015年

8
该回答将提供有关为什么以及如何:r! cat工作的信息的帮助 。
卡兰德森

11
@KErlandsson, :r将文件的内容插入当前文档。!cat说,运行cat本质上会打开stdin(* nix外壳),(shift + insert)或者对于某些终端,右键单击将剪贴板的内容粘贴到终端 CTRL+D文件的末尾,因此关闭:r !cat会话。
丹尼尔(Daniel)

这真的是“直接”吗?是否设置paste仅为此目的而选择的选项?@jvriesem如果我认为您对这个词的理解是正确的,则这不是“直接”选项。
0xc0de

您还可以使用:r! catthen CTRL+SHIFT+V粘贴到终端(然后为CTRL+D)。
Paul Rougieux

86

如果您在本地工作,则可以使用以下键序列从系统剪贴板粘贴:

"+p

这是一个正确的vim命令,因此无需担心进入插入模式或先关闭自动缩进功能。

当然,如果您正在远程工作(例如,通过SSH进行控制台),则此方法将不起作用,您应该进入:set noai,插入模式,粘贴到控制台,离开insertmode :set ai以及其他地方介绍的路由。


10
我很久以前就写了这个答案。如今,我使用:set paste:set nopaste而不是因为它虽然更长,但更容易记住,而不必每次都查找它!
thomasrutter

6
在某些嵌入式系统(主要基于busybox):set paste中未实现,因此:set noai应改为使用。
jcarballo

当您要复制大文本时,使用+寄存器不是更快吗?
pedromanoel 2014年

1
@pedromanoel仅在本地工作时有效。例如,如果您在本地复制了某些内容并将其粘贴到SSH会话中的vim中,则无法通过SSH访问vim。
thomasrutter 2014年

1
@thomasrutter但我将此映射到<leader>p..非常有用!
戴恩

51

虽然使用设置粘贴模式paste/nopaste/pastetoggle非常好,但是您仍然必须在粘贴之前手动启用粘贴模式,并在粘贴之后禁用粘贴模式。作为我的懒人,以下是到目前为止我发现的最佳解决方案,它可以在粘贴时自动切换粘贴模式。

这是一个小技巧,可在粘贴时使用终端的方括号粘贴模式自动设置/取消Vim的粘贴模式。在您的.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

现在,您可以粘贴而无需显式打开/关闭粘贴模式-它会自动为您处理。

资源: Coderwall

注意:此解决方案在WSL(Linux的Windows 10子系统)中不起作用。如果有人对WSL有解决方案,请更新此答案或将其添加到注释中。

Tmux如果使用tmux,则需要对声明进行两次转义。此代码也在Coderwall中


这太夸张了。但是,一件事...每粘贴一次,在每个粘贴的开头我都会得到一个“ 0”(零)字符。有什么建议吗?
朱利叶斯(JuliusŠ)。

请注意,如果使用tmux,则需要加倍转义。代码这是Coderwall链接在回答
Daithí

1
如果您比较懒惰,并将上面的代码粘贴到您的.vimrc中,请注意函数XTermPasteBegin()的缩进。
k1133

我很好奇它是如何工作的,因此我搜索了粘贴括号,并找到了gitlab.com/gnachman/iterm2/-//wikis/Paste-Bracketing,它解释了t_SIt_EI变量启用了粘贴括号并将其禁用。启用粘贴包围式曝光时,粘贴的文本以esc[200~开头,后跟esc[201~

37

Mac用户可以通过直接从粘贴板读取以下内容来避免自动格式化:

:r !pbpaste

3
这是一个很棒的回应。但是,当我执行此操作时,它会隐藏文档(看起来就像我回到了命令行一样),但是剪贴板上有文本。它提示我按Enter键,然后按Enter,然后我回到我的文档中而没有任何更改。发生了什么事,我该怎么办?
jvriesem 2015年

如果您只键入:.!pbpaste,这应该可以通过将当前行替换为粘贴缓冲区的输出来工作。通常,vim允许您将当前文件中的数据通过管道传输到另一个程序,并将文本替换为命令的输出。因此,:1,3!pbpaste用粘贴缓冲区替换文件的前三行。我:.!ppjson通常会花很长的时间(未格式化的JSON字符串)并对其进行格式化,然后将长字符串替换为格式化后的等效字符串。ppjson只是一个运行的bash脚本python -m json.tool
PatS


16

将其添加到您的文件中~/.vimrc,您只需在粘贴前后按F2键:

set pastetoggle=<F2>

12

我只是放入set clipboard=unnamed我的.vimrc。这使得默认的粘贴缓冲区映射到X的剪贴板。

因此,如果我在终端中标记了一些文本,则只需按一下p即可将其粘贴到vim中。同样,我可以在vim中拉动东西(例如YY,将当前行拉动到缓冲区中),然后在任何窗口中单击鼠标中键将其粘贴。

不知道。我觉得这很方便。


恕我直言,这是最好的答案,无需切换F11(vim中默认情况下已预先配置)。这在macs OSX系统中有效,我对其他人一无所知。
LightMan '18

9

在终端机内工作时 vim括号粘贴的 vim插件将自动处理粘贴,而无需在粘贴之前或之后进行任何击键。

它通过检测带括号的粘贴模式来工作,该模式是“现代” x术语兼容终端(如iTerm2,gnome-terminal和其他使用libvte的终端)发送的转义序列。作为额外的好处,它也适用于tmux会话。我在连接到Linux服务器并使用tmux的Mac上与iTerm2一起成功使用了它。


注意它还要进一步说明:不幸的是,这意味着如果您粘贴到终端中的任何内容中有换行符,它们也将运行输入缓冲区的内容。
0xc0de

1
@ 0xc0de,此处的引用与此无关。这是在谈论什么当它会做支持括号粘贴模式。这就是括号内粘贴模式的关键-阻止这种情况的发生。
sh1

对我来说,这比其他解决方案要好得多。谢谢。
jjj

8

将此贴在您的〜/ .vimrc中并感到高兴:

" enables :Paste to just do what you want
command Paste execute 'set noai | insert | set ai'

编辑:基于反射,:r !cat是一种更好的方法,因为它简短,语义清晰,并且不需要自定义vimrc。改用它!


5

虽然:pastetoggle还是:paste:nopaste应工作正常(如果实现的话-他们并不总是如我们可以从讨论中看到)我非常重评粘贴使用直接的方法"+p"*p与阅读"+r"*r

Vim有接取到十类型的寄存器(:help registers)和提问的爱好quotestarquoteplus从节

  1. 选择和删除寄存器"*"+以及“〜

使用这些寄存器为GUI存储和检索所选文本。请参阅quotestarquoteplus。当剪贴板不可用或无法使用时,将使用未命名的寄存器。对于Unix系统,仅当存在+ xterm_clipboard功能时,剪贴板才可用。{Vi无此功能}

注意,对于X11系统,“ *”和“ +”之间只有一个区别。

:help x11-selection进一步明确的差异*+

                                                  quoteplus quote+

记录在案的X选择有3种:PRIMARY(预期代表当前的视觉选择-在Vim的Visual模式下),SECONDARY(定义不明确)和CLIPBOARD(预期用于剪切,复制和粘贴操作) )。

在这三个中,Vim在读写“ *”寄存器时使用PRIMARY(因此,当X11选项可用时,Vim将'clipboard'的默认值设置为“ autoselect”),在读写“ +寄存器时使用CLIPBOARD。Vim无法访问SECONDARY选项。

示例:(假定默认选项值)

  • 在Vim中以可视模式选择一个URL。转到浏览器,然后在URL文本字段中单击鼠标中键。选定的文本将被插入(希望如此!)。注意:在Firefox中,您可以在about:config中将middlemouse.contentLoadURL首选项设置为true,然后在窗口的大多数位置按鼠标中键时,将使用选定的URL。

  • 通过使用鼠标拖动在浏览器中选择一些文本。转到Vim并按鼠标中键:插入选定的文本。

  • 在Vim中选择一些文本,然后执行“ + y”。转到浏览器,用鼠标拖动在文本字段中选择一些文本。现在使用鼠标右键,然后从弹出菜单中选择“粘贴”。所选文本被覆盖。注意,在进行可视选择时,“ +”寄存器中的文本仍然可用,这使得其他文本在“ *”寄存器中可用。这将覆盖选定的文本。

我注意到在Vim中使用中键单击似乎不会弄乱缩进,所以这可能是个主意
Fuseteam


2

如果您使用的是Mac,macvim似乎可以很好地处理它,而无需切换粘贴。

brew install macvim --override-system-vim


如果在.vimrc文件中包含OP指令,是否会这样?
Drew Noakes

2

vim 82016年发布以来,原生粘贴/方括号粘贴是最好和最简单的方法。它甚至可以在ssh上运行!(括号内的粘贴适用于Linux和Mac,但不适用于Windows Git Bash)

  1. 确保您拥有vim 8+(不需要+clipboard+xterm_clipboard选项)。

    vim --version | head -1

  2. 只需在正常模式下使用OS本机粘贴命令(例如ctrl+shift+Vcmd+V)。不要按i进入插入模式。


测试

  1. 将其输出(带有缩进的2行)复制(ctrl+shift+Ccmd+C)到系统剪贴板:

    echo -e '\ta\n\tb'

  2. 使用autoindent启动一个干净的vim 8+:

    vim -u NONE --noplugin -c 'set autoindent'

  3. 在普通模式下从系统剪贴板(ctrl+shift+Vcmd+V)粘贴。不要按i进入插入模式。该ab应使用单标签缩进对齐。您甚至可以在ssh-shing到远程计算机时执行此操作(远程计算机将需要vim 8+)。

  4. 现在尝试旧方法,该方法将使用额外的选项卡自动缩进第二行:按i进入插入模式。然后使用ctrl+shift+V或粘贴cmd+V。在ab现在对齐。


安装Vim 8

  • Ubuntu 18.04- 默认带有Vim 8

  • Ubuntu 16.04- 从PPA安装

    sudo add-apt-repository ppa:jonathonf/vim
    sudo apt update
    sudo apt install vim
    
  • 苹果电脑: brew install vim

1
最好和最简单的方法!此外,Google在Featured snippet搜索中建议使用“粘贴内容,没有制表符vim”,这可能是因为,我使用了“制表符”关键字,仅在此答案中提到了:)
David


1

我知道快速进入一次性粘贴模式的最快方式是tpope的功能不受影响,该功能具有“打开”的功能,yo并且yO可能带有助记符。它们仅在他的vimdoc中记录为:

没有为“粘贴”提供切换功能,因为包装单独插入的典型用例非常浪费:您切换了两次,但只粘贴了一次(YOPO)。而是按yo或yO调用已经设置了“粘贴”的o或O。离开插入模式会自动设置“ nopaste”。


1

粘贴的另一种方法是通过<CR>拖放寄存器(这里是全局寄存器)的内容。请参阅::h i_ctrl-rh i_CTRL-R_CTRL-O

从vim帮助文档中:
Insert the contents of a register literally and don't auto-indent. Does the same as pasting with the mouse<MiddleMouse>. Does not replace characters! The '.' register (last inserted text) is still inserted as typed.{not in Vi}

因此,要在没有自动缩进的情况下将内容粘贴到vim中,请<CR><CO>*在大多数unix系统中使用。

注意:仅在使用vim编译时有效 clipboard



1

直到现在我还没有看到的另一个答案:

:se paste noai

0

可悲的是,我发现提到的vim插件不能与iTerm2 3.0.15配合使用(公平地讲,我不知道这在旧版本上是否无效)-但是我发现了这种黑客。

映射command -p进行粘贴,并使用iTerm2 vim键。显然,这仅适用于iTerm2。

怎么运行的。我使用“ jk”进入退出模式,因此您还需要:

:inoremap jk

在您的.vimrc中。

然后,它仅调用P进入粘贴模式,“ + p从剪贴板粘贴”,然后调用P禁用粘贴模式。

在此处输入图片说明


1
等等,您为此使用'jk'吗?
0xc0de

哦,是的,我忘了提。只需在您的.vimrc中添加“:inoremap jk <esc>”。关于我为什么使用jk,请询问Apple,以及为什么他们感到需要移动并摆脱物理转义键。8(
尼尔·麦吉尔,

顺便说一句,它需要一些培训,但是过了一会儿,jk感觉更快,我想我现在比逃脱更喜欢它。无论如何,如果iTerm2在这里也接受<ESC>还是很有趣的。
尼尔·麦吉尔

苹果要走的路!
0xc0de
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.