Có cách nào để daisy chuỗi .dir-locals.el tập tin không?


15

Giả sử tôi có một thư mục với các tập tin này.

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

Khi tôi đi tạo một tệp /foo/bar/baz/, tôi muốn xâu chuỗi chúng lại với nhau để /foo/.dir-locals.eláp dụng trước, sau đó /foo/bar/.dir-locals.el, và sau đó, sau đó/foo/bar/baz/.dir-locals.el



Không có tùy chọn nào có thể làm điều đó (tôi đã xem xét mã khá chặt chẽ), nhưng nó sẽ (gần như chắc chắn là có thể) với một số mã bổ sung. Tôi cũng có một công dụng cho nó, vì vậy tôi có thể xem xét điều này ...
Constantine

Với elisp, tất cả mọi thứ đều có thể. :)
Eric Johnson

Câu trả lời:


7

Dựa trên câu trả lời ở đây , chúng tôi thực hiện điều này bằng cách khuyên bạn hack-dir-local-variablesnên tìm một thư mục và kiểm tra xem .dir-locals.eltệp đó có đọc được không. Nó sẽ tiếp tục đi lên cho đến khi tìm thấy một thư mục không thể đọc được .dir-locals.el.

Tùy thuộc vào giá trị của walk-dir-locals-upwardcác tập tin có thể được đọc từ thư mục hiện tại trở lên hoặc từ cuối cùng .dir-locals.elđược tìm thấy xuống. Xuống dưới là mặc định để các thư mục con có thể ghi đè cài đặt của cha mẹ chúng.

(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
        )))
  )

Điều này dường như mong đợi rằng mọi thư mục trong cây (lên đến một mức nào đó từ đường dẫn hiện tại) có một .dir-locals.el. Nó có hoạt động không nếu tôi có một cây thư mục a/b/cvà tồn tại a/.dir-locals.ela/b/c/.dir-locals.el, nhưng không a/b/.dir-locals.el(giả sử rằng tôi đang truy cập a/b/c/foo.elvà tôi muốn cài đặt a/.dir-locals.elđược áp dụng)?
Constantine

1
Vâng, đó là những gì tôi đang giả định. Các dir-loc mất tích trong a/b/phá vỡ chuỗi. Nó phải dừng ở đâu đó và nếu bạn muốn nó tiếp tục, bạn có thể thêm một tập tin dir-local trống.
erikstokes

3
BTW, tôi hoan nghênh một bản vá cho Emacs để hỗ trợ xâu chuỗi những người địa phương ra khỏi hộp.
Stefan

6

Đây là một cách khác nhau để làm điều này.

Tôi định nghĩa một hàm tạo ra danh sách tất cả các thư mục trong hệ thống phân cấp thư mục hiện tại.

(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) "" ()))

Một ví dụ là theo thứ tự:

(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")

Bây giờ tôi có thể thêm lời khuyên để hack-dir-local-variableslàm cho nó "giả vờ" rằng chúng tôi đang truy cập một tệp ở đầu cây, áp dụng cài đặt thư mục cục bộ, sau đó bước xuống một cấp, áp dụng lại cài đặt, v.v.

(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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.