Daemon modu: Başlangıçta etkileşimli istemler ertelensin mi?


16

(Aksine, bu sorunun, belirli bir istemin görünmesine neden olan şeyi ortadan kaldıran gönderici tarafından "yanıtlandığı" gibi, bu soru daemon modunda nasıl başlatılır ve etkileşimli iletişim kutuları bastırılır?) İle aynı değildir .)

Henüz var olmayan bir minibuffer'da görüntülenen bir bilgi istemine cevap beklemek için sonsuza dek asılı kalmanın genel bir yolu olup olmadığını bilmek istiyorum emacs --daemon.

Emacs başlatma sırasını tamamlayana kadar sunucu başlatılmadığından, bu istemleri yanıtlamak için bir emacsclient ile bağlanmak imkansızdır. (Bu, boş dizeye ALTERNATE_EDITOR ayarlanmışsa, emacsclientsunucunun yeni bir arka plan programı başlatmasını bulamayan bir hale getirirse, tüm sıkışmış ve bekleyen birden çok Emacs arka plan programı ile karşılaşabilirsiniz.) killall emacsSorunu düzeltmek zorundayım devam etmeden önce.

Ben tanımlamak zaman başlangıçta bir istem neden whack-a-köstebek oynayabilir (daemon modunda modunda Emacs başlatarak ve ne istediğini görerek), ama bir çözüm değil çünkü bir sonraki daemon durduramaz yeni bir nedenden dolayı başlangıçta asılı kalmaktan.

Bir örnek vermek gerekirse, askıda kalmasının yaygın bir nedeni, bir sistem yeniden başlatıldıktan veya Emacs çökmesinden sonra, ilk yeniden başlatma sonrası Emacs'ın geçersiz Emacs'tan kilit dosyalarını çalmanın uygun olup olmadığını bilmek istediği zamandı. Bu istemin her zaman etkileşim olmadan "evet" yanıtı vermesini sağlayacak tavsiyeler oluşturarak bunu düzeltebilirim. Ama sonra, önceki oturumda kaydedilen dosyalardan biri sudo veya SSH parolası gerektiren bir TRAMP dosyasıydı, bu yüzden daemon bir parola isteminde bekletildi. Bu yüzden , rahatsız edici dosyaları kaldırmak için oturum dosyasını ( viveya emacs -q! İle) elle düzenleyerek düzeltiyorum - ancak bir dahaki sefere olmasını engellemiyor.

Böylece, oturumumu başlangıçta otomatik olarak yüklemeyi durdurabilir ve ilk emacsclient'imden manuel olarak yürütmem gereken bir komuta değiştirebilirim. Ancak oturumumu arka planda yüklemiyorsa, kullanmaya hazır olduğum zaman hazırdır, artalan sürecinin tüm amacı kaybolur!

Yani ne istiyorum:

  • (En İyi) Minibuffer istemlerini ertelemenin bir yolu, bir başlatma işlemini tamamlarken hala bir emacclient açana kadar.
  • (OK) Yukarıda açıklandığı gibi tavsiye etmediğim tüm minibuffer istemlerini noyapmanın bir yolu, bir emacclient çalışmadığı sürece geri dönmektir. TRAMP arabellekleri çoğunlukla çalıştığı sürece hata vererek yaşayabilirim.

Bu hedeflerden herhangi birine ulaşmanın bir yolu var mı?


Topluluğun sorun giderebilmesi için bu tür sorunları programlı olarak yeniden oluşturmanın bir yolu var mı?
Melioratus

