bagaimana cara mendapatkan buffer (bukan hanya file) untuk menghormati auto-mode-alist?

13

T: bagaimana saya bisa mendapatkan buffer baru untuk menghormati pemetaan auto-mode-alist?

Saat menemukan file , Emacs membandingkan ekstensi file dengan auto-mode-alistuntuk menentukan mode utama mana yang digunakan untuk buffer file. Apakah ada cara untuk menggunakan informasi auto-mode-alistuntuk menentukan mode buffer yang belum memiliki file yang terkait dengannya?

Yaitu: jika saya membuka buffer baru yang namanya memiliki sesuatu yang terlihat seperti ekstensi file, dapatkah saya membuatnya terbuka secara otomatis dalam mode yang diharapkan? Misalnya, jika saya membuka buffer baru a-new-buffer.elyang belum dikaitkan dengan file, saya ingin membuka buffer emacs-lisp-modedaripada dalam mode default.

Dan
sumber
2
Hanya ingin tahu: Apa gunanya? TKI, mengapa / kapan / dalam konteks apa Anda ingin melakukan ini? Biasanya, jika Anda ingin buffer dikaitkan dengan file dan mengambil modenya auto-mode-alist, Anda membuat buffer " mengunjungi " file (dan itu menangani semuanya).
Drew
5
Contoh kasus penggunaan umum bagi saya adalah: a) orgbuffer sementara untuk menguji fungsi baru yang saya tulis untuk digunakan dalam org-mode; b) Rpenyangga sementara untuk melakukan manipulasi statistik yang cepat dan dibuang; c) buffer teks sementara untuk menulis email. Dalam setiap kasus, saya tidak ingin membuat file untuk dikunjungi, saya hanya ingin buffer yang dibuang yang tetap terbuka dalam mode yang sesuai.
Dan
2
File mengunjungi perintah seperti C-x C-fyang tidak " membuat file kunjungan ". Itu adalah kesalahpahaman mendasar. Mereka hanya melakukan apa yang Anda cari. Hal ini hanya jika dan ketika Anda mencoba untuk menyimpan buffer bahwa file akan dibuat. Jika Anda tidak mencoba untuk menyimpan buffer, tidak ada file yang dibuat. Apa yang Anda inginkan, dari apa yang saya mengerti sejauh ini, adalah "mengunjungi file" (yang sebenarnya berarti membuka buffer dalam mode yang tepat).
Drew
8
Seperti Dan, saya membuat buffer sementara sepanjang waktu yang saya tidak ingin dikaitkan dengan jalur file yang sebenarnya. Mengunjungi jalur file palsu akan berfungsi tetapi setidaknya ada sedikit gesekan dalam memilih direktori (atau menerima yang sekarang). Mungkin ada efek samping lain tergantung pada konfigurasi Anda yang lain: Perilaku simpan otomatis? Grup ibuffer atau proyek proyektil ditentukan oleh jalur? Ido konfirmasi konfirmasi? Karena buffer harus memiliki nama, menggunakan nama untuk mengatur mode secara otomatis untuk buffer sementara masuk akal bagi saya.
glukas
@Drew, ya, itu masuk akal dan akan menjadi jawaban paling sederhana untuk pertanyaan ini - bisakah Anda mempostingnya sebagai jawaban? Layak untuk ditingkatkan.
Dan

Jawaban:

8

File perintah kunjungan seperti C-x C-f jangan membuat file untuk dikunjungi. Mereka melakukan apa yang Anda cari.

Hanya jika dan ketika Anda mencoba untuk menyimpan buffer , sebuah file akan dibuat .

Jika Anda tidak mencoba untuk menyimpan buffer, tidak ada file yang dibuat. Apa yang Anda inginkan, dari apa yang saya mengerti sejauh ini, adalah " mengunjungi file " (yang sebenarnya berarti membuka buffer dalam mode yang tepat).

