Emacs as python IDE
最近 python 写的比较多,比较了几个编辑器,最后还是留下了 emacs。
主要比较了 emacs 和 pycharm。pycharm 绝对是一个很强的 IDE,几乎可以补全任何东西,写代码各种提示。比如 Django 里面定义一个 model User 之后,就可以 User.
之后提示 objects
,这个是依据 metaclass 来补全的。另外还有比如写 User.objects.get(|)
的时候,光标在竖线那个位置,会提示 User
的字段,这个相当好用。这两个只是皮毛,实在是太好用了。
但是为什么还要用 emacs 呢?emacs 的编辑器功能太好用了。比如 <
到页首, >
到页尾, C-x b
切换 buffer,还有切换 frame,等等快捷键非常舒服,完全不用鼠标。不过也可能是我习惯了 emacs 的快捷键了。在 pycharm 里面时不时就不行,比如选择一段文字,纯键盘需要按 ->
配合才可以,那还不如用鼠标算了。
其实如果一上手就用 pycharm,那绝对会觉得很爽。
emacs 写 python 在原生的 python-mode
基础上有两个好用的选择,一个是 anaconda-mode,一个是 elpy。 anaconda-mode
相对来说比较简陋一点,但是补全什么的没问题,缺少重构功能。两个的工作模式都是会启动一个补全用的进程,然后通过 lisp 和这个进程交互获取补全信息。
anaconda-mode 遇到的问题和解决
anaconda-mode
我遇到一个问题,为了下载 emacs 的 package 方便,我设置了代理,这个代理导致 anaconda-mode
和补全进程交互的时候,连接不能断开,就会不停的新建连接,一会就打开文件数满了,可以参观这个 issue。主要是设置了 no_proxy
解决。
(setq url-proxy-services
'(("no_proxy" . "^\\(127.0.0.1\\|localhost\\|10.*\\)")
("http" . "127.0.0.1:6152")
("https" . "127.0.0.1:6152")))
auto-virtualenv
我的 python 项目使用了 virtualenv
,会在项目目录下面建一个 .venv
的目录,把虚拟环境放进去。 anaconda-mode
提供了 pythonic-activate
命令, elpy
提供了 pyvenv-activate
来切换环境。但是每次打开项目都需要搞一下就挺恶心了。
然后找到了 auto-virtualenv 这个工具。安装之后,他会自动查找你的项目里面的可能的虚拟环境。项目根目录识别是通过 .git
, .hg
等一些逻辑来判定的,具体可以看代码。然后虚拟环境识别是通过根目录下面的 .python-version
.venv
等来识别的。
我的项目是建了一个 .venv
目录,所以每次打开一个 python 文件,会自动配置好 virtualenv 的环境,这样 elpy
在 django 自带的 model 上面也可以查找 defination。
(use-package auto-virtualenv
:ensure t
:config
(add-hook 'python-mode-hook 'auto-virtualenv-set-virtualenv)
)
elpy
elpy
其实没有什么好配置的,主要注意的是,因为我们用了 virtualenv 环境,所以需要他依赖的包都装在 .venv
环境或者装在 python 自己的目录下面应该都可以。启动 emacs 之后可以使用 M-x elpy-config
看看还有什么没配置好。
(use-package elpy
:ensure t
:init
(setq elpy-rpc-backend "jedi")
(elpy-enable)
:config
(add-hook 'python-mode-hook 'elpy-mode)
(with-eval-after-load 'elpy
(add-hook 'elpy-mode-hook 'elpy-use-ipython))
:bind (("M-*" . pop-tag-mark))
)
elpy-rpc-backend
有两个选择,一个 jedi
,一个 rope
,我试了感觉区别不大,另外 rope 感觉要死了。所以我用了 jedi
。
flycheck
flycheck 可以配合 flake8
实时显示出来你的代码有不符合 flake8 要求的地方,很方便。这个工具我也遇到一个坑 issue,有兴趣可以看看。主要原因是 flycheck 是使用 flake8 < xxx.py
这种方式检查的,而这种方式下 flake8 不会考虑文件头部的 coding
设置,来识别文件编码,而是根据 LC_CTYPE
环境变量来的,所以只要正确设置这个变量就可以了。 issue 里面提到的设置 emacs 的编码屁用么有的。
flycheck 可以配合 flake8 和 pylint 来做 python 代码的检查,如果装了前者,就不会考虑后者了。我试过 pylint,这货默认要求有点高,比如 class 和 method 没有 doc string 也会提示,代码一堆问题,我就赶紧换掉了。。。
python outline
好处是打开 python 文件的时候,会把代码都折叠起来,按照需要你自己打开就好。elpa 里面没有,网上搜到的。
(use-package python-magic
:ensure outline-magic
:config
(add-hook 'python-mode-hook 'my-python-outline-hook)
(add-hook 'python-mode-hook
(lambda ()
(setq outline-regexp "def\\|class ")))
)
indent-tools
这个工具是用来锁进 python 代码和浏览代码用的。搜一下有动图,看看就知道了。
(use-package indent-tools
:ensure t
:init
(add-hook 'python-mode-hook
(lambda () (define-key python-mode-map (kbd "C-c i") 'indent-tools-hydra/body))
)
)
yasnippet 和 company
elpy 是使用这两个补全的。有几个有用的配置, C-s
那个,可以在补全候选菜单出来的时候,用关键词过滤结果。
我没搞定在 company 里面直接显示出来 yasnippet 可用的 snippet,只好设置了一个快捷键 C-c y
来提示。可以提示出来一大堆。比如我经常写错的 -*- coding:utf8 -*-
有一个 snippet 叫做 utf8
,直接输入之后 tab 就可以了。
(use-package company
:ensure t
:init
(setq company-minimum-prefix-length 2)
(setq company-dabbrev-ignore-case t)
:config
(add-hook 'after-init-hook 'global-company-mode)
(define-key company-active-map (kbd "C-n") #'company-select-next)
(define-key company-active-map (kbd "C-p") #'company-select-previous)
(define-key company-active-map (kbd "C-s") #'company-filter-candidates)
(global-set-key (kbd "C-c y") 'company-yasnippet)
)