Cara mengatur status keluar untuk emacsclient

4

Saya menemukan diri saya menggunakan sesi Emacs utama saya (CocoaEmacs di OSX) untuk mengedit baris perintah bash saya. Untuk melakukannya saya mengatur EDITOR saya ke emacsclient. Kemudian saya mengedit baris di Emacs dan menyimpan dan keluar dari buffer itu - biasanya menggunakan "C-x #"yang dijalankan (server-edit).

Masalahnya adalah kadang - kadang saya berada di tengah-tengah pengeditan baris dan saya sadar saya tidak ingin benar-benar mengeksekusi baris (penyesalan masuk). Masalahnya adalah bahwa bash menentukan apakah akan mengeksekusi baris atau tidak berdasarkan status pengembalian.

Yang saya inginkan adalah ada dua pilihan bagi saya.

  1. Jika saya menekan "C-x #"simpan buffer dan kembali kode keluar 0(yaitu, saya telah melakukan pengeditan saya dan saya siap untuk bash untuk turun dengannya).

  2. Jika saya membunuh buffer maka jangan simpan buffer, bunuh, dan kembalikan kode keluar yang tidak nol. Aku bahkan tidak akan keberatan jika aku harus memukul ikatan alternatif.

Salah satu solusi parsial adalah dengan berkomentar. Saya tidak melihat ini sebagai opsi bagi saya seperti biasanya alasan saya mengedit commandline di Emacs adalah bahwa saya sedang mengerjakan hal multi-line.

milkypostman
sumber
Apakah mengosongkan buffer, menyimpan, dan keluar bekerja untuk Anda? Seharusnya mudah untuk mengikat itu pada sesuatu.
user314253
mungkin bukan karena saya tidak ingin riwayat dihapus dan saya pikir ada masalah dengan itu. Meskipun saya perlu menguasai hal-hal sejarah bash sedikit lebih baik.
milkypostman

Jawaban:

4

Dalam versi Emacs yang relatif terbaru (mis. Dalam salinan Emacs 24.2 saya, tetapi bukan distribusi OSAC dari emacs 22.1), Anda dapat menulis kode Elisp yang akan mengirim perintah ke emacsclient yang memerintahkannya untuk keluar dengan status keluar kesalahan.

Ini lebih mudah daripada kedengarannya.

Ada variabel buffer-local server-buffer-clients,, dengan klien yang dilampirkan ke buffer. Dan fungsinya server-send-stringdapat digunakan untuk mengkomunikasikan perintah mengikuti server-process-filterprotokol.

Sebagai contoh:

(server-send-string (car server-buffer-clients) "-error die")

menyebabkan (salah satu) emacsclient (s) yang terkait dengan buffer untuk segera mengeluarkan teks

*ERROR*: die

dan kemudian keluar dengan kode keluar 1.


Jadi, cukup mudah untuk mendefinisikan fungsi interaktif yang bisa Anda panggil dari emacs sendiri untuk mematikan emacsclients:

(defun tell-emacsclients-for-buffer-to-die ()
  "Sends error exit command to every client for the current buffer."
  (interactive)
  (dolist (proc server-buffer-clients)
    (server-send-string proc "-error die")))

Dengan hal di atas dalam .emacsfile Anda (dan versi Emacs yang cukup saat ini), Anda dapat memohon M-x tell-emacsclients-for-buffer-to-dieuntuk membuat emacsclients keluar dengan status kesalahan. (Dan tentu saja Anda dapat mengikat fungsi ini ke urutan kunci alternatif yang sesuai.)


Catatan kaki

Idealnya, seseorang kemudian akan memasangkan fungsi di atas dengan kait pada server-kill-bufferfungsi untuk mencapai nomor tujuan (2.) di pertanyaan awal. (Yaitu, membunuh buffer tanpa menyimpannya melalui C-x #harus mengaktifkan kesalahan yang sama keluar dari emacsclient.)

Namun, upaya saya untuk menambahkan ini ke kill-buffer-hookgagal, karena server-kill-bufferfungsi diletakkan di bagian depan kill-buffer-hookdaftar setelah server-visit-hookkait telah dijalankan, dan server-kill-bufferfungsi default akan berjalan terlebih dahulu. (Seseorang dapat memperbaiki kill-buffer-hooksetelahnya, tapi saya belum yakin di mana harus meletakkan kode untuk melakukan itu ke dalam aliran kontrol Elisp.)

Pembaruan: Oke, inilah cara yang sangat aneh untuk mencapai hal di atas:

(defun kill-buffer-with-special-emacsclient-handling ()
  (interactive)
  (add-hook 'kill-buffer-hook 'tell-emacsclients-for-buffer-to-die nil t)
  (kill-buffer))

(global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling)

Pembaruan 2: Varian yang sedikit lebih kuat:

(defun kill-buffer-with-special-emacsclient-handling ()
  "Wrapper around kill-buffer that ensures tell-emacsclients-for-buffer-to-die is on the hooks"
  (interactive)
  (add-hook 'kill-buffer-hook 'tell-emacsclients-for-buffer-to-die nil t)
  (kill-buffer))

;; (global-set-key (kbd "C-x k") 'kill-buffer)

(defun install-emacsclient-wrapped-kill-buffer ()
  "Installs wrapped kill-buffer with special emacsclient handling.
Best not to install it unconditionally because the server is not
necessarily running."
  (interactive)
  (global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling))

(add-hook 'server-switch-hook 'install-emacsclient-wrapped-kill-buffer)
pnkfelix
sumber
OK, biarkan saya coba ini dan lihat seberapa bagus kerjanya. Ini yang saya cari.
milkypostman
milkypostman: apakah itu berhasil untuk Anda?
pnkfelix
tbh saya tidak ingat sekarang. tapi saya mengalami masalah yang sama jadi saya akan coba lagi.
milkypostman
1

Cukup tekan Ctrl+Cdi terminal tempat Anda menjalankan bash. Ini membatalkan edisi, dan mendorong baris asli ke sejarah. Jika Anda tidak dapat melakukan ini secara langsung karena Emacs berjalan di terminal yang sama, matikan emacsclientproses dengan pilihan Anda.

Gilles
sumber
ini bagus. apakah ada cara mudah untuk membunuh proses klien dari dalam emacs? itu akan lebih baik bukan? terlihat rumit melaluiserver.el
milkypostman