Existe uma maneira de encadear arquivos .dir-locals.el em cadeia?


15

Suponha que eu tenha um diretório com esses arquivos.

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

Quando vou criar um arquivo /foo/bar/baz/, gostaria de encadear uma série de maneira que /foo/.dir-locals.else aplique primeiro e depois /foo/bar/.dir-locals.ele depois/foo/bar/baz/.dir-locals.el



Não há opção que faça isso (observei o código com muita atenção), mas deveria ser (quase certamente é) possível com algum código extra. Eu tenho um uso para ele também, então eu poderia olhar para isso ...
— Constantino

Com elisp, tudo é possível. :)
— Eric Johnson

Respostas:


7

Com base na resposta aqui , fazemos isso aconselhando hack-dir-local-variablesa procurar um diretório e carregar se o .dir-locals.elarquivo está legível. Ele continuará subindo até encontrar um diretório sem legibilidade .dir-locals.el.

Dependendo do valor dos walk-dir-locals-upwardarquivos, pode ser lido do diretório atual para cima ou do último .dir-locals.elencontrado para baixo. Para baixo é o padrão, para que os subdiretórios possam ignorar as configurações de seus pais.

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

Isso parece esperar que todo diretório na árvore (até algum nível acima do caminho atual) possua um .dir-locals.el. Funcionará se eu tiver uma árvore de diretórios a/b/ce existir a/.dir-locals.ele a/b/c/.dir-locals.el, mas não a/b/.dir-locals.el(suponha que eu esteja visitando a/b/c/foo.ele deseje que as configurações a/.dir-locals.elsejam aplicadas)?
— Constantine

11
Sim, é o que estou assumindo. Os dir-locals ausentes a/b/quebram a cadeia. Ele precisa parar em algum lugar e, se você quiser continuar, pode adicionar um arquivo dir-locals vazio.
— Erikstokes

3
BTW, eu gostaria de receber um patch para o Emacs para apoiar encadeamento dir-locals fora da caixa.
— Stefan

6

Aqui está uma maneira diferente de fazer isso.

Defino uma função que produz a lista de todos os diretórios na hierarquia de diretórios atual.

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

Um exemplo está em ordem:

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

Agora, posso adicionar conselhos para hack-dir-local-variablesfazê-lo "fingir" que estamos visitando um arquivo na parte superior da árvore, aplicar configurações de diretório local e, em seguida, descer um nível, aplicar configurações novamente e assim por diante.

(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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.