Panggil emacsclient dari program yang disebut oleh Emacs

9

Saya mengalami masalah saat melihat file dokumentasi pdf dengan AucTex. Saya gunakan pdf-toolsuntuk melihat file PDF dari dalam Emacs, dan saya telah menetapkan emacsclient -nsebagai pdf-viewer default saya (via xdg-mime di Debian Linux). Ini berfungsi dengan baik di sebagian besar keadaan, tetapi itu merusak (Tex-documentation-texdoc ...)fungsi Auctex ( C-c ?).

Saya telah mempersempit masalahnya menjadi satu baris kode. Ketika saya mencoba melihat dokumentasi untuk listingspaket, TeX-documentation-texdocubah ini menjadi sexp berikut:

(shell-command-to-string "texdoc --view  listings")

texdocpada gilirannya panggilan emacsclientuntuk benar-benar membuka file (berdasarkan bagaimana saya mengkonfigurasi desktop saya via xdg). Namun, pada titik ini, Emacs hang dan saya harus berhenti ( C-g) untuk mendapatkan kontrol kembali. Setelah itu, tidak ada pdf baru dibuka. Hal yang sama terjadi jika saya mencoba memanggil emacsclient secara langsung:

(shell-command-to-string "emacsclient -n tmp.pdf")

Kedua perintah bekerja di baris perintah (yaitu, emacsclient -n tmp.pdfdan texdoc --view listings.

Pertanyaan saya adalah, dalam contoh seperti ini, bagaimana saya memanggil emacsclient dari dalam Emacs? (dan saya tahu saya bisa membuka file pdf dengan find-file; itu bukan pilihan di sini karena saya perlu memanggil proses eksternal (texdoc) untuk menemukan file, dan proses itu kemudian memanggil emacsclient).

Tyler
sumber
Mengapa tidak gunakan saja texdoc -M --list listingsuntuk mencari file, lalu gunakan find-file?
Quarky
@suvayu Hanya kenyamanan. Alternatif lain adalah beralih ke terminal untuk memanggil texdoc --viewdan kemudian beralih kembali ke Emacs ketika membuka file. Tapi saya pikir harus ada cara untuk melakukan ini dalam satu langkah dari Emacs?
Tyler
1
Bisakah (async-shell-command "emacsclient -n tmp.pdf")memecahkan masalah?
Sebutkan
1
@Name menarik - (async-shell-command "emacsclient -n tmp.pdf")berfungsi, tetapi tidak (async-shell-command "texdoc --view listings")tidak. Jadi itu petunjuk yang berguna.
Tyler
1
Apakah C-u C-c ?bekerja? Pertama-tama menunjukkan daftar dokumen yang terkait dengan paket, kemudian membuka pemirsa dengan (call-process "texdoc" nil 0 nil "--just-view" doc).
giordano

Jawaban:

5

Solusinya adalah berjalan texdocdalam proses asinkron.

Cara terbaik untuk melakukannya adalah dengan menggunakan start-file-processalih-alih shell-command-to-string(yang merupakan fungsi praktis untuk kode cepat & kotor ketika lebih baik untuk menulis skrip shell kecil daripada kode Elisp yang sesuai, tetapi sebaliknya lebih baik dihindari dalam pengalaman saya).

Tapi itu akan membutuhkan perubahan besar pada kode di sekitarnya, karena start-file-processtidak mengembalikan output proses secara langsung, sebaliknya ia memungkinkan Anda menunjukkan di mana buffer untuk menempatkan output dan kemudian Anda harus menggunakan set-process-sentinelfungsi callback yang mengambil output dari buffer itu dan tidak "apa pun yang perlu dilakukan dengan itu" ketika perintah selesai.

Stefan
sumber
Dalam kasus spesifik menjalankan texdocdi AUCTeX saya menemukan penggunaan sentinel sedikit berlebihan, karena ini bukan fitur mendasar (seperti itu adalah pembukaan penampil untuk dokumen output, dalam hal ini kita menggunakan penjaga).
giordano
Saya tidak tahu mengapa fungsi "-to-string" digunakan, jadi saya tidak tahu apa yang dilakukan dengan output perintah. Jika output ini diperlukan (seperti yang disarankan oleh penggunaan ...-to-string), maka solusi async akan membutuhkan proses-filter atau proses-sentinel. Jika tidak, maka kodenya mungkin bisa menggunakan sesuatu seperti (shell-command "texdoc --view listings &").
Stefan
Dijelaskan dalam komentar untuk TeX-documentation-texdoc: ...-to-stringvarian digunakan untuk menunjukkan kepada pengguna kemungkinan pesan kesalahan (misalnya ketika tidak ada dokumentasi yang ditemukan). Selain itu, texdoc nonexistingpackagemengembalikan 0, tetapi sentinel dapat digunakan untuk mem-parsing output.
giordano
Kemudian seorang penjaga tampaknya menjadi pilihan terbaik.
Stefan
Saya tidak dapat menemukan doa start-file-processyang benar-benar berfungsi di sini. (start-file-process "texdoc" "*texdoc*" "texdoc" "--view" "listings")menciptakan buffer *texdoc*, yang dimasukkan "Proses texdoc selesai", dan pdf tidak pernah terbuka. Hal yang sama terjadi ketika saya mengatur penampil pdf xdg-mime untuk membuktikan juga.
Tyler
1

Jika Anda hanya perlu mengumpan balik permintaan ke Emacs, tanpa menunggu jawaban, maka Anda dapat menjalankannya emacsclientdi latar belakang. Di bawah OS Unix-style (Linux, macOS, Cygwin, ...):

emacsclient … &

Di bawah Windows asli:

start emacsclient …
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Tentu, tetapi dalam kasus khusus ini saya perlu memanggil program (texdoc) yang kemudian memanggil (emacsclient). Tingkat pengalihan tambahan menyebabkan masalah.
Tyler
@Tyler texdocasynchronous (artinya Anda tidak menunggu sampai selesai), bukan? Jadi Anda bisa menerapkan prinsip yang sama: jalankan texdoc … &sebagai perintah shell.
Gilles 'SANGAT berhenti menjadi jahat'
Kami mencobanya di komentar di bawah pertanyaan saya; ini berfungsi saat menelepon emacsclientlangsung, tetapi tidak saat menelepon texdoc.
Tyler