.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



それを行うオプションはありません(コードをかなり詳しく調べました)が、余分なコードがあれ(ほぼ確実に)可能です。私はこのに見えるかもしれませんので、あまりにもそれのための使用を持っている...
コンスタンティン

elispを使用すると、すべてのことが可能になります。:)
エリックジョンソン14

回答:


7

ここでの回答に基づいて、hack-dir-local-variables1つのディレクトリを検索し、その.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/ca/.dir-locals.elありa/b/c/.dir-locals.el、が存在し、が存在しない場合は機能しますかa/b/.dir-locals.el(私は訪問a/b/c/foo.elしていて、設定をa/.dir-locals.el適用したいと仮定しています)?
コンスタンティン14

1
はい、それは私が仮定していることです。欠落しているdir-locals a/b/はチェーンを破壊します。どこかで停止する必要があり、続けたい場合は、空のdir-localsファイルを追加できます。
エリクスト14

3
ところで、私はEmacsが直接dir-localsをチェインすることをサポートするためのパッチを歓迎します。
ステファン

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で、ツリーの最上部にあるファイルにアクセスしていることを「ふりをする」ようにアドバイスを追加し、ディレクトリローカル設定を適用してから、1レベル下に移動し、設定を再度適用するなどのことができます。

(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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.