Pintasan direktori di buffer emacs

8

Jadi saya bertanya pertanyaan ini tentang cara pintas direktori di shell. Idenya adalah saya ingin dapat membuka file /home/Documents/foo, katakanlah, dengan mengetik C-x C-f ~foo/file.

Jadi, apakah ada cara untuk meniru "direktori bernama" zsh di buffer emacs?

Secara kebetulan, definisi pintasan yang ingin saya gunakan sudah ada di .zshrc saya, jika ada solusi yang membacanya secara langsung, yang mendapat poin bonus.

Seamus
sumber
Mungkin ini bukan pertanyaan SE unix dan saya harus mencoba keberuntungan saya pada SU?
Seamus
pertanyaan ini tidak spesifik unix (bahkan ke bagian zsh: ada port zsh untuk Windows, atau setidaknya untuk Cygwin), jadi harus di SU. Tapi, yah, itu di sini sekarang, jadi saya jawab di sini.
Gilles 'SO- stop being evil'

Jawaban:

8

Komponen Emacs yang bertanggung jawab untuk memperluas ~nama file adalah expand-file-name. Sayangnya, itu ditulis dalam C, dan jauh di dalam perutnya adalah kode yang mengasumsikan bahwa apa yang muncul setelah itu ~adalah nama pengguna. Untungnya, Emacs memiliki cara umum untuk menambahkan pembungkus di sekitar fungsi, sehingga Anda dapat melakukan apa yang Anda inginkan jika Anda tidak keberatan mengulangi beberapa logika dalam fungsi bawaan.

Berikut adalah beberapa kode yang sama sekali belum diuji yang harus Anda jalani. Cari “Advising Emacs Lisp Functions” di manual Emacs Lisp untuk informasi lebih lanjut; ide dasarnya adalah defadvicemenambahkan beberapa kode untuk dijalankan sebelum kode aktual expand-file-name. Mohon beri tanda kesalahan yang telah saya buat dalam komentar (apakah Anda tahu cara memperbaikinya atau tidak).

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

Saya akan membiarkan parsing pintasan .zshrcuntuk diisi expand-file-name-custom-tilde-alist(atau teknik apa pun yang Anda pilih untuk menjaga alias tetap selaras) sebagai latihan.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Solusi latihan saya:(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

Cukup gunakan $foosebagai ganti ~foodi minibuffer. Emacs akan memperlakukan foosebagai nama variabel lingkungan dan menggunakan nilainya.

Friedel
sumber
Apa fitur tersembunyi yang mematikan! (komentar: ekspor variabel agar tersedia)
AdrieanKhisbe