Elisp'ten bir minibuffer istemine nasıl cevap verebilirim?


10

Bazen kendi kullanımım için yazdığım bir işlevin içindeki etkileşimli işlevleri kullanarak kendimi bulurum. Bir işlev bazı bilgiler isterse (örn. "Çıktı dosyası: ~ /"), mini öğeye metin eklemenin genel bir elisp yolu varsa ve daha sonra kullanıcının bunu yapmak zorunda kalmaması için enter tuşuna basın?

Örnek olarak, org-latex-export-to-pdfbir işlevin içinde çalıştırmak istediğimi ancak kullanıcının bir dosya adı belirtmesini istemediğimizi varsayalım . Koşmak (org-latex-export-to-pdf)noktayı minibuffer'a taşıyacak, ancak bir (insert "filename.tex")sonraki satıra benzer bir şey koymak işe yaramıyor gibi görünüyor.


3
Tipik olarak, etkileşimli bir fonksiyon kendi interactivecümlesinde bu tür bilgileri ister . Elisp'den çağrıldığında, bilgiyi bir işlev argümanı olarak iletebilmelisiniz. Tabii ki, bu size yardımcı olmaz, aramaya çalıştığınız işlevin bu tasarımı takip etmemesi durumunda.
Lindydancer

Evet, genellikle böyle olduğunu gördüm (maalesef şu anda değil), bu yüzden bunun cevabını bulmak çok zor olabilir. Kullanıcının minibuffer'ın istemlerine cevap yazmasını gerçekten istemenin bir tasarım nedeni olup olmadığını biliyor musunuz ?
Seth Rothschild

Yorumunuz net değil, bana göre. Kullanıcının sorgulanmasını ve yanıtlanmasını istiyor musunuz? Değilse, programlı olarak istediğiniz / ihtiyacınız olan bağımsız değişken değerlerini (çıktı dosyası adı) bulun ve bunları işleve iletin. Bazı kodlar göstermenizi veya başka bir şekilde sorununuzu ve sorunuzun ne olduğunu veya soru risklerinin net olmadığı için açık ve net olmasını öneririm .
Drew

Kullanıcının (ben) sorgulanmasını istemiyorum. Soruyu açıklığa kavuşturabilirim. Birkaç yıl önce minibuffer'a sorma ile ilgili bir e-posta dizisinin bir kısmını okuduktan sonra, bunun nasıl yapılacağını biliyorum. Çalıştırırsam yazarım.
Seth Rothschild

1
Lütfen kendi işlevinizi yazarken kullanmak istediğiniz etkileşimli işlevin belirli bir örneğini gönderin, böylece başka bir forum katılımcısı işleve nasıl bir argüman iletileceğini ve minibufferi tamamen atlayabileceğini gösterebilir.
hukukçu

Yanıtlar:


3

İlginç bir sorun. Editör, post-command-hookher yeni komut döngüsüne her girdiğinde çalışır , yani a recursive-edit. Ancak minibuffer-setup-hook, minibuffer'a girdikten sonra bir işlevi yürüten ile başlayabiliriz . Bu, girişin eklenmesine izin verirken, yakalayıcı henüz ayarlanmadığı için minibuffer'dan çıkmak için çok erken.

(defmacro with-minibuffer-input (form &rest inputs)
  (declare (indent 1))
  `(minibuffer-with-setup-hook
       (lambda ()
         (minibuffer-input-provider ',inputs))
     ,form))

Bu, 'argümanları' kendi 'komut döngümüzde' recursive-editsarmamız gerekti, bu da her girdiğimizde yürütülür , bu noktada bir argüman açar ve bir seviye yukarı atar exit-minibuffer.

;; -*- lexical-binding: t -*-
(defun minibuffer-input-provider (inputs)
  (let ((hook (make-symbol "hook")))
    (fset hook (lambda ()
                 (remove-hook 'post-command-hook hook)
                 (when inputs
                   (when (= 0 (minibuffer-depth))
                     (error "Too many inputs"))
                   (when (cdr inputs)
                     (add-hook 'post-command-hook hook))
                   (insert (pop inputs))
                   (exit-minibuffer))))
    (add-hook 'post-command-hook hook)))


(with-minibuffer-input (call-interactively 'find-file)
  "/")

(with-minibuffer-input (call-interactively 'occur)
  "\\(foo\\)\\(bar\\)" "\\1");;C-u C-x C-e

;;foobar

(with-minibuffer-input (call-interactively 'replace-string)
  "foo" "bar")

;; foo

3

Bu ad için bir makro yazdım with-simulated-input, buraya ulaşabilirsiniz . Kullanıcı etkileşimini simüle etmek için isteğe bağlı giriş sağlamanız ve isteğe bağlı lisp formları yürütmenizi sağlar.

Örneğin:

(with-simulated-input '("hello SPC" (insert "world") "RET")
  (read-string "Enter greeting: "))

"hello world"ilk dize tarafından eklenen "merhaba", lisp kodu aracılığıyla eklenen "dünya" ve son olarak girişi tamamlamak için "RET" ile dönecektir .

Daha fazla kullanım örneği için bakabileceğiniz bir test paketi ile birlikte gelir.


0

O kullanılarak görünüyor run-with-timerile insertişi alacaksınız.

(run-with-timer .2 nil 'insert "filename.tex")
(run-with-timer .3 nil 'execute-kbd-macro (kbd "RET"))
(org-latex-export-to-pdf)

Daha insertsonra yerleştirildiğinde komut çok hızlı bir şekilde geliyor. Eklenecek bir yer olmadan önce dizeyi eklemeye çalışır.


Kullanıcının dosya adı sorulmaması için org-export-output-file-name, kullanıldığında programlı olarak bir dosya adı geçirerek yardım istemek için sorunuzu gözden geçirmenizi tavsiye ederim org-latex-export-to-pdf. Çabalarınızı soruya koyabilirsiniz - örneğin, run-with-timervb. - Bu, iyi bir çözüm değildir (bence). Daha iyi bir çözüm, bir dosya adını program aracılığıyla düzgün bir şekilde iletmektir, böylece minibuffer asla ilk etapta açılmaz. Daha fazla elisptecrübesi olan biri tarafından daha iyi bir çözüm alabilmeniz için bu cevabı silmenizi tavsiye ederim .
hukukçu

@ lawlist, bir dosya adının nasıl aktarılacağı sorusu org-latex-export-to-pdfilgilendiğim değil. Bir örnek eklememe niyetim göründüğünden bir örnek. Sorduğum soru, kastettiğim bir soru: elisp aracılığıyla bir minibuffer istemine güvenilir bir şekilde cevap vermenin bir yolu var mı? Vakaya göre çözüm, aradığım şey değil. Yorumunuzdan, tavsiye edilmediğini çıkarabilirim.
Seth Rothschild
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.