有没有办法以菊花链方式连接.dir-locals.el文件?


15

假设我有一个包含这些文件的目录。

/foo/bar/baz/.dir-locals.el
/foo/bar/.dir-locals.el
/foo/.dir-locals.el

当我要在中创建文件时/foo/bar/baz/,我想将它们以菊花链方式链接到一起,从而/foo/.dir-locals.el首先应用,然后再应用/foo/bar/.dir-locals.el,然后再应用。/foo/bar/baz/.dir-locals.el



没有选项可以做到这一点(我仔细地看了一下代码),但是应该(几乎可以肯定)有一些额外的代码。我也有用,所以我可能会研究一下...
Constantine

有了elisp,一切皆有可能。:)
埃里克·约翰逊

Answers:


7

根据此处的答案,我们建议hack-dir-local-variables您查找一个目录并加载该.dir-locals.el文件是否可读以进行检查。它将继续上升,直到找到不可读的目录.dir-locals.el

根据walk-dir-locals-upward文件的值,可以从当前目录向上或从最后.dir-locals.el找到的向下读取。默认为向下,以便子目录可以破坏其父级的设置。

(defvar walk-dir-locals-upward nil
  "If non-nil, evaluate .dir-locals.el files starting in the
  current directory and going up. Otherwise they will be
  evaluated from the top down to the current directory.")

(defadvice hack-dir-local-variables (around walk-dir-locals-file activate)
  (let* ((dir-locals-list (list dir-locals-file))
         (walk-dir-locals-file (first dir-locals-list)))
    (while (file-readable-p (concat "../" walk-dir-locals-file))
      (progn
        (setq walk-dir-locals-file (concat "../" walk-dir-locals-file))
        (add-to-list 'dir-locals-list walk-dir-locals-file
                     walk-dir-locals-upward)
        ))
    (dolist (file dir-locals-list)
      (let ((dir-locals-file (expand-file-name file)))
        (message dir-locals-file)
        ad-do-it
        )))
  )

这似乎期望树中的每个目录(从当前路径向上到某个级别)都有一个.dir-locals.el。如果我有一棵目录树a/b/c并且存在a/.dir-locals.ela/b/c/.dir-locals.el,但是没有a/b/.dir-locals.el(假设我正在访问a/b/c/foo.el并且我希望应用设置),它会起作用a/.dir-locals.el吗?
君士坦丁

1
是的,这就是我的假设。缺少的dir-locals a/b/中断了链接。它必须停在某个地方,如果您希望它继续下去,可以添加一个空的dir-locals文件。
erikstokes

3
顺便说一句,我很欢迎Emacs的补丁程序支持开箱即用地链接目录本地。
Stefan 2015年

6

这是一种不同的方法。

我定义了一个函数,该函数生成当前目录层次结构中所有目录的列表。

(defun file-name-directory-nesting-helper (name previous-name accumulator)
  (if (string= name previous-name)
      accumulator                       ; stop when names stop changing (at the top)
      (file-name-directory-nesting-helper
       (directory-file-name (file-name-directory name))
       name
       (cons name accumulator))))

(defun file-name-directory-nesting (name)
  (file-name-directory-nesting-helper (expand-file-name name) "" ()))

一个例子如下:

(file-name-directory-nesting "/foo/bar/baz/quux/foo.el")
;; => ("/" "/foo" "/foo/bar" "/foo/bar/baz" "/foo/bar/baz/quux" "/foo/bar/baz/quux/foo.el")

现在,我可以添加建议以hack-dir-local-variables使其“假装”我们正在树的顶部访问文件,应用目录本地设置,然后下一级,再次应用设置,依此类推。

(defun hack-dir-local-variables-chained-advice (orig)
  "Apply dir-local settings from the whole directory hierarchy,
from the top down."
  (let ((original-buffer-file-name (buffer-file-name))
        (nesting (file-name-directory-nesting (or (buffer-file-name)
                                                  default-directory))))
    (unwind-protect
        (dolist (name nesting)
          ;; make it look like we're in a directory higher up in the
          ;; hierarchy; note that the file we're "visiting" does not
          ;; have to exist
          (setq buffer-file-name (expand-file-name "ignored" name))
          (funcall orig))
      ;; cleanup
      (setq buffer-file-name original-buffer-file-name))))

(advice-add 'hack-dir-local-variables :around
            #'hack-dir-local-variables-chained-advice)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.