2026 年维护说明:前半部分是面向当前 Vim 与 Neovim 的排查指南。末尾的存档部分完整保留 2019 年源导出,包括原有措辞、Markdown、命令和当年的 Stack Overflow 链接。旧的
:set paste流程今天仍可作为 Vim 的手动备用方案;当前 Vim 已能识别终端的 bracketed paste,而 Neovim 会自动处理粘贴并且已经移除pastetoggle。这三条路径不能再混为一谈。
Table of Contents
最短答案
如果从终端粘贴代码后,每一行都比上一行更靠右,先确认实际运行的是哪一个编辑器:
:version
:echo has('nvim')
然后选择对应路径:
| 环境 | 应怎样处理 |
|---|---|
| Vim,偶尔一次粘贴错乱 | 运行 :set paste,在 Insert 模式粘贴,完成后立刻运行 :set nopaste |
| Vim,反复出现错乱 | 优先修复 bracketed paste;确实无法修复时,才把 set pastetoggle=<F3> 作为手动备用方案 |
| Neovim | 不要添加 pastetoggle;它已被移除。正常的终端或 GUI 粘贴应自动处理 |
| Vim 或 Neovim 能使用系统剪贴板寄存器 | 退出 Insert 模式后用 "+p,直接绕开终端把粘贴内容模拟成按键的路径 |
不要在 Vim 配置中永久写入 set paste。paste 模式会有意关闭或改变映射、缩写、缩进、制表、换行和格式化行为。一直开着它,虽然解决了一次粘贴,却会悄悄破坏正常编辑。
为什么粘贴后会形成“缩进楼梯”
终端可能把粘贴内容作为一连串普通按键交给编辑器。如果编辑器无法区分“粘贴”和“逐字输入”,每个换行都会触发 autoindent、smartindent、cindent、indentexpr、注释续行或其他格式规则。剪贴板中原有的缩进又叠加上编辑器新算出的缩进,于是变成:
if condition:
first_call()
second_call()
third_call()
Bracketed paste 解决的是输入分类问题。支持它的终端会在粘贴内容前后加开始和结束标记,Vim 或 Neovim 因而能把整块内容当作粘贴,而不是普通输入。前提是终端、SSH、tmux 等复用器和编辑器组成的完整链路都能保留并理解该协议。
Vim:手动 paste 流程
对于 Vim,2019 年的做法今天仍可作为备用方案:
:set paste
进入 Insert 模式并粘贴。完成后返回 Normal 模式,恢复正常行为:
:set nopaste
如果确实经常需要手动切换,当前 Vim 帮助仍然记录了 pastetoggle:
set pastetoggle=<F3>
粘贴前后各按一次 <F3>。pastetoggle 与普通 Insert 模式映射不同:Vim 在 paste 开启时会忽略 Insert 模式映射,而这个专用选项仍能把 paste 模式关掉。
随时可以检查当前状态:
:set paste?
如果粘贴结束后 Vim 仍显示 paste,运行 :set nopaste。Vim FAQ 也明确警告,不要让该选项永久开启。
当前 Vim:优先使用 bracketed paste
当前 Vim 在 :help xterm-bracketed-paste 中记录了括号粘贴。终端协议可用时,Vim 会收到粘贴边界标记,把内容按字面插入,而不会将它解释为命令。这条路径正常时,不需要手动切换。
手动开关在终端链路过旧或配置异常时仍然有用,但它应是备用方案,不应成为第一项永久配置。Vim 文档还提醒,bracketed paste 不是安全保证:不同终端的实现可能不同,把不可信文本粘进编辑器或命令行前仍应先检查内容。
Neovim:删除旧的切换设置
Neovim 当前的 provider 文档说明,TUI 粘贴依赖终端的 bracketed-paste 能力,终端支持时会自动工作;GUI 则调用 Neovim 的 paste API。从 Neovim 0.9 起,pastetoggle 已被移除,paste 选项也已标为 obsolete。
因此,下面这条旧 Vim 设置不应出现在当前 Neovim 配置里:
set pastetoggle=<F3>
如果它在 init.vim 中引发 unknown option 错误,直接删除。若 Neovim 粘贴仍会重新缩进或插入原始转义标记,应排查终端、复用器、GUI 或配置链路,而不是重新实现已经移除的开关。
可重复的排查顺序
1. 确认编辑器和版本
使用 :version,不要只凭 shell 命令名或界面外观判断。Vim 与 Neovim 共用配置时,很容易把已废弃的选项也一起带过去。
2. 隔离用户配置
让同一个编辑器在不加载用户配置的状态下启动:
vim --clean
nvim --clean
粘贴一小段无害文本。clean 会话正常时,检查日常配置、filetype 插件、缩进插件和粘贴映射;clean 会话也失败时,终端、SSH 或复用器链路更值得怀疑。这个对比只是证据,不是最终证明;修改终端设置前,应分别在 tmux 或远程会话内外重复测试。
3. 检查 Vim 选项状态和来源
在 Vim 中运行:
:verbose set paste?
:verbose set autoindent? smartindent? cindent? indentexpr?
verbose 有时会显示最后修改选项的脚本。遗留的 paste 可以解释为什么粘贴后映射或缩进失效;意外的 indentexpr 或 filetype 插件,则可能解释为什么只有某一种文件会被改写。
4. 用寄存器绕开终端粘贴
如果编辑器能访问系统剪贴板,在 Normal 模式从 + 寄存器粘贴:
"+p
在 Insert 模式中,依次按 Ctrl-R、Ctrl-O、+。文档中的 CTRL-R CTRL-O {register} 会按字面插入寄存器内容并避免自动缩进。这样可以把“编辑器缩进问题”和“终端粘贴协议问题”分开。
如果 + 寄存器不可用,那是剪贴板功能或 provider 问题,并不能证明 paste 模式坏了。Neovim 中运行 :checkhealth;内置健康检查包含剪贴板支持。Vim 中查看 :version 的 clipboard 功能,再使用该构建和操作系统真正支持的剪贴板方法。
5. 比较传输链路
如果缓冲区里出现 ^[[200~ 之类的文字,说明 bracketed-paste 标记到达了缓冲区,却没有被识别。如果 tmux 外、SSH 外或另一个终端中的行为不同,应先比较这些层,再修改 Vim 缩进选项。不要随意把网上的终端转义码复制进配置:当前 Vim 可以利用 terminfo,而与终端不匹配的手工值会制造第二个问题。
症状—原因对照表
| 症状 | 优先检查的边界 | 第一步 |
|---|---|---|
| 粘贴的每一行逐渐右移 | 粘贴被当作普通输入解释 | 先试 clean 会话,再试 Vim 临时 :set paste |
| 粘贴后映射、缩写或正常缩进失效 | Vim 仍停留在 paste 模式 | :set paste?,然后 :set nopaste |
Neovim 报告 pastetoggle unknown | Neovim 配置中混入了 Vim 专用旧设置 | 删除它,测试自动粘贴与 nvim --clean |
出现字面量 ^[[200~ 或 ^[[201~ | 终端链路没有处理括号粘贴标记 | 对比 tmux/SSH 外和另一个终端 |
"+p 失败或 + 寄存器为空 | 缺少剪贴板功能或 provider | Neovim 用 :checkhealth;Vim 看 :version |
| 仅某一种 filetype 出问题 | filetype 或缩进脚本参与了处理 | :verbose set indentexpr? cindent? autoindent? |
最小判断规则
- 当前 Vim 和 Neovim 优先使用自动 bracketed paste。
- 系统剪贴板寄存器可用时,优先使用
"+p。 :set paste后接:set nopaste只作为 Vim 备用方案。pastetoggle只用于 Vim,并且只在手动备用方案确实反复需要时使用。- clean 会话仍然失败时,先查终端传输,再改缩进插件。
2019 年源存档(原文完整保留)
https://stackoverflow.com/questions/2514445/turning-off-auto-indent-when-pasting-text-into-vim
To turn off autoindent when you paste code, there’s a special “paste” mode.
Type
:set paste
Then paste your code. Note that the text in the tooltip now says -- INSERT (paste) --.
After you pasted your code, turn off the paste-mode, so that auto-indenting when you type works correctly again.
:set nopaste
However, I always found that cumbersome. That’s why I map <F3> such that it can switch between paste and nopaste modes while editing the text! I add this to .vimrc
set pastetoggle=<F3>
