ChatGPT解决这个技术问题 Extra ChatGPT

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

我正在努力学习 Vim。

当我从剪贴板将代码粘贴到我的文档中时,我会在每一行的开头得到额外的空格:

line
  line
    line

我知道你可以关闭自动缩进,但我无法让它工作,因为我有一些其他设置冲突或其他东西(这在我的 .vimrc 中看起来很明显,但当我将它们取出时似乎并不重要)。

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

set expandtab  
set tabstop=2  
set shiftwidth=2  
set autoindent  
set smartindent  
set bg=dark  
set nowrap  
FWIW,vim 8.0.210 添加了对括号粘贴的本机支持,因此它将避免缩进粘贴的文本。
对于新文件,为了避免摆弄 vim 的粘贴/不粘贴,您可以执行 cat > mynewfile.txtEnter,粘贴文本,再次按 Enter,然后 Ctr+D 到节省。该文件现已创建,您可以使用 vim mynewfile.txt 对其进行编辑。
cat 解决方案有一个缺点:变量被更改为该变量的值

L
Louis

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

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

类型

:set paste

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

粘贴代码后,关闭粘贴模式,以便在键入时自动缩进再次正常工作。

:set nopaste

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

set pastetoggle=<F3>

这并不比 :set noai 后跟 :set ai 更简单。 :r! cat 的建议较短。
我认为 set paste 肯定更容易。它比 noai 甚至 noautoindent 更具语义性,当您作为触摸打字员足够熟练时,键入“noai”和“paste”所花费的时间几乎相同,这更重要。
:set noai 并不总是有效,这取决于如何根据 OP 配置其他与缩进相关的设置。 :set paste 似乎同时是多个设置的简写。
派对迟到了,但 set copyindent 会为您无缝处理。
:set paste 还会禁用大括号补全等其他功能,这在粘贴代码时也是不需要的。
0
0xc0de

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

set paste

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


最后!我一直在输入 :set paste / :set nopaste ,多么愚蠢!谢谢。
从实际的角度来看,您的答案比公认的答案更有用
另一种选择是在 vimrc 中添加一个宏:nmap <silent> <leader>p :set paste<CR>"*p:set nopaste<CR>
很好的建议@Chris - 单键序列粘贴没有缩进问题!
如果我不想进入粘贴模式怎么办?有没有办法永久禁用?
t
thegeek

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

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


我喜欢这种直接使用选项。不过,我仍在学习如何在网页上阅读 vim 语法。你的步骤是什么意思?特别是,假设我在系统剪贴板上有一些东西,我应该按什么将它粘贴到 vim 中的文档中?
这个答案对于有关 :r! cat 工作原理和方式的信息会更有帮助。
@KErlandsson,:r 将文件的内容插入到当前文档中。 !cat 说,运行 cat 基本上会打开 stdin (*nix shells) (shift + insert) 或对于某些终端,鼠标右键单击会将剪贴板的内容粘贴到终端 CTRL+D 是文件结尾,所以它关闭:r !cat 会话。
这真的是“直接”吗?而不是设置一个仅用于此目的的选项 paste? @jvriesem 如果我假设您对该词的理解是正确的,这不是“直接”选项。
您也可以使用 :r! cat 然后 CTRL+SHIFT+V 粘贴到终端(然后 CTRL+D)。
t
thomasrutter

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

"+p

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

当然,如果您在远程工作(例如,通过 SSH 控制台),那么这将不起作用,您应该按照其他地方的说明转到 :set noai、插入模式、粘贴到控制台、离开插入模式、:set ai 路由。


我很久以前写过这个答案。现在我改用 :set paste:set nopaste,因为尽管它们更长,但更容易记住,而且我不必每次都查找它!
在一些嵌入式系统中(主要基于busybox):set paste没有实现,所以应该用:set noai代替。
当您要复制大文本时,使用 + 寄存器不是更快吗?
@pedromanoel 仅在本地工作时有效。例如,如果您在本地复制某些内容并想将其粘贴到您的 SSH 会话中的 vim 中,它将无法通过 SSH 访问 vim。
@thomasrutter 但我将其映射到 <leader>p .. 非常有用!
D
Daithí

虽然使用 paste/nopaste/pastetoggle 设置粘贴模式非常好,但您仍然必须在粘贴前手动启用粘贴模式并在粘贴后禁用粘贴模式。作为一个懒惰的人,下面是我迄今为止找到的最佳解决方案,它会在您粘贴时自动切换粘贴模式。

