Setara dengan --tidak menunggu emacs

8

The emacsclientProgram memungkinkan bendera --no-wait(disingkat -n) yang akan menyebabkan emacs server untuk mengunjungi file yang ditentukan, dan segera kembali.

emacsclient -n ~/.bashrc

Jika saya menyediakan editor alternatif, maka ini akan tetap berfungsi dalam kasus di mana tidak ada server Emacs yang berjalan

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc

Namun, ini memberi saya perilaku tidak konsisten karena dalam kasus di mana server sedang berjalan, panggilan ini akan segera kembali. Dalam kasus di mana tidak ada server yang berjalan, dan editor alternatif digunakan, panggilan menjadi panggilan yang memblokir, dan tidak akan kembali sampai saya keluar dari Emacs.

Apakah ada cara untuk memberitahu emacs(sebagai lawan emacsclient) untuk membuat bingkai baru dan kemudian kembali?

nispio
sumber
1
Sepertinya Anda merasa nyaman memberikan Emacs sebagai editor alternatif Anda. Apakah ada alasan Anda memilih untuk tidak menggunakan opsi -a '', "mulai daemon Emacs dan coba lagi emacsclient"?
purple_arrows
@purple_arrows Dalam pengalaman saya, menggunakan -a ''akan memulai daemon alih-alih server. Kemudian ia mencoba untuk membuka terminal Emacs, tetapi karena saya telah memberikan -nopsi, ia tidak tetap terbuka. Itu hanya memantul kembali ke shell.
nispio

Jawaban:

6

Deskripsi

Perilaku default saat menjalankan emacsclient sedikit konservatif. Lihat komentar ini dari emacsclient.c :

  /* Unless we are certain we don't want to occupy the tty, send our
     tty information to Emacs.  For example, in daemon mode Emacs may
     need to occupy this tty if no other frame is available.  */

Dari uraian dan komentar Anda, sepertinya Anda mencoba memulai server Emacs sesuai permintaan sementara juga menggunakan -nflag. Komentar "misalnya" di sini adalah mengapa emacsclient -n -a '' FILEtidak memenuhi apa yang Anda cari ketika tidak ada server yang berjalan.

  1. The -a ''logika dijalankan daemon.
  2. Kemudian emacsclientkatakan itu untuk membuat bingkai terminal baru, karena itu default kecuali Anda mengevaluasi elisp.
  3. The -nlogika segera membunuh kerangka terminal baru.

Jika Anda dapat mengubah Langkah 2 untuk membuat bingkai grafis baru secara default, maka emacsclient -n -a '' FILElakukan apa yang Anda inginkan.

Solusi Elisp

Anda dapat menyebabkan Emacs untuk membuat bingkai grafis baru secara default jika Anda menyarankan fungsi server-process-filterseperti:

