Чи є спосіб вирішити ланцюжок файлів .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 все можливе. :)
Ерік Джонсон

Відповіді:


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

Здається, очікується, що кожен каталог дерева (до деякого рівня вгору від поточного шляху) має a .dir-locals.el. Буде це працювати , якщо у мене є дерево каталогів a/b/cі існує a/.dir-locals.elі a/b/c/.dir-locals.el, але немає a/b/.dir-locals.el(припустить , що я відвідую , a/b/c/foo.elі я хочу від настройки , a/.dir-locals.elякі повинні застосовуватися)?
Костянтин

1
Так, це я припускаю. Зниклі місцеві місцеві жителі a/b/переривають ланцюг. Він повинен десь зупинитися, і якщо ви хочете, щоб це продовжувалося, ви можете додати порожні файли dir-locals.
erikstokes

3
До речі, я вітаю патч для Emacs, щоб підтримувати ланцюжків місцевих мешканців поза коробкою.
Стефан

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.