这是一个小技巧,它使用终端的括号粘贴模式在粘贴时自动设置/取消设置 Vim 的粘贴模式。在 .vimrc 中添加以下内容: let &t_SI .= "\[?2004h" let &t_EI .= "\[?2004l" inoremap [200~ XTermPasteBegin() 函数! XTermPasteBegin() set pastetoggle=[201~ set paste return "" endfunction 现在您可以在不显式打开/关闭粘贴模式的情况下粘贴 - 它会自动为您处理。

来源:Coderwall

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

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


这是辉煌的。不过有一件事......每次粘贴时,我都会在每次粘贴的开头得到一个“0”(零)字符。有什么建议吗?
还要注意如果使用 tmux 那么你需要双重转义。代码在 Coderwall 链接中
如果你更懒惰,将上面的代码复制粘贴到你的 .vimrc 中,请注意函数 XTermPasteBegin() 的缩进。
我很好奇它是如何工作的,所以我搜索了粘贴括号并找到 gitlab.com/gnachman/iterm2/-/wikis/Paste-Bracketing,它解释了 t_SIt_EI 变量正在启用粘贴括号并禁用它。当粘贴括号打开时,粘贴的文本以 esc[200~ 为前缀,然后是 esc[201~
不幸的是,这种映射延迟了从插入模式到正常模式的切换大约半秒。有没有办法减少这种延迟?
m
maniacalrobot

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

:r !pbpaste

这是一个很棒的回应。但是,当我这样做时,它会隐藏文档(看起来我回到了命令行),但我的剪贴板上有文本。它提示我按回车,所以我这样做了,它让我回到我的文档而不做任何更改。发生了什么事,我该怎么做?
如果您只键入 :.!pbpaste,这应该通过将当前行替换为粘贴缓冲区的输出来工作。通常,vim 允许您将当前文件中的数据通过管道传输到另一个程序,并用命令的输出替换文本。所以 :1,3!pbpaste 用粘贴缓冲区替换文件的前三行。我使用 :.!ppjson 获取一个非常长的(未格式化的 JSON 字符串)并对其进行格式化,并将长字符串替换为格式化的等效字符串。 ppjson 只是一个运行 python -m json.tool 的 bash 脚本。
在 Linux 上,xsel --clipboard 而不是 pbpaste 做同样的事情。
V
Von

Here is a post 由想出如何重新映射粘贴事件以自动打开粘贴模式然后再关闭的人提出。在 MacOSX 上的 tmux/iTerm 中为我工作。


谢谢你的提示。我还找到了一个插件,这个人捆绑了类似的功能 - stackoverflow.com/a/36512548/255961
当我从剪贴板插入一段文本时,这似乎会导致一串“eeeeeee”。
p
peterh

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

所以,如果我在终端中标记一些文本,我可以简单地按 p 将其粘贴到 vim 中。同样,我可以在 vim 中拉出东西(例如 YY 将当前行拉入缓冲区)并在任何窗口中单击鼠标中键以粘贴它。

我不知道。我觉得超级方便。


恕我直言,这是最好的答案,无需切换 F11(默认情况下在 vim 中预先配置)。这适用于macs OSX系统,我不知道其他人。
a
anh_ng8

将此添加到您的 ~/.vimrc 中,您只需在粘贴前后按 F2

set pastetoggle=<F2>

s
studgeek

在终端中工作时,vim-bracketed-paste vim 插件将自动处理粘贴,而无需在粘贴之前或之后进行任何击键。

它的工作原理是检测 bracketed paste mode,这是由“现代”x-term 兼容终端(如 iTerm2、gnome-terminal 和其他使用 libvte 的终端)发送的转义序列。作为额外的奖励,它也适用于 tmux 会话。我在连接到 linux 服务器并使用 tmux 的 Mac 上成功地将它与 iTerm2 一起使用。


请注意它还进一步指出的内容:不幸的是,这意味着如果您粘贴到终端的任何内容中有换行符,它们也会运行输入缓冲区的内容。
@0xc0de,该引用与此处无关。那是在谈论外壳不支持括号粘贴模式时会做什么。这就是括号粘贴模式的重点——阻止这种情况的发生。
这对我来说比其他解决方案好得多。谢谢。
D
Dergachev

把它放在你的 ~/.vimrc 中,然后开心:

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

编辑:经过反思,:r !cat 是一种更好的方法,因为它简短、语义化,并且不需要自定义 vimrc。改用那个!


s
sjas

直到现在我才看到的另一个答案:

:se paste noai

B
B.Mr.W.

我是一名 Python 用户,有时会复制并粘贴到 Vim 中。 (我从 Mac 切换到 Windows WSL)这是困扰我的故障之一。

如果您触摸 script.py,然后触摸 vi script.py,Vi 将检测到它是 Python 脚本并尝试提供帮助、自动缩进、粘贴额外缩进等。如果您不告诉它是Python 脚本。

但是,如果这已经发生在您身上,那么当您粘贴已经完全缩进的代码时,默认的自动缩进可能是一场噩梦(请参见下面的倾斜梯形)。

我尝试了三个选项,这是结果

set paste        # works perfect 
set noai         # still introduced extra whitespace
set noautoindent # still introduced extra whitespace

https://i.stack.imgur.com/4TdUY.png


同一条船——你最终是否设置了键盘快捷键或使用插件或其他可行的选择?或者只是和它一起生活:)
@aadibajpai 我把 set pastetoggle=<F2> 放在我的 .vimrc 中,所以按 F2 可以打开和关闭粘贴。
c
codingdave

虽然 :pastetoggle:paste:nopaste 应该可以正常工作(如果实施 - 它们并不总是如我们从讨论中看到的那样)我强烈建议使用直接方法 "+p"*p 粘贴并阅读"+r"*r

Vim 可以访问十种类型的寄存器 (:help registers),提问者对部分中的 quotestarquoteplus 感兴趣

选择和删除寄存器 "*、"+ 和 "~ 使用这些寄存器存储和检索 GUI 的选定文本。请参阅 quotestar 和 quoteplus。当剪贴板不可用或不工作时,使用未命名的寄存器。对于 Unix系统剪贴板仅在存在 +xterm_clipboard 功能时可用。{Vi 无此功能} 注意 X11 系统只有 "* 和 "+ 之间的区别。

:help x11-selection 进一步阐明了 *+ 的区别:

quoteplus quote+ 有 3 个记录在案的 X 选择:PRIMARY(预期表示当前的可视选择 - 如在 Vim 的可视模式中)、SECONDARY(定义不明确)和 CLIPBOARD(预期用于剪切、复制和粘贴操作)。这三个中,Vim 在读取和写入 "* 寄存器时使用 PRIMARY(因此当 X11 选项可用时,Vim 为 "autoselect" 的 'clipboard' 设置默认值),在读取和写入 "+ 寄存器时使用 CLIPBOARD。 Vim 不访问 SECONDARY 选择。示例:(假设默认选项值)在 Vim 的可视模式中选择一个 URL。转到您的浏览器并在 URL 文本字段中单击鼠标中键。所选文本将被插入(希望如此!)。注意:在 Firefox 中,您可以在 about:config 中将 middlemouse.contentLoadURL 首选项设置为 true,然后在窗口中的大多数位置按下鼠标中键时将使用选定的 URL。通过用鼠标拖动在浏览器中选择一些文本。转到 Vim 并按鼠标中键:插入选定的文本。在 Vim 中选择一些文本并执行“+y”。转到您的浏览器,通过用鼠标拖动在文本字段中选择一些文本。现在使用鼠标右键并从弹出菜单中选择“粘贴”。所选文本被覆盖来自 Vim 的文本。请注意,在进行可视选择时,“+ 寄存器中的文本仍然可用,这使得“* 寄存器中的其他文本可用。这允许覆盖选定的文本。


我注意到在 vim 中使用中键似乎不会弄乱缩进,所以这可能是一个想法
T
TheChetan

另一种粘贴方法是在插入模式下通过 <C-r> 并删除寄存器的内容(这里是全局寄存器)。请参阅::h i_ctrl-rh i_CTRL-R_CTRL-O

从 vim 帮助文档中:

从字面上插入寄存器的内容,不要自动缩进。和用鼠标粘贴一样。不替换字符!这 '。'寄存器(最后插入的文本)仍按键入的方式插入。{Vi 无此功能}

因此,要在不自动缩进的情况下将内容粘贴到 vim 中,请在大多数 unix 系统中使用 <C-r><C-o>*

您可以在 vimrc inoremap <C-r> <C-r><C-o> 中添加一个映射,这样您就可以正常粘贴 * 寄存器的内容,而无需使用 <C-r>* 自动缩进。

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


干杯,这是迄今为止最好的解决方案,因为出于某种原因我只有 有这个问题,命令模式下的 p 不受这个问题的影响。理想情况下,如果 可以简单地表现得像 p 那样会很好,但同时也可以这样做!
S
Sergey Vakulenko

这对我有用(+寄存器的情况,我使用的就像aps之间的交换缓冲区):

imap <silent> <S-Insert> <C-O>:set noai<CR><C-R>+<C-O>:set ai<CR>

B
Bruno

来自 vim:]p

从外部:"*]p"+]p


M
Marcus Ericsson

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

brew install macvim --override-system-vim


如果您在 .vimrc 文件中包含 OP 的指令,是否会出现这种情况?
G
Gael

这个问题已经得到解答,但我虽然也可以添加自己的解决方案:

如果您只是想禁用自动缩进系统,对于每种文件类型(基本上,完全禁用自动缩进功能),您可以执行以下操作:

备份 indent.vim 文件:sudo mv /usr/share/vim/vim81/indent.vim /usr/share/vim/vim81/indent.vim.orig 创建一个新的空 indent.vim 文件:sudo touch /usr/share /vim/vim81/indent.vim


d
d.danailov

请阅读这篇文章:Toggle auto-indenting for code paste

有些人喜欢 vimrc 的以下替代方案在状态行中显示的视觉反馈:

nnoremap <F2> :set invpaste paste?<CR>
set pastetoggle=<F2>
set showmode

M
Micah Elliott

我所知道的快速进入粘贴插入模式以进行一次性粘贴的最快方法是 tpope 的 unimpaired,它具有 yoyO >,大概是“你打开”的助记词。它们仅记录在他的 vimdoc 中,如下所示:

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


w
wisbucky

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

确保你有 vim 8+(你不需要 +clipboard 或 +xterm_clipboard 选项)。 vim --版本 | head -1 只需在正常模式下使用操作系统本机粘贴命令(例如 ctrl+shift+V 或 cmd+V)。不要按 i 进入插入模式。

测试

复制(ctrl+shift+C 或 cmd+C)此(2 行带有制表符缩进的行)的输出到系统剪贴板: echo -e '\ta\n\tb' 使用自动缩进启动干净的 vim 8+:vim -u NONE --noplugin -c 'set autoindent' 在正常模式下从系统剪贴板(ctrl+shift+V 或 cmd+V)粘贴。不要按 i 进入插入模式。 a 和 b 应与单个制表符缩进对齐。您甚至可以在 ssh-ing 到远程机器时执行此操作(远程机器需要 vim 8+)。现在尝试旧方法,这将使用一个额外的选项卡自动缩进第二行:按 i 进入插入模式。然后使用 ctrl+shift+V 或 cmd+V 粘贴。 a 和 b 现在没有对齐。

安装 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

Mac:冲泡安装 vim


最好和最简单的方法!此外,Google 在 Featured snippet 中为我的搜索“paste content no tabs vim”提出了建议,可能是因为我使用了“tab”关键字,只在这个答案中提到:)
t
thiagowfx

