Accesos directos de directorio en el búfer de emacs

8

Entonces hice esta pregunta sobre los accesos directos a directorios en un shell. La idea es que me gustaría poder abrir un archivo /home/Documents/foo, digamos, escribiendo C-x C-f ~foo/file.

Entonces, ¿hay alguna manera de emular los "directorios con nombre" de zsh en el búfer de emacs?

Por cierto, las definiciones de acceso directo que quiero usar ya están en mi .zshrc, si hay una solución que las lea directamente, que obtiene puntos de bonificación.

Seamus
fuente
¿Quizás esta no sea una pregunta SE de Unix y debería probar suerte en SU?
Seamus
Esta pregunta no es específica de Unix (incluso hasta la parte zsh: hay un puerto zsh para Windows, o al menos para Cygwin), por lo que debería estar en SU. Pero, bueno, está aquí ahora, así que lo respondí aquí.
Gilles 'SO- deja de ser malvado'

Respuestas:

8

El componente Emacs que se encarga de expandir ~en los nombres de archivo es expand-file-name. Desafortunadamente, está escrito en C, y en el fondo de sus intestinos hay un código que supone que lo que viene después ~es un nombre de usuario. Afortunadamente, Emacs tiene una forma genérica de agregar un envoltorio alrededor de las funciones, por lo que puede hacer lo que quiera si no le importa repetir parte de la lógica en la función incorporada.

Aquí hay un código completamente no probado que debería ayudarte. Consulte "Asesoramiento de las funciones de Emacs Lisp" en el manual de Emacs Lisp para obtener más información; La idea básica es que defadviceagrega un código para ejecutar antes del código real de expand-file-name. Señale los errores que inevitablemente cometí en los comentarios (ya sea que sepa cómo solucionarlos o no).

(defvar expand-file-name-custom-tilde-alist
  '(("foo" . "/home/Documents/foo")))

(defadvice expand-file-name (before expand-file-name-custom-tilde
                             (name &optional default-directory)
                             activate compile)
  "User-defined expansions for ~NAME in file names."
  (save-match-data
    (when (string-match "\\`\\(\\(.*/\\)?~\\([^:/]+\\)\\)/" name)
      (let ((replacement (assoc (match-string 3 name) expand-file-name-custom-tilde-alist)))
        (when replacement
          (setq name (replace-match (cdr replacement) t t name 1)))))))

Dejaré analizar los atajos .zshrcpara completar expand-file-name-custom-tilde-alist(o cualquier técnica que elija para mantener los alias sincronizados) como ejercicio.

Gilles 'SO- deja de ser malvado'
fuente
Mi solución de ejercicio:(defun my/add-to-tilde-alist (hash) (let* ((tilde:dir (split-string hash "=")) (tilde (car tilde:dir)) (dir (cadr tilde:dir))) (push (cons tilde dir) expand-file-name-custom-tilde-alist))) (mapc #'my/add-to-tilde-alist (split-string (with-output-to-string (call-process "zsh" nil standard-output nil "-ic" "hash -d")) "\n" t))
Michaël
4

Simplemente use en $foolugar de ~fooen el minibúfer. Emacs lo tratará foocomo el nombre de una variable de entorno y usará su valor.

Friedel
fuente
¡Qué característica oculta asesina! (comentario: exportar la variable para que estén disponibles)
AdrieanKhisbe