emacs在windows上无法使用term的bug的原理分析

这个老哥提到了这个问题 关于cmdproxy的优化和magit的优化 - #4,来自 Shynur
我本地试了下,确实也是这样。
正好在看emacs源码,就分析看看。
先是猜测term应该也要启动程序,所以直接在调用 CreateProcess 的地方打断点(注意在w32proc.c里面是直接用的CreateProcessA)

但是奇怪的是只断下来一次,执行了这个命令

"c:\\msys64\\usr\\bin\\bash.exe -c \"case $BASH_VERSION in [0123].*|4.[0123].*) exit 43;; esac\""

只是判断了bash的版本,而且第二次就没有触发了

翻了下emacs的文档,在process那一节提到emacs只有三个原语(也就是用c写的执行进程的函数)

call-process
call-process-region
make-process

emacs源码里面的原语都是 DEFUN这种宏开头,于是下断。这次断下来了 这里可以这样把Lisp_Object对象转成字符串显示

XSTRING(program).u.s.data

这里可以看到执行了/bin/sh
这在msys2环境外执行这个命令肯定会失败。
C-h f term看了下,term 的源码在term.el中
搜索可以看到如下的内容
start-process就是包装了make-process 这里可以看到她的逻辑,如果是安卓系统,就执行/system/bin/sh,否则执行/bin/sh
破案了,如果不写死,去获取bash的路径(把msys2加到环境变量里)。获取到 C:\msys64\usr\bin\bash.EXE再去执行的话应该就没问题。

5 个赞