Як я можу відповісти на запит мінібуфера від elisp?


10

Іноді я опиняюсь як використовую інтерактивні функції всередині функції, яку я пишу для власного використання. Якщо функція вимагає певної інформації (наприклад, "Вихідний файл: ~ /"), чи існує загальний спосіб додавання тексту до мінібуфера, а потім натисніть клавішу Enter, щоб користувачеві не довелося цього робити?

Наприклад, припустимо, що я хочу запускати org-latex-export-to-pdfфункцію, але я не хочу, щоб користувач вказував ім'я файлу. Біг (org-latex-export-to-pdf)перемістить крапку в мінібуфер, але, (insert "filename.tex")здається, щось подібне на наступному рядку не здається.


3
Зазвичай інтерактивна функція повинна підказувати таку інформацію у своєму interactiveпункті. Коли ви телефонуєте з elisp, ви повинні мати можливість передавати інформацію як аргумент функції. Звичайно, це вам не допомагає, якщо функція, яку ви намагаєтеся викликати, не відповідає цій конструкції.
Ліндиданер

Так, я виявив, що так і зазвичай (на жаль, наразі не так), що може бути причиною відповіді на це так важко знайти. Чи знаєте ви, чи є причина дизайну, щоб дійсно бажати, щоб користувач вводив відповіді на підказки з minibuffer?
Сет Ротшильд

Ваш коментар для мене незрозумілий. Ви хочете, щоб користувач запитував, відповідав чи ні? Якщо ні, то програмно придумайте потрібні / потрібні значення аргументу (ім'я вихідного файлу) та передайте їх функції. Я пропоную вам показати якийсь код або іншим способом зробити конкретний і зрозумілий, у чому полягає ваша проблема та питання , або питання ризикує бути закритим як незрозумілий.
Дрю

Я не хочу, щоб користувач (мене) запитував. Я можу уточнити питання. Прочитавши частину теми електронної пошти, що стосується вас з декількох років тому про те, що я перебираю на мінібуфер, я думаю, що я знаю, як це зробити. Якщо я зроблю це робочим, напишу його.
Сет Ротшильд

1
Будь ласка, опублікуйте конкретний приклад інтерактивної функції, яку ви хочете використовувати під час написання власної функції, щоб інший учасник форуму міг продемонструвати, як передавати аргумент функції та повністю обходити мінібуфер.
законник

Відповіді:


3

Цікава проблема. Схоже, редактор запускається post-command-hookкожного разу, коли він вводить новий командний цикл, тобто a 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", із "привіт", вставленим першим рядком, "світ", вставлений через код lisp, і нарешті "RET", щоб закінчити введення.

Поставляється з тестовим набором, який ви можете переглянути для більше прикладів використання.


0

Здається, що за допомогою run-with-timerз допомогою 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. Рішення від конкретного випадку - це не те, що я шукаю. З вашого коментаря я можу зробити висновок, що це не рекомендується.
Сет Ротшильд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.