从 Vim 迁移

很多 Vim 用户想用 Emacs,却卡在同一个问题上:手不听话。本篇先讲清两套模型到底差在哪,再给出四条迁移路线,最后正面回答一个被问得最多的问题——在 Emacs 里到底该怎么”启动 Vim”


一、先接受三件事

迁移失败的人,绝大多数不是因为学不会 Emacs,而是因为一开始就用 Vim 的预期去要求 Emacs。所以先把三处根本差异摆出来。

1.1 模态与非模态

Vim 是模态编辑器:同一个按键在不同模式下有不同含义,d 后面必须跟一个动作(dwd$)才完整。Emacs 默认没有模式概念:任何时刻按下 C-n 都是”下一行”,M-x 永远能调出命令。

flowchart LR
    subgraph VIM["Vim 模型:按键含义取决于模式"]
        V1["普通模式<br/>d w 删除一个词"] --> V2["插入模式<br/>直接输入文字"]
        V2 --> V3["可视模式<br/>选区操作"]
        V3 --> V1
    end
    subgraph EMACS["Emacs 模型:按键含义固定,功能靠命令组合"]
        E1["任何时刻<br/>C-n 都是下一行"] --> E2["任何时刻<br/>M-x 都能调出命令"]
        E2 --> E3["任何时刻<br/>C-g 都能取消"]
    end

这不代表 Emacs 更好或更差,而是意味着:在 Emacs 里你不需要”回到普通模式”,也就没有”忘了自己在哪个模式”的焦虑;代价是长时间按修饰键,以及必须记住命令名。 后面要装的 evil-mode,就是把这套模态体验搬进 Emacs。

1.2 概念对照表

Vim 概念Emacs 概念差异要点
bufferbuffer基本相同,都是文件在内存中的副本
window(分割)windowEmacs 的 window 是窗口内的一个视图区,不是操作系统的窗口
tab(标签页)tab-bar / frameEmacs 的 frame 才是操作系统窗口;tab-bar 才是标签页
:commandM-x 命令Emacs 里一切功能都是可调用的命令,数量级更大
.vimrcinit.el配置语言不同:Vimscript / Lua 对 Elisp
插件管理器(vim-plug 等)package.el / use-packageEmacs 的包管理器是内置的
寄存器 registerregister / kill-ringkill-ring 是自动维护的剪切历史
宏 macro键盘宏 kmacroC-x ( 录制、C-x ) 结束、C-x e 执行
markmark概念相近,用法与键位不同
% 匹配括号C-M-n / C-M-p / show-paren-modeEmacs 靠 sexp 导航而不是符号匹配
:helpC-h 全家桶Emacs 的帮助系统是它最被低估的部分

1.3 插件生态的生态位差异

Vim 的哲学是”小而快的编辑器,需要什么装什么”,插件之间边界清晰;Emacs 的哲学是”可编程环境”,很多功能(文件管理、Git、终端、邮件、PDF、日程)是内置或者由内置库演化来的。这带来两个实际后果:

  • 你在 Emacs 中要装的东西可能比在 Vim 中少(例如 Dired 等价于 netrw + 一堆文件管理插件,且远比 netrw 强大)。
  • 但你更需要理解”这些功能是怎么被组织的”,否则会陷入”装了八十个包却不知道它们如何协作”的状态。

二、四条迁移路线

不要一上来就问”哪个最好”。先看你要的是什么。

flowchart TD
    A["你是 Vim 用户"] --> B{"迁移目标是"}
    B -->|"完全转到 Emacs,但保留手感"| C["路线 A:原生 Emacs + evil-mode"]
    B -->|"尽快得到可用环境,不想自己配"| D["路线 B:Doom Emacs"]
    B -->|"想要成熟的一体化框架"| E["路线 C:Spacemacs"]
    B -->|"只想在需要时用 Emacs"| F["路线 D:两个编辑器并存"]
    C --> C1["理解最深<br/>配置最自由<br/>上手最慢"]
    D --> D1["上手最快<br/>默认就是 evil<br/>需要接受它的约定"]
    E --> E1["生态成熟<br/>文档完善<br/>较重且有自己的规范"]
    F --> F1["零迁移成本<br/>用 emacsclient 互通<br/>放弃统一工作流"]

