elispからミニバッファープロンプトに応答するにはどうすればよいですか?


10

自分で使用するために記述している関数の内部で、インタラクティブな関数を使用していることがあります。関数がいくつかの情報を要求する場合(たとえば、「出力ファイル:〜/」)、ミニバッファーにテキストを追加し、Enterキーを押してユーザーがそうする必要がないようにする一般的なelisp方法はありますか?

例として、org-latex-export-to-pdf関数内で実行したいが、ユーザーがファイル名を指定する必要がないようにしたいとします。実行(org-latex-export-to-pdf)するとポイントがミニバッファーに移動しますが(insert "filename.tex")、次の行に何かを置くことは機能しないようです。


3
通常、インタラクティブ関数は、そのinteractive句でそのような情報を要求する必要があります。elispから呼び出されると、情報を関数の引数として渡すことができるはずです。もちろん、これはあなたが助けようとしている関数がこの設計に従っていない場合、あなたを助けません。
Lindydancer 2015年

ええ、私は通常(残念ながら現時点ではそうではありません)の場合もそうであることがわかりました。ユーザーにミニバッファーからのプロンプトへの回答を実際に入力してほしいという設計上の理由があるかどうかを知っていますか?
セスロスチャイルド

あなたのコメントは不明瞭です。ユーザーにクエリを実行して応答させたいですか?そうでない場合は、プログラムで必要な引数値(出力ファイル名)を考え出し、それらを関数に渡します。コードを表示するか、他の方法で問題と質問を具体的かつ明確にすることをお勧めします。または、質問のリスクが不明確であるとして閉じられます。
2015年

ユーザー(私)に照会したくない。質問を明確にすることができます。数年前からミニバッファーへのヤンキングについてあなたを巻き込んだメールスレッドの一部を読んだ後、私はこれを行う方法を知っていると思います。うまくいけば、書きます。
セスロスチャイルド

1
別のフォーラム参加者が関数に引数を渡し、ミニバッファーを完全にバイパスする方法を示すことができるように、独自の関数を作成するときに使用するインタラクティブ関数の具体例を投稿してください。
弁護士、2015年

回答:


3

興味深い問題。エディタpost-command-hookは、新しいコマンドループ、つまりrecursive-edit。に入るたびに実行されるようです。しかしminibuffer-setup-hook、ミニバッファーに入った後で関数を実行するから始めることができます。これは入力の挿入を可能にしますが、キャッチがまだ設定されていないため、ミニバッファーを終了するには早すぎます。

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

我々は、GETのは、我々が入るたびに実行され、私たち自身の「コマンドループ」、の「引数のラップする必要があったことをrecursive-edit経由して、それは一つの引数をポップし、1つ上のレベルに投げた時点では、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

これを呼び出すためのマクロを作成しました。これはここからwith-simulated-input取得できます。これにより、ユーザーの相互作用をシミュレートするために、任意の入力を提供したり、任意のlispフォームを実行したりできます。

例えば:

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

"hello world"最初の文字列によって「hello」が挿入され、lispコードを介して「world」が挿入され、最後に「RET」が返されて入力が終了します。

それはあなたがより多くの使用例を見ることができるテストスイートが付属しています。


0

run-with-timerwith を使うinsertことで仕事が終るようです。

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

コマンドをinsert後で配置すると、すぐに表示されます。文字列を挿入する場所がなくなる前に文字列を挿入しようとします。


ユーザーがファイル名の入力を求められないように、org-export-output-file-name使用時にプログラムでファイル名を渡す支援を求めるために質問を修正することをお勧めしますorg-latex-export-to-pdf。質問run-with-timerなどに努力を払うことはできますが、それは(私の意見では)良い解決策ではありません。より良い解決策は、プログラムでファイル名を適切に渡して、ミニバッファーが最初から開かないようにすることです。この回答を削除して、よりelisp経験のある人がより良い解決策を得ることができるようにしてください。
弁護士、2015年

@lawlistファイル名をどのように渡すかという質問はorg-latex-export-to-pdf私が興味を持っているものではありません。あなたが私にファイル名を追加することに熱心であるように思われたので、それは例です。私が尋ねた質問は私が意味したものです:elispを介してミニバッファプロンプトに確実に応答する方法はありますか?ケースバイケースの解決策は、私が探しているものではありません。あなたのコメントから、私はそれが推奨されていないと推測できます。
セスロスチャイルド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.