Nei buffer indirizzati, posizionare il punto sul file più importante di quella directory


14

Il 90% delle volte che visito una directory in Emacs, la prima cosa che faccio è spostare il punto in un file specifico e aprirlo. Molte volte, il file che devo aprire è molto prevedibile. Per esempio:

  • Se ci sono .texfile in questa directory, di solito vado direttamente a master.tex.
  • Alla radice dei progetti Android, è comunemente AndroidManifest.xml.
  • In una directory in cui sviluppo un pacchetto emacs, è quasi sempre il file sorgente principale del pacchetto. Questo è di solito, ma non sempre, l'unico .elfile in questa directory.

C'è un modo in cui posso aver indirizzato automaticamente il punto su questi file quando apro queste directory?

Ciò offrirebbe molta comodità (dato che potrei aprirli semplicemente premendo RET), ma darebbe comunque la flessibilità di visitare altri file.

Risposte:


16

Scrivi una funzione personalizzata per dired-initial-position-hook. In questa funzione è possibile utilizzare varie funzioni dirette per cercare file ed eventualmente chiamare dired-goto-fileper spostare il punto sul file "migliore":

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

Di seguito spiegherò aspetti specifici di questa funzione ed evidenzierò potenziali estensioni.

Saltare ai file

dired-goto-fileritorna nilse il file non esiste nel buffer diretto corrente, quindi è sicuro chiamare senza controllo preventivo. Tuttavia dired-goto-filerichiede un nome file assoluto (errori sui nomi relativi), quindi expand-file-name.

Ricerca di file

Dired non fornisce un'API diretta per la ricerca di file. In generale, puoi iterare su tutti i file proprio come faresti su tutte le righe di un buffer:

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

Tuttavia, è più comodo utilizzare le funzioni di marcatura. Basta fare attenzione a usare un marcatore "insolito" per non perdere i segni interattivi esistenti:

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

Salva modalità luogo

È inoltre necessario prestare attenzione per quanto riguarda la modalità Salva luogo, nel caso in cui sia stata abilitata. Nei buffer Dired, la modalità Salva luogo non ricorda il valore del punto come in altre modalità, ma era attivo l'ultimo punto del nome file. Ripristina questo nome di file proprio come facciamo noi: si aggancia dired-initial-position-hooke chiama dired-goto-file(in effetti è lì che ho rubato quel codice :)).

Se il nostro hook viene prima del salvataggio del luogo, la modalità Salva luogo sovrascriverà incondizionatamente la nostra posizione. Tuttavia, se viene prima del nostro hook (come nel caso in cui Save Place è abilitato dopo aver configurato questo hook), la nostra funzione sovrascriverà effettivamente Save Place che non è desiderabile. Tuttavia, come in qualsiasi buffer, Save Place imposta la variabile locale save-placesu un valore diverso da zero, quindi possiamo semplicemente controllarlo e agire solo Save Place non ha ripristinato un nome di file.

Se preferisci che Save Place sia “loose”, rimuovi il segno di spunta save-placee assicurati che il nostro hook sia eseguito dopo Save Place, abilitando prima la modalità Save Place e quindi chiamando add-hookcon un valore diverso da zero per l' APPENDargomento.


Bella risposta. Potresti voler definire bound-and-true-p. :-)
Malabarba,

@Malabarba bound-and-true-pè una macro integrata da bindings.el.
lunaryorn,

Caro dio, non faccio ciò che mi fa stare peggio, il fatto che non lo sapessi o il fatto che non ho nemmeno verificato.
Malabarba,

@Malabarba Non importa, mi ci è voluto un anno (letteralmente) per scoprire l'esistenza di questa funzione.
lunaryorn,

Sì, è una funzione meravigliosa di cui non avevo mai sentito parlare fino ad ora!
sanityinc,
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.