2010-10-25 7 views
18

Según la documentación de Emacs, Directory Variables se aplica a todos los archivos debajo de un directorio que contiene un archivo .dir-locals.el.¿Cómo puedo acceder a la ruta al directorio actual en un archivo variable de directorio de emacs?

¿Cómo puedo, en ese archivo, establecer una variable para la ruta completa que contiene el archivo? Por ejemplo:

((nil . ((indent-tabs-mode . t) 
      (my-project-path **THIS_DIRECTORY**)))) 
+2

Usted no ha mencionado explícitamente, pero me pregunto si usted estaría interesado en cualquiera de los diversos " proyectos "paquetes". Por ejemplo, acabo de empezar a usar https://github.com/bbatsov/projectile; podría hacer algo de lo que quería hacer con directory-locals. – offby1

Respuesta

6

Creo (file-name-directory (or load-file-name buffer-file-name)) debería darle la ruta del directorio.

Ver http://xahlee.org/emacs/elisp_idioms_batch.html

Editar: Excepto que no lo hará, porque ningún eval expresiones se evalúan en el contexto de la memoria intermedia cuyas variables están siendo hackeado.

+2

Sí, pero ... por lo que sé, emacs en realidad no evalúa los formularios en .dir-locals; en cambio, simplemente los lee y asigna valores a las variables nombradas ... y los valores tienen que ser constantes. Espero estar equivocado, pero sospecho que no hay forma de hacerlo. – offby1

+0

@ offby1: Este tipo de enfoque parece funcionar un poco más que el de nberth, al menos ... – SamB

+0

@SamB Estoy decepcionado de que ninguno de nosotros, al parecer, haya intentado esto; así que lo hice. No funciona :-('' '((nil. ((Did-it-work (file-name-directory (o load-file-name buffer-file-name)))))) ' '' Sin embargo, recibí una advertencia de "variable insegura" – offby1

2

En caso de que sigue siendo importante, a la OP o algún otro, sugeriría a crear una función para generar el archivo .dir-locals.el. Entonces uno podría escribir algo como:

(let ((path default-directory) 
     file) 
    (setq file (format "%s/.dir-locals.el" path)) 
    (with-temp-buffer 
    (insert (format "((nil . ((indent-tabs-mode . t) 
      (my-project-path \"%s\"))))" path)) 
    (when (file-writable-p file) 
     (write-region (point-min) 
        (point-max) 
        file)))) 

para ser ejecutado dentro del directorio de inicio del proyecto.

+1

Hmm. Puede que no sea la * peor idea del mundo, pero ¡aún deja mucho que desear! – SamB

+0

Funciona hasta que mueva el directorio. Por ejemplo, configuraciones específicas del proyecto comprometidas con un repositorio git y alguien lo revisa en otro lugar. –

1

hack-local-variables es la función principal para el procesamiento de todas las variables locales, y llama hack-dir-local-variables que tratar con el archivo .dir-locals.el (o una variable de clase local dir, si no se está usando ese archivo).

El código para establecer el directorio no está aislado en su propia función, por lo que tendremos que copiarlo a cabo en una nueva función (esto desde GNU Emacs 24.0.95.1):

(defun my-dir-locals-dir() 
    "Return the directory local variables directory. 
Code taken from `hack-dir-local-variables'." 
    (let ((variables-file (dir-locals-find-file (or (buffer-file-name) default-directory))) 
     (dir-name nil)) 
    (cond 
    ((stringp variables-file) 
     (setq dir-name (file-name-directory variables-file))) 
    ((consp variables-file) 
     (setq dir-name (nth 0 variables-file)))) 
    dir-name)) 
+0

Este código parece correcto, aunque un poco difícil de poner en '. dir-locals.el' sí mismo ... – SamB

+0

La función sin duda viviría en la misma biblioteca que el código que requirió la información en primer lugar. Probablemente solo lo llamarías como una función en lugar de establecer una variable (aunque podrías emparejarlo con una variable automáticamente buffer-local, que se extiende la función de verificar si esa variable ya está configurada, y simplemente devolver el valor existente si hay uno; solo haciendo el procesamiento para establecer el valor si * no * ya está configurado). – phils

+0

Biblioteca? ¿Quién dijo algo acerca de una biblioteca? – SamB

10

Pregunté yo mismo la misma pregunta y no encontré ninguna solución en la web, por lo que creo que esta respuesta puede ayudar. En realidad, resulta que podemos reutilizar dir-locals-find-file para obtener el directorio que contiene el archivo .dir-locals.el. Así que esto es lo que he encontrado para, por ejemplo, la creación de un diccionario personal aspell dedicada a un directorio completo:

((nil . ((eval . (setq ispell-personal-dictionary 
         (expand-file-name 
         ".aspell_words" 
         (file-name-directory 
         (let ((d (dir-locals-find-file "."))) 
          (if (stringp d) d (car d)))))))))) 

Además, parece que las entradas se evalúan en el orden en que se especifican, por lo que el siguiente código debería funcionar:

((nil . ((eval . (set (make-local-variable 'my-project-path) 
         (file-name-directory 
         (let ((d (dir-locals-find-file "."))) 
         (if (stringp d) d (car d)))))) 
     (eval . (message "Project directory set to `%s'." my-project-path))))) 

Emacs se quejará de las variables locales no seguros (debido a la construcción de eval), sin embargo, todavía se puede marcar de forma permanente a lo seguro.

+0

Este enfoque no funcionará de manera confiable con más de un .dir-locals.el en el alcance. – SamB

+0

@SamB Acabo de probarlo, y parece funcionar bien para mí (siempre y cuando no tenga dependencias de variables intrincadas entre sus archivos '.dir-locals.el'); con una serie de '.dir-locals.el' que contiene exactamente mi último ejemplo anterior,' my-project-path' se establece en la ruta más larga en el alcance del archivo visitado. Sin embargo, no sé exactamente cómo se especifica el comportamiento de Emacs w.r.t imbricated '.dir-locals.el'. – nberth

+1

Malo: mi prueba rápida fue parcial, ya que los '.dir-locals.el' eran todos idénticos. De hecho, 'dir-locals-find-file' siempre devuelve el primer' .dir-locals.el' encontrado por Emacs (el más cercano al archivo visitado). Reconozco la limitación. – nberth

1

Si está trabajando en * nix, es posible obtener el directorio de trabajo por el siguiente código elisp,

(defun get-working-directory() 
    (getenv "PWD)) 

Por cierto, tengo que mencionar que, (shell-command "pwd") resultará en el directorio en el archivo (que es correspondiente al búfer que está editando actualmente).

+1

El inglés está bien :-). – DJJ

0

En mi caso, quería ubicar un archivo que era relativo a mi directorio de trabajo actual para mi repositorio, y el archivo .dir-locals.el se comprobó en la raíz, por lo que un archivo "local" para. dir-locals.el también era un archivo "local" para la raíz del proyecto. respuesta

de pajato0 anteriormente trabajó para algunos casos, pero también estaba rompiendo otros modos (como Magit).Tengo alrededor del problema utilizando la función del paquete de projectileprojectile-project-root a encontrar mi la ruta base para mí:

((nil . ((eval . (setq cmake-ide-build-dir 
        (concat (projectile-project-root) "/build-make")) 
     )))) 
Cuestiones relacionadas