Как создать интерактивную функцию elisp с дополнительными аргументами

Как вы пишете функцию elisp, которая должна быть привязана к нажатию клавиши, которая работает без подсказки по умолчанию, но когда предыдущая команда Ctrl-u запрашивает у пользователя аргумент. Что-то похожее (это неправильный синтаксис, но я надеюсь, что вы поняли эту идею)?

 (defun my-message (&optional (print-message "foo"))
   (interactive "P")
   (message print-message))
 (global-set-key "\C-c\C-m" 'my-message)

Ответ 1

Далее используется функция interactive, которая позволяет использовать код вместо строки. Этот код будет выполнен только тогда, когда функция будет вызвана в интерактивном режиме (что делает этот вариант другим ответом по сравнению с более ранним ответом). Код должен оцениваться в списке, в котором элементы сопоставляются с параметрами.

(defun my-test (&optional arg)
  (interactive (list (if current-prefix-arg
                         (read-from-minibuffer "MyPrompt: ")
                       nil)))
  (if arg
      (message arg)
    (message "NO ARG")))

Используя этот метод, эту функцию можно вызывать из кода типа (my-test) или (my-test "X"), не запрашивая приглашение пользователя. Для большинства ситуаций вы хотели бы спроектировать функции, чтобы они запрашивали ввод только при интерактивном вызове.

Ответ 2

Следуя такой же реализации, как и ваш пример, вы можете сделать что-то вроде этого:

(defun my-message (&optional arg)
  (interactive "P")
  (let ((msg "foo"))
    (when arg
      (setq msg (read-from-minibuffer "Message: ")))
    (message msg)))

Ответ 3

Если вы просто хотите использовать эту функцию как интерактивную, этот код вам нужен:

(defun my-message (&optional ask)
  (interactive "P")
  (message (if ask
               (read-from-minibuffer "Message: ")
             "foo")))