1
İlk satırda yazdığım gibi, verilen bir örneği düzeltmek oldukça kolay ... "Doktor, bunu yaptığımda acıyor ..." "O zaman bunu yapma." Sorun genel durum. Ama sorunu oluşturmak için basit bir yol aracılığıyla masaüstü yeniden başlatma sahip olmaktır (read-desktop)çalıştırmadan önce, o zaman, emacs --daemoniçine bir tamsayı koyarak sahte kilit dosyası oluşturmak .emacs.desktop.lock nerede ( koymak bu dosyayı maalesef senin yapılandırmasına bağlıdır , ama muhtemelen ya homediriniz ya da ~ / .emacs.d / .
Trey

1
Bu, burada sıkça bahsedilen bir durumdur, örneğin: emacs.stackexchange.com/questions/8147/… veya emacs.stackexchange.com/questions/31621/… bağlam sağlayabilir.
Trey

Bu hata ilgili görünüyor: Hata # 13697 - Emacs kullanıcı ile etkileşime girip giremeyeceğini anlamanın bir yolu , ama bildiğim kadarıyla kimse üzerinde çalıştı.
npostavs

@npostavs Bağlantı için teşekkürler - Hatayı açıkladım, ancak anlayabilmem için buraya (silindiğinden beri) yorum yaptığım yanlış bir başlangıç ​​yaptım!
Trey

Yanıtlar:


2

Tartışmamız , bunu çalıştıran herhangi bir X sunucunuz olmadığını, ilk çözümümü sizin için işe yaramaz hale getirdiğini açıkladı.

Aşağıda metin terminal çerçeveleriyle çalışan ikinci bir çözüm sunacağım.

Başlatma işleminiz birinden kullanıcı girişi gerektirdiğinde, avoid-initial-terminalEmacs ile önerilen işlevler bir metin terminal çerçevesi açılana kadar bekler. Bilgi istemi o karenin minibuffer'ında görünür ve etkileşimli yanıtınızı verebilirsiniz.

Kodla ilgili bilgiler kodda yorum olarak verilir. TODOKendi yapılandırmanızı nereye ekleyeceğinizi gösteren açıklamalara sahip işaretçiler vardır . Şu anda orada kodu doğrulayan test formları var.

;; TODO: Do here configure the server if needed.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Startup the server:
;; Analysis of read_from_minibuffer in src/minibuf.c and daemon_type in src/emacs.c
;; shows that daemon-initialized must have run before read-passwd / read-string
;; works on frames. Before it only works on stdin & stdout.
(server-start) ;;< early start
(let ((after-init-time before-init-time))
  (daemon-initialized)) ;; Finalize the daemon, 

(advice-add 'daemon-initialized :override #'ignore)
;;< Ignore `daemon-initialized' after initialization. It may only run once!
;; Now the background emacs is no longer marked as daemon. It just runs the server.

(defun prevent-server-start (&rest _ignore)
  "Prevent starting a server one time after `server-start' has been advised with this."
  (advice-remove 'server-start #'prevent-server-start))

(advice-add 'server-start :override #'prevent-server-start)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Prepare waiting for a real terminal frame when user input is required:

