问题已经解决,不过或许有更好的解决方案。
我在写这个提问的过程中,自己慢慢理清了思路,最终比较丑陋的解决了问题。但是已经写了那么多了,不想删掉。我想,分享一下思考、疑惑的过程应该也是有价值的。
我在终端里能正常启动,lsp-mode跟lsp-ui。但是在GUI下就是不行!我想这应该是环境变量有问题,but我把终端里的所有环境变量都setenv到emacs里,还是不行。
下面是报错信息,这个报错信息在我刚装lsp-python-mode的时候出现过。那时是在终端里操作的,依然不错的原因是pyls没有安装。现在在GUI里,我执行(shell-command-to-string “which pyls”) --> /usr/local/bin/pyls,说明不是找不到pyls的缘故(或者这不能说明什么,ls-mode用的是另一种方式启动pyls的?)
Error running timer ‘lsp-ui-sideline--run’: (wrong-type-argument hash-table-p nil) [2 times]
Error in post-command-hook (lsp-ui-doc--make-request): (error "Buffer models.py has no process")
Error running timer ‘lsp-ui-sideline--run’: (wrong-type-argument hash-table-p nil) [8 times]
也许真的是启动方式不一样,我立刻想到了call-process,实验了一下,果然:
(call-process "which"
nil t "*scratch*"
"pyls") ; --> /usr/local/bin
(call-process "pyls"
nil t "*scratch*"
"-h") ; --> 报错,No such file or directory "pyls"
(shell-command-to-string "which pyls") ; --> /usr/local/bin
(shell-command-to-string "pyls -h") ; --> 正常执行,打印了帮助信息
我很好奇为什么它能which pyls
出来,却不能执行pyls
,难道call-process不走环境变量那一套?
突然明白了什么,`PATH环境变量是给进程用来寻找cmd的,不是用来定位要启动的进程的。不知道这样理解是否正确。
然后我去注释掉(require 'lap-python-mode),自己写了那个define,cmd指定为pyls的绝对路径:
(lsp-define-stdio-client lsp-python "python"
(lsp-make-traverser #'(lambda (dir)
(when (directory-files dir nil ".git") ;hardcode,只有项目root目录才可以是python root
(directory-files
dir
nil
"\\(__init__\\|setup\\)\\.py"))))
'("/usr/local/bin/pyls"))
然后,这样就work了!但是是否有更好的解决方案?
我感觉这应该算是lsp-mode的坑,内部去执行一遍(shell-comamnd-to-string (format “which %s” cmd))来获取cmd的path,再用这个path去调用call-process是不是会更好一些?
另外我还是无法理解,如果环境变量不是关键因素,那么为什么终端里启动的emacs能辨析pyls
而GUI的却不行?
我的意思是终端里的emacs为什么可以直接(call-process "pyls"... ...)
?难道它不需要指定绝对路径吗?