(defadvice server-process-filter (before prefer-graphical activate)
  ;; STRING is a sequence of commands sent from emacsclient to the server.
  (when (and
         ;; Check that we're editing a file, as opposed to evaluating elisp.
         (string-match "-file" string)
         ;; Check that there are no frames beyond the Emacs daemon's terminal.
         (daemonp)
         (null (cdr (frame-list)))
         (eq (selected-frame) terminal-frame)
         ;; Check that we have a graphical display.
         ;; `display-graphic-p' doesn't work here.
         (getenv "DISPLAY"))
    (setq string (concat
                  ;; STRING must be all one line, but comes to us
                  ;; newline-terminated.  Strip off the trailing newline.
                  (replace-regexp-in-string "\n$" "" string)
                  ;; Add the commands to create a graphical frame.
                  "-window-system "
                  "-display " (getenv "DISPLAY")
                  ;; Add back the newline.
                  "\n"))))

Masukkan itu ke dalam file init Anda, lalu, seperti yang dikatakan, emacsclient -n -a '' FILEdan Bob adalah paman Anda.

Bandingkan dengan Solusi Shell

Di satu sisi, saya bisa menunjukkan beberapa keuntungan menggunakan pendekatan defadvice ini dibandingkan dengan menggunakan skrip yang disarankan oleh Archenoth

#!/bin/bash
emacs --eval '(server-start)' $* &

sebagai editor alternatif. Dengan defadvice:

  1. save-buffers-kill-terminal( C-x C-csecara default) berperilaku konsisten di semua bingkai. Itu tidak pernah membunuh proses Emacs, karena setiap frame selalu merupakan bingkai klien.
  2. Bingkai terminal daemon menggantung. Perintah seperti find-grepitu keluar untuk proses eksternal berperilaku lebih baik ketika terminal bisu ada. Setidaknya, saya mengalami lebih sedikit sakit kepala terkait shell yang lepas.

Di sisi lain ... ya.

  1. Script shell itu sangat sederhana.
  2. Nasihat protokol komunikasi Emacs tidak.

Kesimpulan

Mungkin ada kompromi? Ini adalah yang terbaik yang bisa saya pikirkan. Anda menetapkannya sebagai $ EDITOR Anda.

#!/bin/sh

emacsclient -e "(frames-on-display-list \"${DISPLAY}\")" 1>/dev/null 2>/dev/null
if [ "$?" = "1" ]; then
    emacsclient -c -n -a "" "$@"
else
    emacsclient -n "$@"
fi
purple_arrows
sumber
Jadi, bagaimana saya menyarankan fungsi ketika emacs tidak berjalan?
nispio
Anda seharusnya bisa memasukkannya ke file init. Daemon membaca file itu ketika mulai dan selesai membaca sebelum emacsclient mulai mengirim perintah. Setidaknya itulah yang saya lakukan.
purple_arrows
4

Saya tidak yakin bagaimana melakukannya dengan ketat di dalam Emacs, tetapi untungnya ada cara lain untuk mendapatkan apa yang Anda gambarkan.

Jika Anda tidak memiliki sesuatu .emacsuntuk memulai server, Anda selalu dapat membuat skrip kecil yang memulai Emacs dengan file yang ingin Anda edit dan memulai server bercabang.

Sesuatu seperti:

#!/bin/bash
emacs --eval '(server-start)' $* &

Dan kemudian meneruskannya ke -a.


Namun ...
Jika server Anda mulai .emacs, Anda tidak perlu membuat skrip; Anda memiliki opsi yang sedikit lebih singkat:

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc &

Ampersand akan melatarbelakangi proses dan langsung mengembalikan shell Anda, bahkan ketika Emacs mulai untuk pertama kalinya.

Anda mungkin harus disownmemprosesnya jika bash membunuh pekerjaan saat keluar. Jika itu masalahnya, Anda cukup menambahkan a disownsampai akhir:

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc & disown

Di Windows, padanan terdekatnya adalah " start" perintah ...

Jadi, seperti saran skrip di atas, Anda mungkin harus membuat file batch yang berisi sesuatu seperti:

start /b C:\path\to\emacs %*

Dan kemudian tunjukkan -aargumen itu.
Itu harus menjalankan file batch dan segera kembali setelah memulai Emacs dengan file yang sesuai.

Archenoth
sumber
Saya menggunakan Linux (RHEL 6.5), dan &merupakan hal pertama yang saya coba. Sayangnya, teks berikut dikirim ke stderr: dan kemudian terminal memblokir proses menunggu untuk berakhir: emacsclient: can't find socket; have you started the server? To start the server in Emacs, type "M-x server-start". Saya menduga bahwa emacsclientfork menjadi latar belakang, tetapi kemudian memanggil emacsyang akan dibuka di latar depan.
nispio
Kalau begitu, mungkin skrip kecil mungkin rute terbaik ..? Sesuatu seperti emacs --eval '(server-start)' $* &mungkin? Dengan begitu server mulai, Anda mendapatkan terminal Anda, dan emacsclientmemiliki server yang dapat dihubungkan.
Archenoth
Saya sudah mengujinya dan menambahkannya ke jawaban saya ... Maaf tentang itu! Saya pikir Anda memiliki mekanisme untuk memulai server ketika Anda menjalankan emacscara normal. Saya sadar kebanyakan orang mungkin tidak akan memiliki konfigurasi itu, jadi itu sekarang bagian pertama dari jawabannya. Semoga ini bisa membantu ..!
Archenoth
@nispio atur parameter editor alternatif Anda untuk & di akhir.
Malabarba
2
@ Malabarba Anda tidak bisa meneruskan argumen baris perintah atau arahan shell ke editor alternatif, itulah sebabnya saya menyarankan skrip kecil.
Archenoth