(defun avoid-initial-terminal (fun &rest args)
  "Wait until we are no longer on \"intial-terminal\".
Afterwards run `fun' with frame on the other terminal selected."
  (message "Avoiding initial terminal. Terminal: %S" (get-device-terminal nil))
  (while (string-equal
      (terminal-name (get-device-terminal nil))
      "initial_terminal")
    (sleep-for 1))
  ;; (message "Selected frame: %S; Running %S with %S." (selected-frame) fun args)
  (apply fun args))

(advice-add 'read-string :around #'avoid-initial-terminal)

(advice-add 'read-passwd :around #'avoid-initial-terminal)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TODO: Your initialization that is not daemon related
;; and may require user input:

;; Currently this is just a test.
(read-passwd "Passwd: ")

(read-string "String: ")

(y-or-n-p "y-or-n query")

Test: Emacs sürümü: 26.1

1) emacs --daemonBir konsolda çalıştırın .

2.) emacsclient --ttyBaşka bir konsolda çalıştırın . Orada bir parola ve bir dize girmeniz istenir. Daha sonra, bir y veya np sorgusunu da yanıtlamanız gerekir.


3

Tam olarak ne istediğinizi değil, belki de orijinal sorununuza bir çözüm:

Emacs - daemon'un sonsuza kadar asılı kalmasını engellemenin genel bir yolu olup olmadığını bilmek istiyorum, henüz mevcut olmayan bir minibuffer'da görüntülenen bir isteme bir cevap bekliyorum.

Eğer arka plan programı size başlangıç ​​aşamasında ortaya çıkan soruları cevaplamak için grafiksel bir çerçeve verirse, artık takılı kalmazsınız.

Aşağıdaki kod my-with-initial-frame, kullanılabilir ilk ekranda (örn :0.0.) Bir çerçeve açan genel bir tavsiyeyi tanımlar .

Bu tavsiye, aşağıda gösterildiği gibi y-or-n-pveya gibi sorgu komutlarına kolayca eklenebilir read-passwd.

Sadece bir çerçeve açmak, kullanıcı arayüzündeki soruları cevaplamak için oldukça kaba bir olasılık sağlar. Bir iletişim kutusu da kullanılabilir, y-or-n-pancak bu belirli sorgulama komutları için özel çözümler gerektirir. Bundan kaçınmak istedim.

Bu kodu init dosyanızda denerseniz, orada ilk şey olduğundan emin olun.

(when (daemonp)

  (defun my-with-initial-frame (&rest _)
    "Ensure a frame on display :0.0 and ignore args."
    (let* ((display-list (x-display-list))
           (display-re (and display-list (regexp-opt display-list)))
           (term (and display-re (cl-some (lambda (term) (and (string-match display-re (terminal-name term)) term)) (terminal-list))))
           (frame (and term (cl-some (lambda (frame) (and (frame-live-p frame) frame)) (frames-on-display-list term)))))
      (select-frame (or frame (make-frame-on-display (getenv "DISPLAY"))))))

  (message "Advising querying functions with `my-with-initial-frame'.")
  (advice-add 'y-or-n-p :before #'my-with-initial-frame)
  (advice-add 'read-passwd :before #'my-with-initial-frame))

Ölçek:

Varsayımlar:

Programların DISPLAYortam değişkeni üzerinden bağlanabildiği çalışan bir xserver'a sahip olun .

Xterm'de giriş:

emacs --daemon

emacsclient --eval '(y-or-n-p "A")'

y-or-n-pSorgu istemi içeren bir çerçeve açılır A (y or n). Bu sorguyu yanıtlayın ve tekrar deneyin:

emacsclient --eval '(y-or-n-p "B")'

B (y or n)Aynı çerçevedeki bilgi istemiyle yeni sorgu . Bu çerçeveyi, örneğin ile kapatın C-x 5 0ve tekrar deneyin:

emacsclient --eval '(y-or-n-p "C")'

Sorgu istemiyle yeni bir çerçeve açılır C (y or n).

Aynı şey şifre girişi için de geçerlidir.


@Trey Kodumla ilgili bir sorunum vardı (aslında testle). X sunucusunu başlatmak ilk kez çalışmadı. Daemon'u yeniden başlatmadığım için başlangıçta fark etmedim. Bunu şimdi düzelttim. Lütfen tekrar test edin. Teşekkürler.
Tobias

Linux sanal bilgisayarımın bağlı bir grafik terminali yok, bu yüzden çalışamıyorum xterm. Ayrıca, bu çözümün yapanlar için işe yarayacağını düşünmüyorum - başlangıçta çalıştırılacak olan arka plan programınız varsa, giriş ekranının üstünde izin verilmeyen bir çerçeve açmaya çalışır, bu yüzden çöker.
Trey

