C'è un modo per collegare i file .dir-locals.el a daisy chain?


15

Supponiamo di avere una directory con questi file.

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

Quando vado a creare un file /foo/bar/baz/, mi piacerebbe metterli insieme in modo tale che si /foo/.dir-locals.elapplichi prima, e poi /foo/bar/.dir-locals.el, e poi/foo/bar/baz/.dir-locals.el



Non esiste alcuna opzione che lo farebbe (ho esaminato il codice abbastanza da vicino), ma dovrebbe essere (quasi certamente è possibile) con qualche codice aggiuntivo. Ne ho un uso anche io, quindi potrei esaminare questo ...
Costantino,

Con elisp, tutto è possibile. :)
Eric Johnson,

Risposte:


7

Sulla base della risposta qui , lo facciamo consigliando hack-dir-local-variablesdi cercare una directory e caricare verificare se quel .dir-locals.elfile è leggibile. Continuerà a salire fino a quando non trova una directory non leggibile .dir-locals.el.

A seconda del valore dei walk-dir-locals-upwardfile possono essere letti dalla directory corrente verso l'alto o dall'ultimo .dir-locals.eltrovato verso il basso. Il down è l'impostazione predefinita in modo che le sottodirectory possano ostruire le impostazioni dei loro genitori.

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

Questo sembra aspettarsi che ogni directory nella struttura (fino a un certo livello dal percorso corrente) abbia un .dir-locals.el. Funzionerà se ho un albero di directory a/b/ce ci sono a/.dir-locals.ele a/b/c/.dir-locals.el, ma no a/b/.dir-locals.el(supponiamo che io stia visitando a/b/c/foo.ele voglio che le impostazioni a/.dir-locals.elvengano applicate)?
Costantino,

1
Sì, è quello che presumo. I dir-locali mancanti a/b/interrompono la catena. Deve fermarsi da qualche parte e se vuoi che continui, puoi aggiungere un file dir-locals vuoto.
erikstokes,

3
A proposito, accolgo con favore una patch per Emacs per supportare il concatenamento di dir-locali fuori dalla scatola.
Stefan,

6

Ecco un modo diverso di farlo.

Definisco una funzione che produce l'elenco di tutte le directory nella gerarchia di directory corrente.

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

Un esempio è in ordine:

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

Ora posso aggiungere un consiglio per hack-dir-local-variables"fingere" che stiamo visitando un file nella parte superiore dell'albero, applicare le impostazioni della directory locale, quindi scendere di un livello, applicare nuovamente le impostazioni e così via.

(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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.