如何从elisp回答minibuffer提示?


10

我偶尔会发现自己在自己编写的函数内部使用交互函数。如果某个函数要求提供某些信息(例如“输出文件:〜/”),是否有一种通用的省略号方式可将文本添加到小型缓冲区中,然后按Enter键,以便用户不必这样做?

例如,假设我想org-latex-export-to-pdf在函数内部运行,但是我不想用户必须指定文件名。运行(org-latex-export-to-pdf)会将点移动到迷你缓冲区,但是(insert "filename.tex")在下一行放置类似内容似乎无效。


3
通常,交互式功能应在其interactive子句中提示输入此类信息。从elisp调用时,您应该能够将信息作为函数参数传递。当然,如果您尝试调用的函数未遵循此设计,这对您没有帮助。
Lindydancer

是的,我发现通常也是如此(不幸的是现在不是这样),这也许就是为什么很难找到答案的原因。你知道,如果有一个设计的原因真的希望用户键入了答案,从迷你缓冲区中提示?
塞斯·罗斯柴尔德

对我来说,您的评论不清楚。是否要查询用户并做出响应?如果不是,则以编程方式提供您想要/需要的参数值(输出文件名),并将其传递给函数。我建议您显示一些代码或以其他方式使您的问题和问题具体化,并弄清楚是什么,否则问题可能会因为不清楚而被关闭。
画了

我不希望查询用户。我可以澄清这个问题。在阅读了几年前涉及您的有关拉到微型缓冲区的电子邮件线程的一部分之后,我想我知道该怎么做。如果我能正常工作,我会写出来。
塞斯·罗斯柴尔德

1
请张贴一个您要在编写自己的函数时使用的交互式函数的特定示例,以便其他论坛参与者可以演示如何将参数传递给该函数并完全绕过小型缓冲区。
法律学家

Answers:


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))

那就是我们需要将“参数”包装在我们自己的“命令循环”中,每次我们输入a时都会执行recursive-edit该参数,这时它会通过弹出一个参数并向上一级抛出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经验的人获得更好的解决方案。
法律学家

@lawlist如何将文件名传递给org-latex-export-to-pdf我的问题不是我感兴趣的问题。这是一个示例,因为您似乎有意向我添加文件名。我问的问题是我的意思:有没有办法通过elisp可靠地回答minibuffer提示。逐案解决方案不是我想要的。从您的评论中,我可以推断出不建议这样做。
塞斯·罗斯柴尔德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.