Как вызвать интерактивную функцию Emacs Lisp с аргументом префикса, из другой функции Emacs Lisp?

Я хочу написать функцию Emacs Lisp, которая включит flyspell-mode независимо от текущего состояния режима. Функция flyspell-mode-on устарела. Документация предполагает, что положительный аргумент префикса превратится в flyspell-mode, но, к сожалению, работает

(flyspell-mode 1)

выводится сообщение об ошибке:

Wrong number of arguments: (lambda (flyspell-mode 1)), 0

Если бы я мог понять, как вызвать flyspell-mode с аргументом префикса, я считаю, что смогу решить эту проблему.

Наиболее подходящий раздел, который я могу найти в руководстве Emacs Lisp, - это раздел "Интерактивный вызов", который описывает такие команды, как call-interactively. Это решительно не то, что я хочу.

(Конечная проблема, которую я пытаюсь решить, - создать крючок режима, который включает режим независимо от его текущего состояния.)

N.B. Название вопроса emacs Lisp функция вызова с аргументом префикса программно делает его похожим, но этот вопрос спрашивал о том, как создать интерактивную команду, и проблема была в конечном итоге решена с помощью call-interactively.


EDIT: этот вопрос спорный; Я нашел альтернативное решение моей исходной проблемы:

(add-hook 'text-mode-hook
          (function (lambda ()
                      (require 'flyspell)
                      (if flyspell-mode nil (flyspell-mode)))))

Но мне все же хотелось бы знать, как вызвать функцию Emacs Lisp с аргументом префикса, из другой функции Emacs Lisp, без чего-либо интерактивного.


UPDATE. Возможно, мне следовало спросить, почему я получил сообщение об ошибке...

Ответ 1

Похоже, что ваша версия режима Flyspell не соответствует соглашениям о второстепенном режиме, которые требуют, чтобы вы могли включить вспомогательный режим с помощью (name-of-mode t) или любой положительный аргумент префикса, отключите его с помощью (name-of-mode 0) любого отрицательного префиксного аргумента и переключите его с помощью (name-of-mode nil).

Если у вас установлена ​​последняя версия Flyspell, отчет об ошибке может быть в порядке. У меня есть версия, поставляемая с GNU Emacs 23.2 на моей машине, и она соблюдает соглашение. Моя версия также определяет две функции turn-on-flyspell и turn-off-flyspell, как тривиальные обертки вокруг flyspell-mode; функции с такими именами являются общими, но не официальными соглашениями. Функции flyspell-mode-on и flyspell-mode-off, по-видимому, предназначены для внутреннего использования.

Как правило, команды считывают текущий префиксный аргумент из переменной current-prefix-arg. Не путайте это с prefix-arg, что является значением для следующей команды (только несколько команд, например universal-argument, коснитесь этой переменной). Таким образом, если вам нужно передать префиксный аргумент при вызове функции, свяжите или установите current-prefix-arg.

(let ((current-prefix-arg t))
  (flyspell-mode))

Ответ 2

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

В подавляющем большинстве случаев вам не нужно беспокоиться о том, может ли аргумент быть "аргументом префикса" для неинтерактивных вызовов; просто проверьте документацию по функциям и передайте нужное значение для того, что вы хотите сделать.

Если по какой-то причине вам необходимо реплицировать отправку префиксного аргумента в неинтерактивный контекст, вам нужно будет проверить объявление функции (interactive) и точно определить, как он использует этот аргумент, и убедиться, что вы реплицируете этот поведение для аргумента, который вы передаете.

Подробнее см. в разделе

  • C-h f interactive RET
  • M-: (info "(elisp) Prefix Command Arguments") RET

В более сложных случаях, когда функция меняет свое поведение на основе переменной current-prefix-arg, вы можете напрямую установить эту переменную.

(let ((current-prefix-arg '(4)))
  (foo current-prefix-arg))

Ответ 3

Я могу думать об этом. Должно быть лучше

(call-interactively '(lambda ()
                       (interactive)
                       (flyspell-mode '(4))))

UPDATE: Я могу запустить это прямо. Что мне не хватает в этом вопросе.?

(flyspell-mode '(4))

Ответ 4

FWIW, функция "flyspell-mode" приняла аргумент (как в "(flyspell-mode 1)" ) по крайней мере с Emacs-21, поэтому я не знаю, как вы получили эту ошибку.

Но пока я здесь, я мог бы также отметить, что (flyspell-mode) в режиме "add-hook" изменил значение в Emacs-24: вместо значения "переключить режим flyspell в тексте" режимы "теперь это означает" включить режим flyspell в текстовых режимах ". Это отстало-несовместимое изменение, но я считаю, что он исправит более скрытые ошибки, чем он представит.