以下 vim 插件通过其“括号粘贴”模式自动处理:https://github.com/wincent/terminus

设置“括号粘贴”模式,这意味着您可以忘记手动设置“粘贴”选项,只需继续以任何模式粘贴即可。


G
Goblinhack

可悲的是,我发现提到的 vim 插件不能与 iTerm2 3.0.15 一起使用(公平地说,我不知道这是否在旧版本上损坏) - 但我发现了这个 hack。

映射命令-p 进行粘贴并使用 iTerm2 vim 键。显然这只适用于 iTerm2。

这个怎么运作。我使用“jk”进入转义模式,所以你还需要:

:inoremap jk

在你的 .vimrc 中。

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

https://i.stack.imgur.com/CKXUt.png


等等,什么,你用'jk'来做这个?
哦,是的,我忘了提到这一点。只需将 ":inoremap jk " 添加到您的 .vimrc 中。至于我为什么使用 jk,请询问 Apple 以及为什么他们觉得需要移动并摆脱物理转义键。 8(
顺便说一句,这需要一些培训,但过了一会儿 jk 感觉更快,我想我现在更喜欢它而不是逃跑......无论如何,知道 iTerm2 是否也接受 在这里会很有趣。
苹果加油!
E
Ela Dute

如果您使用 v8.2 以上的 vim,您可以使用 :help tmux-integration 检查。

如果您在 tmux 中运行 Vim 时遇到问题,这里有一些提示。如果某些东西不起作用,您可以注释掉部分(它可能取决于 tmux 正在运行的终端):

if !has('gui_running') && &term =~ '^\%(screen\|tmux\)'
    " Better mouse support, see  :help 'ttymouse'
    set ttymouse=sgr

    " Enable true colors, see  :help xterm-true-color
    let &termguicolors = v:true
    let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
    let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"

    " Enable bracketed paste mode, see  :help xterm-bracketed-paste
    let &t_BE = "\<Esc>[?2004h"
    let &t_BD = "\<Esc>[?2004l"
    let &t_PS = "\<Esc>[200~"
    let &t_PE = "\<Esc>[201~"

    " Enable focus event tracking, see  :help xterm-focus-event
    let &t_fe = "\<Esc>[?1004h"
    let &t_fd = "\<Esc>[?1004l"

    " Enable modified arrow keys, see  :help xterm-modifier-keys
    execute "silent! set <xUp>=\<Esc>[@;*A"
    execute "silent! set <xDown>=\<Esc>[@;*B"
    execute "silent! set <xRight>=\<Esc>[@;*C"
    execute "silent! set <xLeft>=\<Esc>[@;*D"
endif