如何定位并解决Emacs helm-ag的中文搜索问题 (新手向)

说明

我的Emacs一直无法支持用helm-ag搜索中文。在用Emacs做主力编辑时,要用到ag搜索时,只能在cygwin下进行。 一年前就想把印象笔记迁到org了,但快速的中文搜索是必要的,也因为这个原因不能迁。

直到最近看到这样的软文,太不严谨了,难道要学锤子…

而且前段时间,某版本的印象笔记,竟然有无法同步的bug,官方给的解决方案是手工降版本。 不靠谱啊… 是时候加速逃跑计划了,希望能在国内版代码被改得越来越糟之前。

中文搜索,是个劝退力相当强的问题。这个问题会出现在新手阶段,一般能搜索到的解决办法都是:尝试改10几个encoding相关的函数和变量。在过去1年里,自己也常常突然起兴,改一组encoding试试,然而都GG了。好在我还没有被劝退… 昨天又折腾了一次,总算是解决了这个问题。

下面的内容,会对以下问题有所帮助:

  • 任何系统的任何语言下(Windows/OSx/Linux/Android…)使用helm-ag搜索中文,无结果或显示乱码
  • 使用helm-ag搜索时,出现emacs卡死

我自己目前只在Windows7上折腾好了。其他系统的思路是一样的。

误区: helm-ag的搜索问题,与shell的选择和设置有关

打开helm-ag.el源码,能找到调用ag.exe的语句:

(apply #'start-file-process "helm-do-ag" nil cmd-args)

Emacs提供了几个起子进程的函数:

  • shell-command-to-string
  • start-process-shell-command
  • start-process
  • start-file-process
  • call-process

这些函数名字里,带有“shell”的,是与当前设置的shell有关的;而其他的都和shell没任何关系。

helm-ag用的start-file-process,和shell无关。

如果你和我一样,在cmd cmdproxy zsh bash 之间换了又换,那现在可以停下来了,往下看。

继续往下看,你会发现helm-ag的编码问题,只与一个encoding配置有关…

ag rg pt 的选择

在windows下,有ag ag(cygwin) rg pt,这几个选择。

从大家的评价看,Windows下用rg是最好的,而用cygwin的ag,我自己测下来一定会卡很久。

用Windows的同学,可以去下载rg.exe,然后加入PATH了。如果用的其他系统,也建议装下rg,后续说明都是以rg为例。

快速修正编码设置

M-x list-buffers 切换到 scratch

M-x emacs-elisp-mode 启用elisp mode

写这么一行:

(call-process "rg" nil t nil "中文")

然后在你的HOME目录下,放一个带有"中文"两个字的文本文件。

把光标放在这行,按M-x lisp-state-eval-sexp-end-of-line

可以看到在这行的后面,或者没有追加任何搜索结果,或者追加了错误信息,或者搜索结果中应该是中文的,显示为了乱码。

再写这么一行

(modify-coding-system-alist 'process "rg" '(utf-8 . chinese-gbk-dos))

其中:

  • rg 表示只修改"rg"进程的编码
  • '(utf-8 . chinese-gbk-dos)里的chinese-gbk-dos表示: 从Emacs向rg进程提供文本参数时,编码为gbk
  • '(utf-8 . chinese-gbk-dos)里的utf-8表示: 从rg获取进程输出到Emacs时,解码为utf-8

为什么要这么设置呢? call-process 函数不通过shell启动进程,而是由操作系统直接启动。而Windows7中文版本的系统编码为gbk。

… 这里的表述不够准确,但且先这么理解

而Emacs内处理所有文本,都是utf-8的

通过这行配置,即可解决Emacs和rg之间对接时的编码问题了

光标移动到这行,M-x lisp-state-eval-sexp-end-of-line执行一下

而后再回头执行下call-process那一行,顺利的话,就能看到中文搜索结果被追加且正常显示了。

如果还是不行,请把chinese-gbk-dos换成你的系统的默认编码

最终配置

请把下面两行加入 **dotspacemacs/user-config()**函数:

(modify-coding-system-alist 'process "rg" '(utf-8 . chinese-gbk-dos))
(custom-set-variables '(helm-ag-base-command "rg --vimgrep --no-heading --smart-case"))

加第二行是因为,最近发现修改了dotspacemacs-search-tools '("rg")不起作用,helm-ag时,还是用的ag,而非rg。

顺带一提

  • 这几个都是一样的,互为本体和别名的关系 chinese-gbk-dos gbk-dos windows-cp936-dos
  • 可随时用M-x describe-current-coding-system,翻到Process I/O部分,来检查对rg进程的编码设置

遗留问题

helm-ag的搜索结果里,多一行: .\nul: 函数不正确。 (os error 1)

但是没什么影响,如果有人知道的话,请解答下~

7 个赞

虽然rg对windows有utf-8的支持,但是我还是使用ag, 感觉上比rg快。

的确在windows上使用ag时,存在想要退却的gbk编码问题,因此很早我就使用了一个ag的windows改进版本, 出自一个年长的国外计算机老师之手。

使用这个版本的ag的时候,需要在使用 helm-ag 前改变 current-language-environment 为gbk,我的设置为:

(defun my/helm-ag-gbk (&rest args)
  (set-terminal-coding-system nil)
  (set-keyboard-coding-system nil)
  (set-language-environment 'chinese-gbk))

(advice-add 'helm-do-ag :before #'my/helm-ag-gbk)

但是我没有尝试 使用进程编码传输的转换,我相信如果如楼主所言helm-ag调用ag的方式是直接的非shell的子进 程,那么应该能行。

另外这个版本的ag,在helm-ag上有一个bug,就是无法使用空格做空格的正则参数,只能用其他正则空白符表达式 代替,空格对它来说好像是分割符。

果然大家的配置都不一样…

我在debain上用,ag,rg搜中文都没有问题的。可能是我直接安装的就是中文版的debain的原因?

刚刚似乎发现spacemacs中用rg的一个bug,如果只搜索中文单字的话,就会显示Display not ready,非要是两个字以上才有正常的搜索结果。

用ag就没有这个问题。

又试验了一下,这应该不是bug,只不过rg的匹配规则如此

rg不是号称自己是最快的searcher……

写函数名,不要直接写spacemacs的按键啊……即使函数是spacemacs专属,非spacemacs用户也能看名字知道大概的意思然后用别的函数替代。虽然对帖子整体影响不太大。

我在 spacemacs 里面只启用 ivy layer,这套设置不起作用

是吧 我目前用helm,ivy还没机会了解 XD

需要直接call rg,如果用compile这类先调用cmdproxy执行shell command就不行了,需要临时改cmdproxy的coding-alist

我的情况是 (setq helm-ag-base-command “ag --nocolor --nogroup --ignore-case”) 把这句–ignore-case去掉就可以搜索到中文了。