Tobias, eğer yukarıdakiler kaba geldiyse özür dilerim - Telefonuma cevap verdim ve kendimi kısa kesmiş olabilirim, bu yüzden detaylandırmaya çalışmama izin verin: Daemon'u kullanmama ve server-startbaşlangıç ​​sonunda çalıştırma konusunda açıkladığınız tek avantaj bunun yerine, temiz bir başlangıç ​​yaparsanız, beklemek zorunda kalmazsınız. Ama ... beklemeniz gerekecek, çünkü yanlış anlamazsam, bir GUI kullanılamayacağından Emacs arka plan programını sistem oturum açma komut dosyanıza başlatmak için görev koyamazsınız. (Ve benim gibi bir durumda, daha sonra asla olmayacak.)
Trey

@Trey Sohbete katılabilir misiniz ?
Tobias

1

Ben istemleri ertelemek genel olarak zor olacağını düşünüyorum , ama Emacs değiştirmek oldukça kolay olmalı, böylece bu tür istemler hemen bir hata sinyali.

Sadece bu değil, aynı zamanda çok fazla jimnastik olmadan bu sorulara cevap veremiyorsanız, bunun bir hata olarak nitelendirildiğini düşünüyorum, bu yüzden bunun için bir hata raporu göndermenizi tavsiye ederim.


Sanırım biraz daha ayrıntıya ihtiyacım var. Yukarıdaki ödülün yorumunda bahsettiğim masaüstü kayıt dosyası kilidini düşünün. Bir değiştirme hakkında nasıl gitmek Warning: desktop file appears to be in use by PID xxx. Using it may cause conflicts. Use it anyway? (y or n), bir hata içine istemi olmadan özellikle bir şekilde "masaüstü" atıfta (çünkü bu şekilde, nongeneral olma, yalan saçma-a-köstebek)?
Trey

Stefan, ayrıca beni rahatsız etmeyen bir sorun var, çünkü Emacs arka plan programını bu şekilde çalıştırmıyorum, ancak genel olarak yararlı bir cevap vermek için adresleme gerekebilir: ölümcül bir şekilde hata yapmak Emacs'ın sistemd veya diğer bekçi köpekleri aracılığıyla yeniden başlatılmasına neden olur bir döngü içinde. Ancak hataları göz ardı etmek ve sadece oturum açmak *Messages*, ilk istemcide, kullanıcının herhangi bir durumdaki işlemi denemeden önce bir şeyin ciddi bir şekilde kötü olabileceğini ve derhal ilgilenilmesi gerektiğini düşünmesi için yetersizdir.
Trey

(Daemon'u kullanmayanları açıklığa kavuşturmak için — manuel olarak başlatırsanız emacs --daemonveya boş dizeye ayarlanmış ortam değişkeni emacsclientile başlayarak ALTERNATE_EDITOR, normalde *Messages*terminalde yankılamaya giden çıkışı görürsünüz. başlatmayı tamamlar ve Emacs hazırdır, ancak birçoğu Emacs'ın sistem açılışında veya oturum açma saatinde arka plan programını başlatmasını sağlar ve çıktı kaydedilir ya da atılır
Trey

1
@Trey: hata sinyali değil desktop, y-or-n-pişlevde (veya daha düşük) olmalıdır. Başlangıç ​​sırasında meydana gelen hataları görüntülemeyi geciktirmek için bazı mekanizmalarımız var, bu yüzden ilk emacclient daemon'a bağlandığında bunları görüntülemek için kullanabiliriz.
Stefan

Bununla birlikte, her iki durumda da, çoğu kullanıcı algılamamaktadır *Messages*- ve az kullanılan *Warnings*sistem , uyarı oluşturulduğunda etkin bir çerçeve varsa, bu durumda hiçbir çerçeve yoksa ve uyarı sorununu izleyen ilk emacclient kadar pop-up ertelemek kolay görünmüyor. Bu yapılabilirse, bir müşteri öncesi yes-or-no-puyarısı yapma öneriniz oldukça ideal olacaktır. (Kullanıcılar *Messages*başlangıçta taraktan şüpheliyim !)
Trey
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.