Drew
sumber
4
Bagaimana jika Anda memiliki jari hiperaktif yang secara konstan menyimpan file saat ini setiap 3 detik terlepas dari apa yang Anda inginkan?
Malabarba
1
@Malabarba: Sebenarnya, saya punya jari itu! ;-) Mungkin sebagian besar dari kita kentut tua melakukan - kebiasaan mengambil kembali ketika hal-hal crash sepanjang waktu. Tapi bagaimanapun, saya melakukan apa yang saya sarankan: sunting dalam buffer file yang dibuang. Jika memori otot saya yang terlalu aktif menghalangi dan mencoba menyelamatkan, biarlah: baik saya menekan nuntuk tidak menyimpan atau (sering) saya hanya menyimpan buffer. Dan kemudian saya melemparkan file yang dibuat ... atau tidak.)
Drew
1
@ Malabarba Ini persis untuk mencegah kekacauan file temp, yang saya mulai menggunakan buffer awal spesifik mode utama. Jika goresan tersebut layak untuk sebuah file, Anda selalu dapat menyimpannya sebagai file nanti.
Kaushal Modi
1
@kaushalmodi: Tidak ada yang menentang buffer mode khusus Anda, tetapi " kekacauan file temp " dengan mudah dibersihkan seperti kekacauan buffer . ;-) Dan jari hiperaktif dalam buffer awal mode khusus menyajikan masalah yang sama, mungkin - sama seperti di *scratch*: Anda diminta untuk menyimpan ketika jari itu secara otomatis mengenai C-x C-s.
Drew
9

Jika telah menggunakan solusi Juri Linkov selama bertahun-tahun.

Saya membuat buffer sementara dengan sesuatu seperti C-x b test.org C-j. Itu major-modeditentukan oleh ekstensi file melalui auto-mode-alist.

;; http://thread.gmane.org/gmane.emacs.devel/115520/focus=115794
(setq-default major-mode
              (lambda () (if buffer-file-name
                          (fundamental-mode)
                            (let ((buffer-file-name (buffer-name)))
                          (set-auto-mode)))))

Untuk menguji efeknya Anda dapat mencoba (prog1 (and (switch-to-buffer "my-new.org") major-mode) (kill-buffer "my-new.org")) => org-mode. Dalam emacs -qtes bersih akan kembali fundamental-mode.

rasmus
sumber
1
Itu sangat pintar! Ini juga lebih rapi daripada adviceopsi yang saya gunakan. Tidak yakin saya mengikuti untuk apa (prog1...)bagian ini, tetapi (setq-default major-mode ...)bagian itu cukup bagus.
Dan
1
Jangan ragu untuk melihat situs Juri's Emacs . The prog1-test hanya menunjukkan bahwa Anda mendapatkan yang diharapkan major-modeketika beralih ke buffer. Eval setq-defaultbagian dan jalankan tes. Ini akan kembali org-mode Tanpa setq-defaultitu akan kembali fundamental-mode.
rasmus
Ini jauh lebih elegan daripada hook-list-update-hook saya. Terima kasih!
glucas
ini harus menjadi jawaban yang diterima, karena itu sebenarnya menjawab pertanyaan daripada memberi tahu kita mengapa kita salah karena menanyakannya :)
Shlomi
6

Menemukan cara berbasis saran menggunakan ide yang berasal dari komentar @ Drew dan jawaban @ glucas yang akan saya rekam di sini kalau-kalau itu berguna bagi siapa pun.

Versi singkatnya: gunakan aftersaran untuk menanyakan apakah buffer memiliki nama file yang terkait, atur satu untuk sementara jika tidak, dan kemudian biarkan seluruh set-auto-modemesin menangani detailnya. Setelah sedikit pengujian (tidak ekstensif), tampaknya berfungsi dengan baik.

Untuk ido-switch-bufferdan vanilla switch-to-buffer, dua nasihat adalah:

(defadvice ido-switch-buffer (after set-mode activate)
  (unless buffer-file-name
    (let ((buffer-file-name (buffer-name)))
      (set-auto-mode t))))

(defadvice switch-to-buffer (after set-mode activate)
  (unless buffer-file-name
    (let ((buffer-file-name (buffer-name)))
      (set-auto-mode t))))

Saya menemukan opsi ini bermanfaat di atas find-filetitik di mana @Drew mengangkat karena jari-jari saya dapat melampaui otak saya: memori otot sering membuat saya masuk ke wilayah switch-to-buffer sebelum sepenuhnya terjadi pada saya yang find-fileakan melakukan apa yang saya butuhkan. Sekarang, kedua opsi tersedia.

UPDATE: bug kecil tapi berpotensi menjengkelkan dalam kode di atas: itu akan menjalankan kembali mode hook pada buffer setiap kali Anda beralih ke itu. Berikut ini memberikan nama file yang sebenarnya dari /tmpdirektori dan menghindari masalah itu:

(defadvice ido-switch-buffer (after set-mode activate)
  (unless buffer-file-name
    (setq buffer-file-name (concat "/tmp/" (buffer-name)))
    (set-auto-mode t)))
