Windows 下 emacs 的 M-!
,call-process
,等的 encoding 问题
不想读系列:开启 UTF-8 Beta 保平安
前言
最近打算把浏览器的书签从浏览器中迁移出来,于是打算转用 buku。Emacs 有一个包 ebuku ,提供了一个前端。
但是在实际使用的时候,在 Windows 里会有编码的问题。具体体现为类似乱码
系统状况
我的系统是英文为主要,然后为非 Unicode 的程序开启了中文编码(GBK)。这个设置应该是为了兼容中英文比较普遍的设置了(如果不设置中文编码,有时候安装软件,或者解压文件的时候会有乱码)
Ebuku 运作原理
Ebuku 是一个比较简易的包,通过 regex 来提取 buku 运行的结果。但这也是问题的源头。
折腾编码
在 Windows 当中,编码的问题由来已久,从最早的完全不支持 utf,到使用自己的 utf-16le。 在测试我的 Emacs 的编码的时候,发现调用 call-process
或 M-!
的时候,编码环境是 gbk (我是通过一个“笨”办法,跑 python -c "import sys;print(sys.stdout.encoding)"
来确认的,应该有更好的办法)
在知道编码是 gbk 之后,事情就好办了,可以通过设置一些参数来让 emacs 用合适的编码来处理 buku 的输出。
(set-default 'process-coding-system-alist
'(("[cC][mM][dD][pP][rR][oO][xX][yY]" gbk-dos . gbk-dos)))
这段设置可以让 emacs 成功识别编码,在这个环境下,如果输出有中文的话,可以成功读取成正确的内容。
Buku gbk 输出乱码
理论上,上一步问题应该已经解决了,可惜的是,在运行 ebuku 的时候还是会提示出错。在手动跑了 ebuku 中的命令之后,发现虽然大多数的输出是没有问题的,但是在有的字符的时候还是会出先乱码
这里我也不知道具体的原因,不过我怀疑罪魁祸首还是 gbk 的问题。顾又开始在网上查阅各种有关 emacs 编码的问题。最后在一篇 reddit 的帖子中看到有一个用户提到可以通过设置本文最开始提到的 Beta UTF-8 支持来解决这一问题。
在设置了这个选项,并且按提示重启电脑之后,终于可以在 M-!
中看到到编码是 UTF-8 了!折腾终于结束了
其他杂记
- 为何不用 Linux/Mac,我也想,但必须在 windows 环境下干一些事情(玩游戏),同时也想用 Emacs
2 个赞
设置Windows编码为utf-8时在部分软件里面会出现兼容性问题
有 Locale Emulator 做最后保底 (捂脸)
emacs在windows上运行程序有几种,很多是通过cmdproxy进程代理的,所以设置cmdproxy有效。像consult-ripgreg异步调用rg就不需要cmdproxy,只需要设置
(add-to-list 'process-coding-system-alist
'("[rR][gG]" . (utf-8 . gbk-dos)))
像projectile的fd调用就是cmdproxy,我一般通过advise临时设置process-coding-system-alist
,而不是像那样set-default 'process-coding-system-alist
,代码如下:
(defadvice projectile-files-via-ext-command (around my-projectile-files-via-ext-command activate)
(let ((cmdproxy-old-encoding (cdr (assoc "[cC][mM][dD][pP][rR][oO][xX][yY]" process-coding-system-alist))))
(modify-coding-system-alist 'process "[cC][mM][dD][pP][rR][oO][xX][yY]" '(utf-8 . gbk-dos))
ad-do-it
(modify-coding-system-alist 'process "[cC][mM][dD][pP][rR][oO][xX][yY]" cmdproxy-old-encoding)
))
确定Buku是如何调用的(可以用process explorer查看进程树),然后对应设置进程就行了。假设Buku是cmdproxy代理,并且输出utf-8编码,那么按上面你的代码这样设置可能有效:
(set-default 'process-coding-system-alist
'(("[cC][mM][dD][pP][rR][oO][xX][yY]" utf-8 . gbk-dos)))
不过你这样是全局设置cmdproxy了,最好是找到调用Buku的elisp代码,然后advise临时设置编码。
1 个赞
ebuku 是使用 call-process
来调用 buku 的,我推测和实验的结果 cmdproxy 是生效的。当我当时最后遇到的问题是在 (gbk-dos . gbk-dos)
的情况下 buku 自己的输出会有部分是乱码(90%的中文没问题,但可能我的书签中有其他的文字,比如有个标题中有德文字符)。这个没能找到根本原因,只能推测是在 windows 中 python(buku 是个 python 的包)encoding 处理的兼容性问题。
如果在 powershell 或者 cmd 中直接运行 buku 的话,都是没有这个问题的(当时忘记截图了…)不过我在验证 encoding 时(没设置 utf-8 beta时), powershell 和 cmd 都是使用 utf-8 作为输出。