路线对比表

维度路线 A:原生 + evil路线 B:Doom路线 C:Spacemacs路线 D:并存
上手时间数小时到数天十分钟半小时五分钟
默认 Vim 手感需要自己装 evil默认就是 evil首次启动可选 vim 风格不需要
配置自由度和可控性最高中(可用 config.el 覆盖)中(.spacemacs 分层)不涉及
学习价值最高
启动速度取决于你的配置经过优化偏慢不涉及
适合谁想长期掌握 Emacs 的人想立刻干活的人喜欢开箱框架的人不确定要不要转的人

建议:先走路线 D 或路线 B 中的一条,用一两周确认自己真的要用 Emacs,再决定要不要走路线 A。 本文的重点是路线 A 与路线 D——因为它们才是”从 Vim 迁移”这件事的技术核心。


三、路线 A:手装 evil-mode

3.1 安装与启用

;; 在 init.el 中:先安装再启用
(use-package evil
  :ensure t
  :init
  ;; 必须在 require evil 之前设置,否则不生效
  (setq evil-want-integration t)      ; 与 Emacs 原生键位集成
  (setq evil-want-keybinding nil)     ; 由 evil-collection 接管各模式的键位
  (setq evil-undo-system 'undo-redo)  ; 用 Emacs 28+ 内置的 undo-redo
  :config
  (evil-mode 1))                      ; 全局启用
 
;; evil-collection 把 evil 的键位适配到 dired、magit、help 等内置与第三方模式
(use-package evil-collection
  :ensure t
  :after evil
  :config
  (evil-collection-init))

如果暂时不用 use-package,等价的裸写法是:

(require 'evil)
(evil-mode 1)

第一次启动时会从 MELPA 下载,安装完成后 M-x evil-mode 可以随时开关全局 evil。

3.2 evil 的状态机

evil 不只是”把 hjkl 绑定成方向键”,它实现了一整套状态机,这也是它比简单的 vi 模拟更接近 Vim 的原因。

stateDiagram-v2
    [*] --> Normal
    Normal --> Insert: i a o O I A s c
    Insert --> Normal: ESC 或 C-[
    Normal --> Visual: v V C-v
    Visual --> Normal: ESC
    Normal --> Replace: R
    Replace --> Normal: ESC
    Normal --> Operator: d c y 等操作符
    Operator --> Normal: 接一个动作后自动返回
    Normal --> Motion: 只读模式等场景自动进入
    Normal --> Emacs: C-z
    Emacs --> Normal: C-z

各状态的含义:

状态作用进入方式
normal与 Vim 普通模式基本一致ESCC-[
insert与 Vim 插入模式一致iaoOIAsc
visual字符/行/块可视模式vVC-v
replace覆盖输入R
operator按下 d/c/y 后等待动作的中间状态自动进入并自动返回
motion只读模式(如 Dired)中自动使用的状态由模式决定
emacs临时完全交还给 Emacs 原生按键C-z

C-z 是关键:在普通状态按 C-z,evil 会切到 emacs 状态,此时 C-fC-nC-y 等原生键位全部回来;再按 C-z 切回普通状态。切换键由变量 evil-toggle-key 控制,不确定当前值时用 C-h v evil-toggle-key RET 查看。

另外,Emacs 的 C-x 前缀在 evil 的普通状态下依然可用——evil 只覆盖它自己定义了绑定的键位。所以在普通状态里直接按 C-x C-f 找文件、C-x C-s 保存,都正常。

3.3 ex 命令行

在普通状态按 : 会打开 evil 的 ex 命令行,支持 Vim 的一部分 ex 命令:

:w                  " 保存
:q                  " 退出当前窗口
:wq                 " 保存并退出
:e ~/.emacs.d/init.el
:%s/foo/bar/g        " 全文替换
:g/TODO/d           " 删除所有含 TODO 的行
:set nu             " 显示行号(evil 只实现了部分 :set 选项)

与 Vim 的差别要提前知道:evil 实现的是 ex 命令的子集,不是全部。在 : 后面按 TAB 可以看到当前支持的命令补全;C-c C-c 之类的用法在 evil 里不存在。遇到不支持的 ex 命令时,改用对应的 Emacs 命令即可(下一节有对照表)。

3.4 一份可直接使用的 evil 配置

(use-package evil
  :ensure t
  :init
  (setq evil-want-integration t)
  (setq evil-want-keybinding nil)
  (setq evil-undo-system 'undo-redo)
  ;; 搜索时不要移动光标(与 Vim 默认一致)
  (setq evil-search-module 'evil-search)
  (setq evil-ex-search-vim-style-regexp t)
  (setq evil-split-window-below t)    ; :sp 在下方分割
  (setq evil-vsplit-window-right t)   ; :vsp 在右侧分割
  (setq evil-shift-width 4)           ; >> 与 << 的缩进宽度
  :config
  (evil-mode 1)
  ;; 让 C-u / C-d 保持 Emacs 的"翻页"含义以外的行为时,用下面这行
  ;; 在普通状态下用 M-数字前缀代替 Vim 的计数前缀(evil 已支持 3j 这类计数)
  (define-key evil-normal-state-map (kbd "C-h") 'evil-window-left)
  (define-key evil-normal-state-map (kbd "C-j") 'evil-window-down)
  (define-key evil-normal-state-map (kbd "C-k") 'evil-window-up)
  (define-key evil-normal-state-map (kbd "C-l") 'evil-window-right))
 
(use-package evil-collection
  :ensure t
  :after evil
  :config
  (evil-collection-init))

evil-window-left / evil-window-down / evil-window-up / evil-window-right 是 evil 提供的窗口切换函数,把它们绑到 C-h/j/k/l 上,就得到 Vim 用户熟悉的”Ctrl+方向键切分屏”手感。

3.5 值得一起装的 Vim 风格增强包

对应的 Vim 能力说明
evil-surroundvim-surroundcs"'ds"ysiw) 全套
evil-nerd-commentervim-commentarygccgc 注释切换
evil-matchitmatchit% 在 HTML/if-end 等结构间跳转
evil-easymotionvim-easymotion快速跳转到任意位置
avyvim-sneak / easymotionEmacs 侧最常用的跳转包,可与 evil 配合
expand-region.el无直接对应逐级扩大选区,Vim 用户会很喜欢
multiple-cursors.elvim-multiple-cursors多光标编辑
smartparensauto-pairs括号自动配对与结构化编辑
undo-fuVim 的撤销树手感提供接近 Vim 的撤销/重做语义
undo-treeundotree可视化撤销历史树

四、在 Emacs 里”启动 Vim”到底指什么

这个问题有四种完全不同的含义,很多争论其实是在各说各话。下面逐条给出做法。

flowchart TD
    Q["我想在 Emacs 里启动 Vim"] --> A{"你想要的是什么"}
    A -->|"想要 Vim 的操作方式"| B["让 Emacs 变成模态编辑器<br/>装 evil-mode 或直接用 Doom"]
    A -->|"想在 Emacs 窗口里运行真的 Vim 程序"| C["用 vterm / eat / term<br/>开一个终端再敲 vim"]
    A -->|"想从 Vim 跳到 Emacs 编辑同一个文件"| D["emacsclient -c -n +行号 文件"]
    A -->|"想继续以 Vim 为主,Emacs 只做补充"| E["混合工作流<br/>用 EDITOR 与 :! 互通"]

4.1 含义一:我想要 Vim 的操作方式

这就是上一节的 evil-mode,或者直接用 Doom Emacs(它默认就是 evil)。此时”启动 Vim”= 启动 Emacs,按键体验是 Vim 的。

4.2 含义二:我想在 Emacs 窗口里跑真正的 Vim 程序

可以,而且很实用。Emacs 有终端模拟器,终端里当然可以运行 Vim。

方案一:vterm(推荐,性能最好)

;; 需要编译原生模块,安装前先准备 cmake 与 libtool
(use-package vterm
  :ensure t
  :commands vterm
  :bind ("C-c t" . vterm))

安装依赖:

# Debian / Ubuntu
sudo apt install cmake libtool libtool-bin
 
# Arch Linux
sudo pacman -S cmake libtool
 
# macOS
brew install cmake libtool

Windows 上 vterm 需要 MSYS2 环境编译,成功率不高,建议改用下面的 eat

然后在 vterm 缓冲区里直接敲:

vim ~/.emacs.d/init.el

这会启动一个真正的 Vim 进程,你在里面看到的界面、:help、插件全部是货真价实的 Vim。有一个关键点:在 vterm 里运行 Vim 时,Vim 拿不到 Emacs 的按键映射,它是独立进程,所以按 Esc 返回 Vim 的普通模式是有效的;但 vterm 自身也有一个”复制模式”(vterm-copy-mode),需要用键位(默认 C-c C-t)进出,具体以 C-h b 在该缓冲区内的显示为准。

方案二:eat(纯 Elisp,无编译依赖)

eat 是一个纯 Elisp 实现的终端模拟器,项目地址在 codeberg.org/akib/emacs-eat,安装后 M-x eat 即可。它在性能上不如 vterm,但胜在零编译依赖、跨平台一致,对”只想在 Emacs 里跑一次 Vim”这种需求完全够用。

方案三:内置 term / ansi-term

M-x ansi-term 是 Emacs 内置方案,不需要装任何东西。它对全屏 TUI 程序的支持不如前两者,主要问题是字符模式下控制字符的处理term 有行模式与字符模式(C-c C-j 切换),C-cC-\ 这类按键的行为与真实终端存在差异,实际使用时用 C-h b 查看当前缓冲区内的绑定最可靠。如果只是想临时跑个 Vim,可以接受;长期使用建议换 vterm 或 eat。

为什么要在 Emacs 里跑 Vim 而不是直接开一个终端窗口?

  • 所有内容都在同一套键位与主题里,切换成本低。
  • 可以用 Emacs 的复制粘贴、搜索(在当前缓冲区里 C-s)处理终端输出。
  • 在学习 Emacs 的过渡期作为”降落伞”,随时能回到熟悉的环境。

4.3 含义三:从 Vim 跳到 Emacs 编辑同一个文件

这是混合工作流最有价值的一条:Vim 里正在编辑的文件,按一个键交给 Emacs 打开,编辑完回到 Vim 继续。

先启动 Emacs 守护进程,这样每次调用都是瞬间打开:

# 启动守护进程(只启动一次)
emacs --daemon

然后在 Vim 里加一条命令(写进 .vimrc):

" 把当前文件在当前行位置交给 Emacs 打开
command! -bar EmacsEdit execute '!emacsclient -c -n +' . line('.') . ' ' . shellescape(expand('%:p'))
 
" 顺便给个快捷键
nnoremap <leader>e :EmacsEdit<CR>

emacsclient 的参数含义:

参数含义
-c创建一个新的图形窗口(frame)
-n不等待,立刻返回(否则 Vim 会卡住等 Emacs 关闭)
-t在当前终端里打开(适合纯终端环境,如 :terminal 里)
-a ""如果守护进程没启动,就先启动它再连接
+N跳到第 N 行

如果 Vim 运行在远程服务器、Emacs 运行在本地,可以用 -t 配合 SSH 与端口转发,或者反向使用——把 Emacs 也跑在服务器上。

4.4 含义四:想继续以 Vim 为主,只借 Emacs 的部分能力

最常见的两种借法:

借 Emacs 当 Git 提交编辑器(比 Vim 里写提交信息舒服)

# 需要守护进程已启动
git config --global core.editor "emacsclient -c -a ''"

借 Emacs 当某些工具的外部编辑器

export EDITOR="emacsclient -t -a ''"   # 终端场景
export VISUAL="emacsclient -c -a ''"   # 图形场景

这样 crontab -esudoeditgit commit 等所有遵守 EDITOR 约定的工具都会交给 Emacs。想改回 Vim 只要取消这两行环境变量即可,这是一次零风险的双向切换

4.5 反向:从 Emacs 回到 Vim

如果 Emacs 里你想直接调用系统 Vim,最简单的方式是在终端缓冲区里敲 vim;如果想用当前文件打开,可以写一个小命令:

(defun my-open-in-vim ()
  "用系统 Vim 打开当前文件,并定位到当前行。"
  (interactive)
  (let ((file (or buffer-file-name
                   (user-error "当前缓冲区没有关联文件")))
        (line (line-number-at-pos)))
    (start-process "vim" nil "vim" (format "+%d" line) file)
    (message "已在新终端启动 Vim:%s" file)))

图形界面下 start-process 启动的终端程序能否显示取决于你的终端配置,更可靠的做法是在 vterm 里执行。这条命令的意义在于心理上:你知道随时可以回去,就不会因为焦虑而放弃 Emacs。


五、键位对照大全

下面按功能分组。左侧是 Vim,右侧是 Emacs 原生,最后一列是 evil 下的情况。

5.1 移动

VimEmacs 原生evil 下
h j k lC-b C-n C-p C-f与 Vim 相同
w b eM-f M-b M-e与 Vim 相同
0 ^ $C-a M-m C-e与 Vim 相同
gg GM-< M->与 Vim 相同
C-d C-uC-v M-vC-d 保留 Vim 语义
%C-M-n / C-M-p(按括号对跳转)evil-matchit
f t ; ,C-s 搜索 / avy 跳转与 Vim 相同(avy 更强)
{ }M-{ M-}(按段落移动)与 Vim 相同
zz zt zbC-l(把当前行移到屏幕中央)与 Vim 相同

5.2 编辑

VimEmacs 原生说明
xC-d删除一个字符
ddC-a C-kM-x kill-line删除整行;Emacs 的 C-k 删除到行尾
dwM-d删除一个词
d$C-k删除到行尾
yyM-w(复制)配合选区Emacs 没有”整行 yank”的单键,M-w 复制选区
p PC-y粘贴;Emacs 的 C-y 与 Vim 的 C-y(上滚一行)冲突
uC-/C-_C-x u撤销
C-rM-x undo-redo(28+)或 C-g C-/重做;Emacs 的 C-r 是反向搜索
ciw ci"无直接对应,expand-region 最接近结构化修改是 evil-surround 的领域
>> <<C-c C->? 用 M-x indent-rigidly 或选中后 TABevil 下 >><< 可用
gccM-;comment-dwim注释切换,Emacs 原生一个键搞定
JM-^delete-indentation合并两行
~无直接对应大小写转换用 M-u M-l M-c
gu gUM-l M-u小写/大写

5.3 搜索与替换

VimEmacs 原生说明
/ ?C-s C-r增量搜索,边输边跳
n NC-s C-s(重复上一次搜索)/ C-r重复搜索
*C-s C-wM-x isearch-forward-symbol-at-point搜索光标下的词
:%s/a/b/gM-x query-replaceC-M-%(正则)交互式替换
:g/pat/dM-x delete-matching-lines删除匹配行
:vimgrepM-x rgrep / consult-ripgrep项目内搜索

5.4 文件、窗口、缓冲区

VimEmacs 原生说明
:e fileC-x C-f打开文件
:wC-x C-s保存
:qC-x C-c(退出 Emacs)/ C-x k(关闭缓冲区)注意 :q 在 evil 里关闭窗口而不是退出 Emacs
:sp :vspC-x 2 C-x 3水平/垂直分割
C-w h/j/k/lC-x o 或方向键配合 windmove在窗口间移动
:bdC-x k关闭缓冲区
:lsC-x C-bM-x ibuffer列出缓冲区
gt gTC-x t o / tab-bar-switch-to-tab切换标签页(需 tab-bar-mode
:terminalM-x vterm / M-x eat / M-x shell打开终端

5.5 宏、寄存器、标记

VimEmacs 原生说明
q 录制 / @ 执行C-x ( / C-x ) / C-x eevil 下 Vim 的录制方式可用
"ayy / "apC-x r 系列寄存器命令Emacs 的 register 用 C-x r s / C-x r i
ma / `aC-x r SPC a / C-x r j aEmacs 的 register 也存位置
Ctrl-o / Ctrl-iM-x pop-global-mark跳转历史
. 重复上次修改无对应命令Emacs 里靠键盘宏或多次 C-x zrepeat

六、: 命令到 M-x 命令的对照

Vim 的 ex 命令对应到 Emacs 就是”调用一个命令”。下面是最常用的对照。

Vim exEmacs 等价备注
:wC-x C-s另存为用 C-x C-w
:q / :q!C-x k 后按 ! 强制丢弃修改并关闭缓冲区
:wq / :xC-x C-s C-x kEmacs 里保存与关闭是两个动作
:e .C-x d打开 Dired 文件管理器
:e!M-x revert-buffer从磁盘重新读取
:set nuM-x display-line-numbers-mode
:set pasteM-x electric-indent-mode 关闭Emacs 侧对应的是缩进行为
:help xxxC-h f / C-h v / C-h k按”函数/变量/按键”分别查
:makeM-x compile通用命令执行框架
:grepM-x rgrep
:terminalM-x vterm
:cdM-x cd修改当前缓冲区的默认目录
:!cmdM-x shell-commandM-!执行一次性外部命令
:r fileM-x insert-file把文件内容插入当前位置
:normal @qM-x apply-macro-to-region-lines对每行执行宏
:bufdo无直接对应ibuffer 标记后批量操作,或写一段 Elisp

七、Vim 插件到 Emacs 包的对照

Vim 插件Emacs 对应说明
vim-plug / lazy.nvimpackage.el + use-package内置,无需额外安装
NERDTree / nvim-treeDired、treemacs、dirvishDired 是内置的,先学它
fzf / telescopeconsult + vertico模糊查找文件、缓冲区、搜索
CtrlPvertico + consult同上
vim-airline / lualinedoom-modeline、mood-line状态栏
gruvbox / tokyonightmodus-themes、doom-themes、catppuccin主题
vim-fugitiveMagit功能远超 fugitive
vim-commentaryM-;(内置)或 evil-nerd-commenter
vim-surroundevil-surround
auto-pairssmartparens 或内置 electric-pair-mode
ALE / coc.nvimeglot(Emacs 29 起内置)、lsp-mode
nvim-cmpcorfu + cape
vim-easymotion / sneakavyevil-easymotion
undotreeundo-fuundo-tree
vimwikiOrg mode、org-roam
vimtexAUCTeX
vim-tmux-navigatorwindmove + 窗口键位需要配合 tmux 配置
which-key.nvimwhich-key(Emacs 30 起内置)按下前缀键后显示可用后续键

八、肌肉记忆冲突清单

从 Vim 迁移到 Emacs,最危险的不是”不会用”,而是”手比脑快”。下面这些冲突会导致实际的数据损失,请认真读一遍。

按键Vim 里是Emacs 里是风险处理建议
C-w删除前一个词(插入模式)剪切选中区域用 evil 时注意状态;误切后 C-/ 撤销
C-y向上滚动一行粘贴用 evil 后语义回到 Vim
C-r重做反向增量搜索用 evil 后语义回到 Vim
C-a行首 / 数字加一行首(同 Vim)一致
C-x数字减一极重要的前缀键evil 普通状态下未被覆盖
C-u上翻半屏通用前缀参数在 Emacs 里 C-u 3 C-n 表示”往下 3 行”
ESC退出插入模式元键(等同 M-在终端里 ESC 有延迟,用 C-[ 代替更稳
C-[等同 ESC等同 ESC与 Vim 一致,可放心使用
C-c无特殊含义用户自定义前缀Emacs 惯例把 C-c + 字母 留给用户
C-g取消当前操作Emacs 里最重要的键,任何卡住都先按它
C-h左移一个字符帮助前缀在 evil 普通状态下 h 才是左移;C-h 是帮助

一条经验:在 Emacs 里养成”先按 C-g”的条件反射。命令输错、搜索卡住、minibuffer 里迷路、执行太久想中止,全都是 C-g。这个键在 Vim 里没有对应物,但它可能是 Emacs 里你最常用的键。

8.1 过渡期的三个建议

  1. 前两周不要折腾配置。 用 evil(或 Doom)把 Vim 手感保住,把精力放在理解 buffer、window、minibuffer、帮助系统上。
  2. 每天强制自己用一次原生 Emacs 键位。 比如强制用 C-x C-s 保存、C-x C-f 打开文件。这些是 Emacs 的”公共语汇”,绕开它们会让你之后读不懂别人的配置。
  3. 把”卡住”当成信号。 每次卡住都追问一句”Emacs 里这件事对应哪个命令”,然后用 C-h 查出来。三个月后你会发现自己在 Emacs 里比在 Vim 里更少卡住。

九、Doom Emacs 与 Spacemacs 快速上手

如果你选择路线 B 或 C,这里给出最小可用步骤。

9.1 Doom Emacs

# 备份原有配置(如果 ~/.emacs.d 已有内容)
mv ~/.emacs.d ~/.emacs.d.bak
 
# 克隆并安装
git clone --depth 1 https://github.com/doomemacs/doomemacs ~/.config/emacs
~/.config/emacs/bin/doom install

安装后:

操作命令
应用配置改动doom sync
升级 Doom 与包doom upgrade
诊断环境doom doctor
打开配置文件SPC f p 或直接编辑 ~/.config/doom/config.el
调用任意 Emacs 命令SPC :

Doom 的三个核心文件:init.el(模块开关)、config.el(个人配置)、packages.el(声明额外包)。它的默认键位是 evil,SPC 是 leader 键。Windows 下配置目录是 %APPDATA%\doom

9.2 Spacemacs

git clone https://github.com/syl20bnr/spacemacs ~/.emacs.d

首次启动会询问编辑风格,选择 vim 即可获得 Vim 键位(还有 emacshybrid 两种)。个人配置写在用户主目录的 .spacemacs 文件中,SPC 是 leader 键,按下 SPC 后稍等即可看到 which-key 提示的后续按键(例如 SPC f e d 打开配置文件)。

9.3 什么时候该离开框架

两个信号:第一,你开始频繁地”绕过”框架的约定;第二,你读不懂启动过程发生了什么。这时就该考虑回到路线 A,用自己的配置重建一个你完全理解的环境。框架的价值是让你快速用起来,不是永远替你做决定。


十、混合工作流的取舍

最后给一份实用建议。如果你一时决定不了,就按这张表分工。

任务建议工具理由
快速改一行配置、临时看一个文件Vim启动快,不打断思路
长时间写代码、多文件重构Emacs补全、LSP、Magit、项目导航一体化
写文档、写笔记Emacs(Org / Markdown)Org 的能力在 Vim 侧没有对等物
Git 操作任意,但推荐 Magit复杂操作(拆提交、交互式变基)在 Magit 里更快
远程服务器上临时编辑Vim(或用 TRAMP + Emacs)取决于服务器是否装了 Emacs
提交信息、crontab 等外部编辑器场景EDITOR=emacsclient两端都能用,随时切换

十一、常见问题

现象原因解决
evil 装完没反应evil-mode 没启用,或包没装成功确认 (evil-mode 1),用 M-x list-packages 看是否已安装
在 Dired 里按 j 没反应evil 未适配该模式安装并初始化 evil-collection
终端里按 Esc 有明显延迟终端无法区分单独的 ESC 与转义序列的开头C-[ 代替,或使用图形界面版 Emacs
:q 没有退出 Emacsevil 的 :q 关闭的是当前窗口退出 Emacs 用 C-x C-c
C-w 把整段文字删掉了C-w 在 Emacs 里是剪切选区C-/ 撤销,之后注意所处状态
想临时用原生 Emacs 键位不必改配置普通状态下按 C-z 切到 emacs 状态
vterm 里 Vim 显示错乱缺少 vterm 模块或行高设置问题确认模块编译成功(M-x vterm 有报错会提示),或改用 eat
中文输入法在 evil 下异常输入法切换键与 evil 状态键冲突调整输入法的切换键,或只在插入状态下切换
emacsclient 报 “can’t find socket”守护进程没启动先执行 emacs --daemon,或用 -a "" 让它自动启动
想彻底回到 Vim正常卸载即可删掉 ~/.emacs.d(先备份),Vim 的配置一直都在

小结

  • Emacs 与 Vim 的差异不在键位,而在”模态 / 非模态”和”编辑器 / 可编程环境”这两层模型上;先接受模型,键位只是习惯问题。
  • 想在 Emacs 里获得 Vim 手感,装 evil-mode(或直接用 Doom);在 Emacs 里跑真正的 Vim,用 vterm 或 eat 开终端;两端互通,用 emacsclient -c -n +行号
  • 最危险的是肌肉记忆冲突,尤其是 C-wC-yC-rESC。养成先按 C-g 的习惯。
  • 迁移期不要追求一步到位。保留 Vim 作为降落伞,用 EDITOR:!emacsclient 打通两端,是不会失败的做法。

相关章节