Dan
sumber
Terlihat bagus, dan membersihkan cruft jawaban saya telah terakumulasi selama beberapa iterasi. :-) Saya hanya akan mengulangi di sini bahwa jika Anda tidak ingin menetapkan path file yang sebenarnya karena alasan tertentu Anda dapat menggunakan variabel buffer-local untuk menghindari pengaturan mode beberapa kali.
glukas
5

The set-auto-modefungsi mengatur mode berdasarkan file yang berhubungan dengan buffer. Berikut adalah fungsi yang sementara ditetapkan buffer-file-namedari nama buffer untuk mengatur mode:

(defun my/set-buffer-mode (buffer &optional again)
  "Set the mode for BUFFER from the name.  
When called repeatedly for the same buffer only set the mode the first
time, unless the optional argument AGAIN is specified.
Does nothing if the buffer is associated with a file."

  (with-current-buffer buffer
    (when again (kill-local-variable 'my/buffer-mode-set))
    (unless (or buffer-file-name 
            (local-variable-p 'my/buffer-mode-set))
      (let ((buffer-file-name (buffer-name)))
        (set-auto-mode t)
        (setq-local my/buffer-mode-set t)))))

Anda dapat menjalankan ini ketika buffer diganti namanya menggunakan saran:

(defadvice rename-buffer (after my/rename-update-mode activate)
  (my/set-buffer-mode (current-buffer) 'again))

Saya tidak yakin tentang tempat terbaik untuk menghubungkan ini untuk memengaruhi buffer baru. Di sini saya menggunakan buffer-list-update-hook, tetapi dipanggil dalam banyak kasus daripada yang kita butuhkan.

(add-hook 'buffer-list-update-hook
      '(lambda ()
         (my/set-buffer-mode (car (buffer-list)))))
glukas
sumber
Jawaban di atas telah direvisi untuk menangani beberapa masalah. Secara khusus, saya sudah kembali menggunakan buffer-list-update-hookkarena change-major-mode-hooktidak dipanggil dengan buffer arus yang diharapkan. Sebagai catatan, mungkin lebih masuk akal untuk menyarankan fungsi switch-buffer seperti yang dilakukan @Dan dalam jawabannya.
glucas
3

Anda dapat menggunakan * scratch * buffer untuk tujuan membuat buffer sementara yang memiliki mode utama yang sama dengan file yang sedang Anda kerjakan.

Berikut ini jawaban emacs SE yang mungkin memecahkan masalah Anda:

Bagaimana saya bisa dengan cepat beralih antara file dan buffer * scratch * memiliki mode utama yang sama?

Pertanyaan dan jawaban yang dirujuk keduanya diposting oleh saya. Jawaban dalam fungsi melakukan hal berikut:

  • Jika Anda bekerja dalam mode X mayor dalam sebuah file, memanggil fungsi ini membuat buffer awal baru yang disebut *scratch-X-mode*jika belum ada, dan beralih ke buffer yang baru dibuat ini.
  • Jika *scratch-X-mode*sudah ada, itu hanya beralih ke buffer itu.
  • Memanggil fungsi ini lagi sementara di buffer awal akan membawa Anda kembali ke buffer file yang Anda kerjakan sebelumnya.
Kaushal Modi
sumber
0

Ada beberapa jawaban bagus di sini tetapi saya ingin menambahkan satu hal lagi. Emacs memiliki banyak fitur dan seringkali ada beberapa cara untuk melakukan sesuatu. Anda dapat menambahkan tag di bagian atas file apa pun yang memberi tahu emacs jenisnya, apa pun ekstensinya. Misalnya menambahkan ini:

# -*-Python-*-

Di bagian atas file akan memberi tahu emacs bahwa itu adalah file Python bahkan tanpa .pyekstensi. Perhatikan bahwa #di awal baris adalah komentar gaya Python. Untuk jenis file yang berbeda, Anda dapat menggunakan komentar yang berbeda. Misalnya untuk menentukan file Lisp yang Anda gunakan ;untuk memulai baris komentar dan mengatur mode dalam emacs seperti ini:

; -*- mode: Lisp;-*-

Lihat Menentukan Variabel File dan Memilih Mode File .

jcoffland
sumber
Ya, tetapi pertanyaan di sini secara khusus tentang membuat buffer sementara baru (misalnya dengan switch-buffer) dan memiliki mode yang secara otomatis diatur ke sesuatu selain fundamental-mode.
glucas