如何让emacs-jedi使用特定于项目的虚拟环境

13
我希望emacs-jedi能够检测到我正在编辑不同项目的文件,并在可用情况下使用相应的虚拟环境。按照惯例,我的虚拟环境与我的项目名称相同,位于$HOME/.virtualenvs/
我找到了kenobi.el,但它假设virtualenvs在项目根目录的bin目录中找到。它还有一些其他我不需要的功能。
受 kenobi.el 的启发,我为 jedi 写了以下初始化代码。它工作得很好,但并非完美。
如果我从我的项目导入库,并且A导入。我可以跳转到由A定义的定义,但是一旦进入,我就无法继续跳转到B的定义。
我的初始化代码:
(defun project-directory (buffer-name)
  (let ((git-dir (file-name-directory buffer-name)))
    (while (and (not (file-exists-p (concat git-dir ".git")))
                git-dir)
      (setq git-dir
            (if (equal git-dir "/")
                nil
              (file-name-directory (directory-file-name git-dir)))))
    git-dir))

(defun project-name (buffer-name)
  (let ((git-dir (project-directory buffer-name)))
    (if git-dir
        (file-name-nondirectory
         (directory-file-name git-dir))
      nil)))

(defun virtualenv-directory (buffer-name)
  (let ((venv-dir (expand-file-name
                   (concat "~/.virtualenvs/" (project-name buffer-name)))))
    (if (and venv-dir (file-exists-p venv-dir))
        venv-dir
      nil)))    

(defun jedi-setup-args ()
  (let ((venv-dir (virtualenv-directory buffer-file-name)))
    (when venv-dir
      (set (make-local-variable 'jedi:server-args) (list "--virtual-env" venv-dir)))))

(setq jedi:setup-keys t)
(setq jedi:complete-on-dot t)
(add-hook 'python-mode-hook 'jedi-setup-args)
(add-hook 'python-mode-hook 'jedi:setup)

我初始化jedi的方式有什么问题?

1个回答

14
我现在已经采用了一个解决方案,使用virtualenvwrapper ELPA包来激活虚拟环境,从而使emacs-jedi能够从VIRTUAL_ENV环境变量中获取虚拟环境路径。以下是完整的、可工作的emacs-jedi初始化代码:
(defun project-directory (buffer-name)
  "Return the root directory of the project that contain the
given BUFFER-NAME. Any directory with a .git or .jedi file/directory
is considered to be a project root."
  (interactive)
  (let ((root-dir (file-name-directory buffer-name)))
    (while (and root-dir
                (not (file-exists-p (concat root-dir ".git")))
                (not (file-exists-p (concat root-dir ".jedi"))))
      (setq root-dir
            (if (equal root-dir "/")
                nil
              (file-name-directory (directory-file-name root-dir)))))
    root-dir))

(defun project-name (buffer-name)
  "Return the name of the project that contain the given BUFFER-NAME."
  (let ((root-dir (project-directory buffer-name)))
    (if root-dir
        (file-name-nondirectory
         (directory-file-name root-dir))
      nil)))

(defun jedi-setup-venv ()
  "Activates the virtualenv of the current buffer."
  (let ((project-name (project-name buffer-file-name)))
    (when project-name (venv-workon project-name))))

(setq jedi:setup-keys t)
(setq jedi:complete-on-dot t)
(add-hook 'python-mode-hook 'jedi-setup-venv)
(add-hook 'python-mode-hook 'jedi:setup)

请记住,您必须首先安装virtualenvwrapper。

阅读virtualenvwrapper文档以了解自动激活项目虚拟环境的另一种方法。简而言之,您可以在项目的根目录中创建一个.dir-locals.el文件,并填写以下内容:

((python-mode . ((project-venv-name . "myproject-env"))))

"myproject-env"更改为您的虚拟环境名称,并使用python-mode钩子激活虚拟环境:
(add-hook 'python-mode-hook (lambda ()
                              (hack-local-variables)
                              (venv-workon project-venv-name)))
(add-hook 'python-mode-hook 'jedi:setup)

这里还有一个不错的包auto-virtualenvwrapper: https://github.com/robert-zaremba/auto-virtualenvwrapper.el。我认为你应该试一下。 - pingz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接