Dalam buffer dired, tempatkan titik pada file paling penting dari direktori itu

14

90% dari waktu saya mengunjungi direktori di Emacs, hal pertama yang saya lakukan adalah memindahkan titik ke file tertentu dan membukanya. Sering kali, file yang perlu saya buka sangat mudah ditebak. Contohnya:

  • Jika ada .texfile dalam direktori ini, saya biasanya langsung menuju master.tex.
  • Pada akar proyek Android, biasanya AndroidManifest.xml.
  • Dalam direktori tempat saya mengembangkan paket emacs, hampir selalu file sumber utama paket. Itu biasanya, tetapi tidak selalu, satu-satunya .elfile dalam direktori ini.

Apakah ada cara saya bisa secara otomatis menempatkan titik pada file-file ini ketika saya membuka direktori ini?

Ini akan menawarkan banyak kemudahan (karena saya bisa membukanya dengan hanya menekan RET), tetapi masih akan memberikan fleksibilitas untuk mengunjungi file lain.

Malabarba
sumber

Jawaban:

16

Tulis fungsi khusus untuk dired-initial-position-hook. Dalam fungsi ini Anda dapat menggunakan berbagai fungsi dired untuk mencari file, dan akhirnya memanggil dired-goto-fileuntuk memindahkan titik ke file "terbaik":

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

Berikut ini saya akan menjelaskan aspek spesifik dari fungsi ini, dan menyoroti ekstensi potensial.

Melompat ke file

dired-goto-filekembali niljika file tidak ada di buffer dired saat ini, jadi aman untuk memanggil tanpa memeriksa sebelumnya. Namun dired-goto-filemembutuhkan nama file absolut (kesalahan pada nama relatif), karenanya expand-file-name.

Mencari file

Dired tidak menyediakan API langsung untuk mencari file. Secara umum, Anda dapat mengulangi semua file seperti halnya Anda mengulangi semua baris dalam 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
  ;; …
  )

Namun, lebih nyaman menggunakan fungsi menandai. Berhati-hatilah untuk menggunakan karakter marker "tidak biasa", agar tidak kehilangan tanda interaktif yang ada:

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

Simpan Mode Tempat

Anda juga harus berhati-hati terkait dengan Mode Simpan Tempat, jika Anda mengaktifkannya. Di buffer Dired, Mode Simpan Tempat tidak mengingat nilai poin seperti pada mode lain, melainkan titik nama file terakhir aktif. Ini mengembalikan nama file ini seperti yang kita lakukan: Ini menghubungkan dired-initial-position-hookdan memanggil dired-goto-file(pada kenyataannya, di situlah saya mencuri kode itu dari :)).

Jika hook kami datang sebelum save place, Save Place Mode tanpa syarat akan menimpa posisi kami. Namun, jika itu datang sebelum hook kami (seperti halnya ketika Save Place diaktifkan setelah Anda mengatur hook ini) fungsi kami sebenarnya akan menimpa Save Place yang tidak diinginkan. Namun, seperti pada buffer apa pun, Save Place menetapkan variabel lokal save-placeke nilai non-nil, jadi kami cukup memeriksanya dan hanya bertindak itu Save Place tidak mengembalikan nama file.

Jika Anda lebih suka memiliki Simpan Tempat "longgar", hapus tanda centang untuk save-place, dan pastikan bahwa kait kami dijalankan setelah Simpan Tempat, dengan mengaktifkan Simpan Tempat Mode terlebih dahulu , dan kemudian memanggil add-hookdengan nilai nihil untuk APPENDargumennya.

lunaryorn
sumber
Jawaban yang bagus Anda mungkin ingin mendefinisikan bound-and-true-p. :-)
Malabarba
@Malabarba bound-and-true-padalah makro bawaan dari bindings.el.
lunaryorn
Ya Tuhan, aku tidak tahu apa yang membuatku merasa lebih buruk, fakta bahwa aku tidak tahu atau bahkan aku tidak memeriksanya.
Malabarba
@Malabarba Sudahlah, saya butuh satu tahun (secara harfiah) untuk menemukan keberadaan fungsi ini.
lunaryorn
Ya, itu adalah fungsi luar biasa yang belum pernah saya dengar sampai sekarang!
sanityinc