Як я можу відповісти на запит мінібуфера від 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.