Emacs consult-rg 执行后 color-rg 中文乱码问题排查与修复
Emacs consult-rg 执行后 color-rg 中文乱码问题排查与修复
问题描述
- 单独使用
consult-rg中文正常 - 单独使用
color-rg中文正常 - 使用
consult-rg之后,color-rg中文显示乱码 - 已排除 PowerShell 编码问题
原始排查过程
1. 定位 encoding 相关配置
文件 lisp/init-basic.el:
| |
文件 lisp/init-completion.el line 123,在 use-package consult :config 块内:
| |
文件 config.el line 225,同样存在:
| |
2. 发现关键问题
process-coding-system-alist 中的 ("es" gbk . gbk) 正则表达式 "es" 过于宽泛,它会匹配任何包含 “es” 子串的程序名。
该系统的 shell-file-name = C:\Program Files\Git\bin\bash.exe,路径中的 “Files” 包含 “es”,因此被该正则匹配。
而 compilation-start(color-rg 使用的进程启动方式)通过 start-file-process-shell-command 创建进程,最终使用的程序名是 shell-file-name(bash.exe 的完整路径)。Emacs 用 process-coding-system-alist 匹配程序名来决定编解码方式。
3. 为什么 “使用 consult-rg 之后” 才出现?
init-completion.el line 123 的 add-to-list 在 use-package consult :config 块内,被 Emacs 展开为 (eval-after-load 'consult ...),即延迟执行。
- consult-rg 运行前:consult 包未加载,
("es" gbk . gbk)未添加到process-coding-system-alist。bash.exe 路径不匹配任何条目,回退到default-process-coding-system=(utf-8 . utf-8)。color-rg 正常。 - consult-rg 运行后:consult 包被加载,
:config块执行,("es" gbk . gbk)被添加到process-coding-system-alist头部。bash.exe 路径匹配 “es” → 解码使用 GBK。rg 输出 UTF-8 被按 GBK 解码 → 乱码。
完整链路:
1. Emacs 启动 → consult 未加载 → "es" 条目不在 process-coding-system-alist 中
2. 运行 color-rg → compilation-start 使用 bash.exe → 无 alist 匹配
→ 回退 default-process-coding-system = utf-8 → 正确输出
3. 运行 consult-ripgrep → consult 加载 → :config 执行
→ (add-to-list 'process-coding-system-alist '("es" gbk . gbk)) 执行
4. 再次运行 color-rg → compilation-start 使用 bash.exe
→ "es" 正则匹配 "Files" 中的 "es" → coding = (gbk . gbk)
→ rg 的 UTF-8 输出按 GBK 解码 → 乱码
修复代码(原始,未整理)
修复1:init-completion.el line 123
将宽泛的正则 "es" 锚定为精确匹配程序名 es 或 es.exe:
| |
修复2:config.el line 225
同样修改:
| |
projectile-grep 乱码问题(后续追加)
问题
my/projectile-grep(init-completion.el line 90)搜索中文同样乱码。
排查
命令:
cd d:/xgzhang/projects/svn/Elafs/branches/asp/ && LANG=en_US.UTF-8 egrep -rinHI --exclude-dir=.idea --exclude-dir=.svn --color=always "领导" *
报错:
'LANG' ڲ ⲿ Ҳ ǿ еij
ļ
这个乱码本身就是 GBK 的 cmd.exe 错误信息("‘LANG’ 不是内部或外部命令…")被按 UTF-8 解码的结果。
原因分析
- Windows Emacs 上
shell-file-name默认为cmdproxy.exe(即 cmd.exe),不是 bash.exe LANG=en_US.UTF-8前缀语法在 cmd.exe 中无效(cmd.exe 不支持 POSIX 环境变量语法)egrep(来自 Git Bash/MSYS2)是 POSIX 程序,其输出编码由 MSYS2 locale 决定,不像 ripgrep 有自己的--encoding参数- 在中文 Windows 上,MSYS2 egrep 默认输出 GBK
process-coding-system-alist中[cC][mM][dD][pP][rR][oO][xX][yY]→(utf-8 . gbk-dos)意味着 cmdproxy 的输出按 UTF-8 解码- 原始命令中的
chcp 65001只影响 Windows 控制台 API,对使用 POSIX I/O 的 MSYS2 程序无效 - 结果:egrep 输出 GBK 字节 → Emacs 按 UTF-8 解码 → 乱码
修复3:init-completion.el my/projectile-grep 函数
| |
变更点:
- 移除
chcp 65001 >nul &&(只影响 Windows 控制台 API,对 MSYS2 egrep 无效) - 移除
LANG=en_US.UTF-8前缀(cmd.exe 不支持 POSIX 环境变量语法) - 添加
(coding-system-for-read 'chinese-gbk-dos)绑定,强制 Emacs 按 GBK 解码该 grep 进程的输出
涉及的关键文件
| 文件 | 行号 | 内容 |
|---|---|---|
lisp/init-basic.el | 68-74, 125-140 | process-coding-system-alist 初始化、语言环境设置 |
lisp/init-completion.el | 123 | 被修复的 ("es" gbk . gbk) 条目(延迟加载) |
lisp/init-completion.el | 90-107 | my/projectile-grep 函数 |
config.el | 225 | 重复的 ("es" gbk . gbk) 条目 |
elpa/color-rg/color-rg.el | 760-900 | color-rg-build-command / color-rg-search |
elpa/consult-20250908.1642/consult.el | 2449-2538 | consult–async-process |
核心教训
process-coding-system-alist正则在匹配时包括程序的完整路径,不仅仅是程序名(basename)。写正则时需要用\`` 和'` 锚定。use-package :config块中的代码是延迟执行的(eval-after-load),状态变化可能发生在任何时间点。- Windows 上
shell-file-name默认是cmdproxy.exe(cmd.exe),不是 bash.exe,即使系统安装了 Git Bash。 chcp 65001只影响 Windows 控制台 API(WriteConsole等),不影响通过管道(pipe)的 POSIX I/O。- MSYS2/Git Bash 的 GNU 工具使用 POSIX locale 决定输出编码,不受 Windows 控制台代码页影响。
coding-system-for-read是 Emacs 动态变量,可以在调用compilation-start/grep时动态绑定来覆盖process-coding-system-alist的解码设置。
- 原文作者:Ethan
- 原文链接:https://zhangxingong.top/post/emacs-consult-rg-color-rg-%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E4%BF%AE%E5%A4%8D/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。



