如何在emacs目录变量文件中访问当前目录的路径?

时间:2010-10-25 06:39:27

标签: emacs elisp

根据Emacs文档,Directory Variables适用于包含.dir-locals.el文件的目录下的所有文件。

如何在该文件中将变量设置为包含该文件的完整路径?例如:

((nil . ((indent-tabs-mode . t)
          (my-project-path **THIS_DIRECTORY**))))

7 个答案:

答案 0 :(得分:10)

我问自己同样的问题并在网上找不到解决方案,所以我认为这个答案可能有所帮助。实际上,事实证明我们可以重用dir-locals-find-file来获取包含.dir-locals.el文件的目录。所以这就是我找到的,例如,设置一个专用于整个目录的aspell个人词典:

((nil . ((eval . (setq ispell-personal-dictionary
                       (expand-file-name
                        ".aspell_words"
                        (file-name-directory
                         (let ((d (dir-locals-find-file ".")))
                           (if (stringp d) d (car d))))))))))

此外,似乎条目按照指定的顺序进行评估,因此以下代码应该起作用:

((nil . ((eval . (set (make-local-variable 'my-project-path)
                      (file-name-directory
                       (let ((d (dir-locals-find-file ".")))
                         (if (stringp d) d (car d))))))
         (eval . (message "Project directory set to `%s'." my-project-path)))))

Emacs会抱怨不安全的局部变量(由于eval构造),但仍可以永久标记它是安全的。

答案 1 :(得分:6)

我认为(file-name-directory (or load-file-name buffer-file-name))应该为您提供目录路径。

请参阅http://xahlee.org/emacs/elisp_idioms_batch.html

编辑:除非它不会,因为任何eval表达式都是在其变量被黑客攻击的缓冲区的上下文中计算的。

答案 2 :(得分:2)

如果它仍然很重要,对于OP或其他一些,我建议您创建一个函数来生成.dir-locals.el文件。然后人们可以写出类似的东西:

(let ((path default-directory)
      file)
  (setq file (format "%s/.dir-locals.el" path))
  (with-temp-buffer
    (insert (format "((nil . ((indent-tabs-mode . t)
          (my-project-path \"%s\"))))" path))
    (when (file-writable-p file)
      (write-region (point-min)
                    (point-max)
                    file))))

在项目主目录中执行。

答案 3 :(得分:1)

hack-local-variables是处理所有局部变量的主要函数,它调用hack-dir-local-variables来处理.dir-locals.el文件(或dir本地类变量,如果你不使用那个文件)。

建立目录的代码不是在它自己的函数中隔离的,所以我们必须将它复制到一个新函数中(这来自GNU Emacs 24.0.95.1):

(defun my-dir-locals-dir ()
  "Return the directory local variables directory.
Code taken from `hack-dir-local-variables'."
  (let ((variables-file (dir-locals-find-file (or (buffer-file-name) default-directory)))
        (dir-name nil))
    (cond
     ((stringp variables-file)
      (setq dir-name (file-name-directory variables-file)))
     ((consp variables-file)
      (setq dir-name (nth 0 variables-file))))
    dir-name))

答案 4 :(得分:1)

如果您正在使用* nix,则可以通过以下elisp代码获取工作目录,

(defun get-working-directory ()
    (getenv "PWD))

顺便说一句,我必须提到,(shell-command "pwd")将导致文件所在的目录(与您当前正在编辑的缓冲区相对应)。

答案 5 :(得分:1)

在我的情况下,我想找到一个与我当前工作目录相关的文件,并将.dir-locals.el文件检入根目录,因此文件“本地”为.dir -locals.el也是项目根目录的“本地”文件。

pajato0上面的答案适用于某些情况,但它也打破了其他模式(如magit)。我通过使用projectile包的projectile-project-root函数找到了我的基本路径,解决了这个问题:

((nil . ((eval . (setq cmake-ide-build-dir
                   (concat (projectile-project-root) "/build-make"))
         ))))

答案 6 :(得分:1)

我发现locate-dominating-file过程是随Emacs一起提供的,可用于检索已知文件的当前目录。下面的示例将guix-directory变量设置到包含.dir-locals.el文件的项目的最顶层目录。

((nil . ((eval . (setq guix-directory
                       (locate-dominating-file default-directory
                                               ".dir-locals.el"))))))

由于依赖eval,因此不是 safe .dir-locals.el设置,但可以完成工作。