【问题标题】:dir-locals.el settings not applied to some variablesdir-locals.el 设置未应用于某些变量
【发布时间】:2019-08-18 18:17:39
【问题描述】:

我想使用我的 .dir-locals.el 在项目上设置 virtualenv 名称。该变量已设置,但在用作其他连接变量中的参数时不被视为。

我尝试将 .dir-locals.el 文件添加到 python 项目。在其中,我为这个特定项目设置了 virtualenv 根名称。之后我启动 Emacs,打开一个 .py 文件检查是否所有需要的变量都用 virtualenv 名称进行了更改。

我的 emacs 配置中关于 python-mode 的部分

;;; Python mode

(require 'python)
(ensure-package 'python-environment)
(require 'python-environment)
(ensure-package 'python-mode)
(require 'python-mode)
;;; dash used for pip-requirements
(ensure-package 'dash)
(require 'dash)
(require 'pip-requirements)
(require 'jedi-core)
(require 'company-jedi)


(defun init-python-mode()
  (setq-local tab-width 4)
  (setq-local indent-tabs-mode nil)
  (set (make-local-variable 'company-backends)
       '((company-jedi company-dabbrev-code)
         company-capf company-files))
  (setq python-environment-directory (expand-file-name "~/.virtualenvs")
      python-indent-guess-indent-offset nil
      python-indent-offset 4
      jedi:complete-on-dot t
      jedi:use-shortcuts t
      jedi:tooltip-method nil
      jedi:get-in-function-call-delay 0
      python-shell-interpreter (concat python-environment-directory
                                       "/" python-environment-default-root-name
                                       "/bin" "/python")
      jedi:server-command (list (concat python-environment-directory
                                        "/" python-environment-default-root-name
                                        "/bin" "/jediepcserver"))
      python-shell-interpreter (concat python-environment-directory
                                       "/" python-environment-default-root-name
                                       "/bin" "/python")
      flycheck-python-pylint-executable (concat python-environment-directory
                                                "/" python-environment-default-root-name
                                                "/bin" "/pylint")
      flycheck-python-flake8-executable (concat python-environment-directory
                                                "/" python-environment-default-root-name
                                                "/bin" "/flake8")
      flycheck-python-pycompile-executable (concat python-environment-directory
                                                   "/" python-environment-default-root-name
                                                   "/bin" "/python")
      )
  (flycheck-mode t)
)

(defun after-init-python-mode()
  (eldoc-mode -1)
  )

(define-key python-mode-map (kbd "C-c C-k") #'comment-dwim)

(add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode))

(add-hook 'python-mode-hook #'init-python-mode)
(add-hook 'python-mode-hook #'jedi:setup)
(add-hook 'python-mode-hook #'after-init-python-mode)

项目的 .dir-locals.el 文件

;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")

((python-mode . ((python-environment-default-root-name . "abc")
         )))

Emacs 似乎对 .dir-locals.el 变量做出反应,我确认这些变量在启动时是安全的。之后,通过执行:'describe-variable python-environment-default-root-name' 我得到这个:

python-environment-default-root-name is a variable defined in ‘python-environment.el’.
Its value is "abc"
Original value was "default"
Local in buffer setup.py; global value is "default"

  This variable’s value is directory-local, set by the file
  ‘/home/mkj/dev/adm/.dir-locals.el’.

...这是预期的。

当执行:'describe-variable jedi:server-command'、'describe-variable python-shell-interpreter',以及使用 python-environment-default-root-name 的其他变量时,我得到这个:

jedi:server-command is a variable defined in ‘jedi-core.el’.
Its value is ("/home/mkj/.virtualenvs/default/bin/jediepcserver")

  This variable may be risky if used as a file-local variable.
python-shell-interpreter is a variable defined in ‘python.el’.
Its value is "/home/mkj/.virtualenvs/default/bin/python"
Original value was "python"

在我看来,使用 python-environment-default-root-name 的变量名的 setq 仅在设置默认值并且 .dir-locals.el 值被忽略或设置太晚时设置一次。

这里是否存在竞争条件,或者这只是为 python 模式设置基于 virtualenv 的变量的错误方法?

【问题讨论】:

    标签: python emacs virtualenv pyenv


    【解决方案1】:

    您可以在您的钩子中添加对hack-local-variables 的调用,以使 dir-locals 可用。通常,只有mode 局部变量会在你的钩子之前设置,通过调用(hack-local-variables t)。与python-mode、你的钩子和hack-local-variables 相关的调用通常看起来像,

    1 -> (normal-mode t)
    | 2 -> (hack-local-variables t)
    | 2 <- hack-local-variables: nil
    | 2 -> (python-mode)
    | | 3 -> (my-python-hook)
    | | 3 <- my-python-hook: ("~/.virtualenvs/default/bin/jediepcserver")
    | | 3 -> (hack-local-variables no-mode) ;; you want this called prior to your hook
    | | 3 <- hack-local-variables: nil
    | 2 <- python-mode: nil
    1 <- normal-mode: t
    

    所以,你可以修改你的钩子,

    (defun my-python-hook ()
      (hack-local-variables)
      ;; ...
      )
    

    不过,这似乎不是一个好的解决方案。我不使用 virtualenv,但似乎 python-environment-virtualenv 在这里是相关的。

    【讨论】:

    • 我不想使用 hack-local-variables :-)
    • 我不确定为什么使用“python-environment-virtualenv”会解决很多问题......例如,它似乎不会影响 flycheck 如何定位其检查程序。跨度>
    • 你为什么不想使用它?这就是 dir-locals 的读取方式...
    • 就像我说的,我不使用 virtualenv 也没有研究细节,但大多数版本管理器都有一种机制来关联不依赖于 emacs hack 的版本
    【解决方案2】:

    我发现 elpy 更适合此目的。它似乎可以无缝地更改公司后端、python 解释器、flycheck 等的变量,而无需更改 pyvenv-workon 变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      • 2019-08-07
      • 1970-01-01
      • 2020-12-26
      • 2021-08-30
      • 2019-11-19
      相关资源
      最近更新 更多