W buforach buforowanych umieść punkt na najważniejszym pliku tego katalogu

14

90% razy, kiedy odwiedzam katalog w Emacsie, pierwszą rzeczą, którą robię, jest przejście do określonego pliku i otwarcie go. Wiele razy plik, który muszę otworzyć, jest bardzo przewidywalny. Na przykład:

  • Jeśli .texw tym katalogu są pliki, zwykle idę prosto do master.tex.
  • U podstaw projektów na Androida jest to często AndroidManifest.xml.
  • W katalogu, w którym tworzę pakiet emacs, prawie zawsze jest to główny plik źródłowy pakietu. To zwykle, ale nie zawsze, jedyny .elplik w tym katalogu.

Czy istnieje sposób, w jaki mogę dired automatycznie umieścić punkt na tych plikach, gdy otwieram te katalogi?

Zapewniłoby to dużą wygodę (ponieważ mogłem je otworzyć po prostu uderzeniem RET), ale nadal dawałoby elastyczność przeglądania innych plików.

Malabarba
źródło

Odpowiedzi:

16

Napisz niestandardową funkcję dla dired-initial-position-hook. W tej funkcji możesz używać różnych funkcji dired do wyszukiwania plików i ostatecznie wywołać dired-goto-filepunkt przejścia do „najlepszego” pliku:

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

Poniżej wyjaśnię konkretne aspekty tej funkcji i podkreślę potencjalne rozszerzenia.

Przeskakiwanie do plików

dired-goto-filezwraca, niljeśli plik nie istnieje w bieżącym buforze wybieranym, więc można bezpiecznie wywoływać bez uprzedniej kontroli. Jednak dired-goto-filewymaga bezwzględnej nazwę pliku (IT błędy w nazwach względna), stąd expand-file-name.

Wyszukiwanie plików

Dired nie zapewnia bezpośredniego interfejsu API do wyszukiwania plików. Ogólnie rzecz biorąc, możesz iterować po wszystkich plikach, tak jak iterujesz po wszystkich liniach w buforze:

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

Jednak wygodniej jest korzystać z funkcji znakowania. Wystarczy użyć „niezwykłych” znaków znaczników, aby nie utracić istniejących znaków interaktywnych:

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

Zapisz tryb miejsca

Musisz także zachować ostrożność w odniesieniu do trybu Save Place, na wypadek, gdybyś go włączył. W buforach Dired, Save Place Mode nie pamięta wartości punktowej, jak w innych trybach, ale raczej ostatni punkt nazwy pliku był włączony. Przywraca tę nazwę pliku, tak jak my: łączy się dired-initial-position-hooki wywołuje dired-goto-file(to właśnie tam ukradłem ten kod :)).

Jeśli nasz haczyk pojawi się przed zapisem miejsca, tryb zapisu miejsca bezwarunkowo zastąpi naszą pozycję. Jeśli jednak pojawi się przed naszym hakiem (tak jak w przypadku, gdy Save Save Place jest włączony po skonfigurowaniu tego haka), nasza funkcja nadpisze Save Place, co nie jest pożądane. Jednak, jak w każdym buforze, Save Place ustawia zmienną lokalną na wartość save-placeinną niż zero, więc możemy to po prostu sprawdzić i tylko działać. Save Place nie przywraca nazwy pliku.

Jeśli wolisz, aby Save Place było „luźne”, usuń zaznaczenie dla save-placei upewnij się, że nasz hook jest uruchamiany po Save Place, włączając najpierw tryb Save Place , a następnie wywołując add-hookwartość APPENDargumentu inną niż zero .

księżycowy
źródło
Świetna odpowiedź. Możesz zdefiniować bound-and-true-p. :-)
Malabarba
@Malabarba bound-and-true-pto wbudowane makro z bindings.el.
lunaryorn
Dobry Boże, nie wiem, co sprawia, że ​​czuję się gorzej, faktu, że o tym nie wiedziałem, a nawet tego nie sprawdziłem.
Malabarba
@Malabarba Nieważne, odkrycie istnienia tej funkcji zajęło mi (dosłownie) rok.
lunaryorn
Tak, to wspaniała funkcja, o której do tej pory nigdy nie słyszałem!
sanityinc