Isi
Saya menggunakan after-make-frame-functions
hook untuk memuat tema dengan benar dalam konfigurasi klien / server emacs . Khususnya ini adalah potongan kode yang saya gunakan untuk membuatnya (berdasarkan jawaban SO ini ):
(if (daemonp)
(add-hook 'after-make-frame-functions
(lambda (frame)
(select-frame frame)
(load-theme 'monokai t)
;; setup the smart-mode-line and its theme
(sml/setup)))
(progn (load-theme 'monokai t)
(sml/setup)))
Masalah
Ketika emacsclient -c/t
sesi baru dimulai, kait dieksekusi tidak hanya di frame baru, tetapi di semua frame yang ada sebelumnya ( sesi emacsclient lainnya ) dan itu membuat efek visual yang sangat menjengkelkan (tema dimuat lagi di semua frame itu) . Lebih buruk lagi, di terminal klien sudah membuka warna tema menjadi benar-benar kacau. Jelas itu hanya terjadi pada klien emacs yang terhubung ke server emacs yang sama. Alasan untuk perilaku ini jelas, hook dijalankan di server dan semua kliennya terpengaruh.
Pertanyaan
Apakah ada cara untuk menjalankan fungsi ini hanya sekali atau mendapatkan hasil yang sama tanpa menggunakan hook?
Solusi parsial
Saya sekarang memiliki kode ini, terima kasih atas jawaban @ Drew. Tetapi masih memiliki masalah, setelah Anda memulai sesi klien di terminal, GUI tidak memuat tema dengan benar dan sebaliknya. Setelah banyak tes, saya menyadari bahwa perilakunya tergantung pada emacsclient yang dimulai pertama, dan setelah membuang berbagai hal, saya pikir itu mungkin terkait dengan palet warna yang dimuat. Jika Anda memuat ulang secara manual tema semua berfungsi dengan baik dan itulah alasan mengapa perilaku ini tidak muncul ketika fungsi dipanggil oleh hook setiap kali seperti pada konfigurasi awal saya.
(defun emacsclient-setup-theme-function (frame)
(progn
(select-frame frame)
(load-theme 'monokai t)
;; setup the smart-mode-line and its theme
(sml/setup)
(remove-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)))
(if (daemonp)
(add-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)
(progn (load-theme 'monokai t)
(sml/setup)))
Solusi terakhir
Akhirnya saya memiliki kode yang benar-benar berfungsi yang memecahkan perilaku yang terlihat dalam solusi parsial, untuk mencapai ini saya menjalankan fungsi sekali dengan mode (terminal atau gui) ketika kemudian emacsclient yang bersangkutan dimulai untuk pertama kali, kemudian hapus fungsi dari hook karena tidak dibutuhkan lagi. Sekarang aku bahagia! :) Terima kasih lagi @Drew!
Kode:
(setq myGraphicModeHash (make-hash-table :test 'equal :size 2))
(puthash "gui" t myGraphicModeHash)
(puthash "term" t myGraphicModeHash)
(defun emacsclient-setup-theme-function (frame)
(let ((gui (gethash "gui" myGraphicModeHash))
(ter (gethash "term" myGraphicModeHash)))
(progn
(select-frame frame)
(when (or gui ter)
(progn
(load-theme 'monokai t)
;; setup the smart-mode-line and its theme
(sml/setup)
(sml/apply-theme 'dark)
(if (display-graphic-p)
(puthash "gui" nil myGraphicModeHash)
(puthash "term" nil myGraphicModeHash))))
(when (not (and gui ter))
(remove-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)))))
(if (daemonp)
(add-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)
(progn (load-theme 'monokai t)
(sml/setup)))
Jawaban:
Saya menduga Anda tidak benar - benar mencari cara untuk " menjalankan hook hanya sekali ". Saya menduga Anda mencari cara untuk menjalankan fungsi tertentu hanya sekali, setiap kali kait dijalankan.
Konvensional, dan sederhana, jawaban yang dimaksud adalah untuk fungsi Anda untuk menghapus diri dari hook, setelah melakukan aksi satu kali yang Anda inginkan. Dengan kata lain, gunakan
add-hook
dalam konteks di mana Anda tahu bahwa fungsi tersebut harus dieksekusi ketika hook dijalankan, dan biarkan fungsi itu sendiri menghapus dirinya sendiri dari hook, setelah fungsi melakukan hal tersebut.Jika saya menebak dengan benar tentang apa yang benar-benar Anda inginkan, maka silakan pertimbangkan untuk mengedit pertanyaan Anda untuk sesuatu seperti " Apakah ada cara untuk menjalankan fungsi hook hanya sekali?
Berikut ini adalah contoh, dari perpustakaan standar
facemenu.el
:sumber
Berikut ini adalah makro yang dapat Anda gunakan sebagai gantinya
add-hook
(tidak diuji secara luas):Catatan:
make-symbol
membuat simbol yang tidak diinginkan dengan nama yang diberikan. Saya menyertakan#
nama untuk menandai simbol sebagai sesuatu yang tidak biasa, kalau-kalau Anda menemukan itu sambil melihat variabel kait.sumber
(void-function gensym)
cl
paket. Maaf tentang itu - saya lupa bahwa tidak semua orang menggunakannya. Anda bisa menggunakannya(make-symbol "#once")
. Saya akan memperbarui jawabannya.Anda dapat membuat fungsi hiper
gen-once
untuk mentransformasikan fungsi normal ke fungsi yang hanya bisa berjalan sekali:lalu, gunakan
(add-hook 'xxx-mode-hook (gen-once your-function-need-to-run-once))
sumber