Emacs 的 lsp-mode
是利用 Language Server Protocol (LSP) 來支援程式語言的編輯,LSP 一開始是為了 VS Code 開發的,可以把對語言的編輯支援與 IDE/editor 脫勾,常常是孤兒的 Emacs 就比較可以跟上時代的發展。但,慣用的 palantir/python-language-server
(pyls) 在搭配 Python 幾乎一定會使用的 virtualenv
時,還是會有認不出虛擬環境裡模組的問題,如果再加上 pyenv
之類的,就還需要考慮不同 Python 版本,事情又更麻煩。以下是幾種解決方案:
每個虛擬環境都裝一套
這需要搭配 add-dir-local-variable
使用,在專案目錄底下新增一個 dir local variable pyvenv-activate
指向虛擬環境的絕對路徑,然後只要在這個環境下安裝 pyls 就可以了。這是個非常穩當的方法,所有基於虛擬環境的應用例如 pipenv
之類的也都適用。
缺點是,整套 pyls 也佔不少空間,每個專案底下都做一次很麻煩,要升級還得各自升級。
自己寫個 pyls wrapper
這算是前面方法的變體。先在自己環境裡裝一套 pyls,例如我習慣裝在 homedir 底下,那就是
1 | python3 -m pip install --user 'python-language-server[all]' |
這樣只要在設定環境時,用 virtualenv --system-site-packages
或者像我是用 pipenv
那就是 pipenv install --site-packages
就可以一併帶入到虛擬環境裡面。但這方法有個問題:帶入的模組是不會在虛擬環境裡新增執行檔的,也就是說 Emacs 執行 pyls
這命令時,會用到虛擬環境「外面」的執行檔,這就會出錯了。解決方法是要繞一圈,在虛擬環境裡以 python -m pyls
的方式執行。
但問題又來了:如果直接把 lsp-pyls-server-command
這變數改掉,lsp-pyls.el
的寫法是把整個值當成命令名稱來用,但系統裡面當然不該有個名稱叫做 python -m pyls
的執行檔。所以可以自己寫個 pyls.sh
裡面就寫 python -m pyls
然後把 lsp-pyls-server-command
改成 pyls.sh
就行了。這方法一樣要仰賴在每個專案正確設定 pyvenv-activate
. 而我是慣用 pipenv
,所以只要寫成這樣
1 |
|
如此不特別設定 pyvenv-activate
也一樣會動。