.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

생략하면 모든 것이 가능합니다. :)
Eric Johnson

답변:


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.el하고 a/b/c/.dir-locals.el있지만은 a/b/.dir-locals.el(I 방문하고있어 가정 a/b/c/foo.el내가에서 설정을 원하는 a/.dir-locals.el적용하는)을?
Constantine

1
그렇습니다, 그것은 내가 가정하는 것입니다. 누락 된 디렉토리 로컬 a/b/은 체인 을 끊습니다. 어딘가에서 멈추어야하며 계속 진행하려면 빈 dir-locals 파일을 추가 할 수 있습니다.
erikstokes

3
BTW, Emacs가 dir-local을 체인으로 지원하는 패치를 환영합니다.
Stefan

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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.