En buffers directos, coloque el punto en el archivo más importante de ese directorio

14

El 90% de las veces que visito un directorio en Emacs, lo primero que hago es mover el punto a un archivo específico y abrirlo. Muchas veces, el archivo que necesito abrir es muy predecible. Por ejemplo:

  • Si hay .texarchivos en este directorio, generalmente voy directamente a master.tex.
  • En la raíz de los proyectos de Android, es común AndroidManifest.xml.
  • En un directorio donde desarrollo un paquete emacs, casi siempre es el archivo fuente principal del paquete. Ese es generalmente, pero no siempre, el único .elarchivo en este directorio.

¿Hay alguna forma en que pueda haber direccionado automáticamente el punto en estos archivos cuando abro estos directorios?

Esto ofrecería mucha conveniencia (ya que podría abrirlos simplemente presionando RET), pero aún así daría la flexibilidad de visitar otros archivos.

Malabarba
fuente

Respuestas:

16

Escribe una función personalizada para dired-initial-position-hook. En esta función, puede usar varias funciones directas para buscar archivos y, finalmente, llamar dired-goto-filepara mover el punto al archivo "mejor":

(defun my-dired-goto-important-file ()
  "Go to an important file in the current dired buffer."
  (unless (bound-and-true-p save-place)
    (let ((candidates '("master.tex" "AndroidManifest.xml"))
          candidate)
      (while (and candidates
                  (not (dired-goto-file (expand-file-name (pop candidates)))))
        nil))))

(add-hook 'dired-initial-position-hook #'my-dired-goto-important-file)

A continuación explicaré aspectos específicos de esta función y resaltaré posibles extensiones.

Saltando a los archivos

dired-goto-filedevuelve nilsi el archivo no existe en el búfer dired actual, por lo que es seguro llamar sin verificación previa. Sin embargo, dired-goto-filerequiere un nombre de archivo absoluto (errores en nombres relativos), por lo tanto expand-file-name.

Buscando archivos

Dired no proporciona una API sencilla para buscar archivos. En general, puede iterar sobre todos los archivos al igual que iteraría sobre todas las líneas en un búfer:

(let (files)
  (goto-char (point-min))
  (while (not (eobp))
    (let ((filename (dired-get-filename nil 'no-error)))
      (when filename
        (push filename files)))
    (forward-line 1))
  ;; Now `files' is a list of files, which you can search for patterns
  ;; …
  )

Sin embargo, es más conveniente usar las funciones de marcado. Solo tenga cuidado de usar un marcador "inusual" para no perder las marcas interactivas existentes:

(unwind-protect
    (when (dired-mark-files-regexp (rx ".tex" string-end) ?t)
      (dired-goto-file (expand-file-name "master.tex")))
  (dired-unmark-all-files ?t))

Modo Guardar lugar

También debe tener cuidado con respecto al modo Guardar lugar, en caso de que lo haya habilitado. En los buffers Dired, el modo Guardar lugar no recuerda el valor del punto como en otros modos, sino que el último punto del nombre del archivo estaba activado. Restaura este nombre de archivo tal como lo hacemos nosotros: se conecta dired-initial-position-hooky llama dired-goto-file(de hecho, ahí es donde robé ese código :)).

Si nuestro gancho viene antes de guardar el lugar, el modo Guardar lugar sobrescribirá incondicionalmente nuestra posición. Sin embargo, si viene antes de nuestro enlace (como es el caso cuando Save Place está habilitado después de configurar este enlace), nuestra función en realidad sobrescribiría Save Place, lo que no es deseable. Sin embargo, como en cualquier búfer, Save Place establece la variable local save-placeen un valor no nulo, por lo que simplemente podemos verificar eso y solo actuarlo. Save Place no restauró un nombre de archivo.

Si prefiere que Save Place esté "suelto", elimine la save-placemarca y asegúrese de que nuestro enlace se ejecuta después de Save Place, habilitando primero el Modo Guardar lugar y luego llamando add-hookcon un valor no nulo para su APPENDargumento.

Lunaryorn
fuente
Gran respuesta. Es posible que desee definir bound-and-true-p. :-)
Malabarba
@Malabarba bound-and-true-pes una macro incorporada de bindings.el.
lunaryorn
Dios mío, no sé qué me hace sentir peor, el hecho de que no lo sabía o el hecho de que ni siquiera lo comprobé.
Malabarba
@Malabarba No importa, me llevó un año (literalmente) descubrir la existencia de esta función.
lunaryorn
Sí, esa es una función maravillosa de la que nunca había escuchado hasta ahora.
sanityinc