Как вызвать интерактивную функцию Emacs Lisp с префиксным аргументом из другой функции Emacs Lisp? - PullRequest
12 голосов
/ 22 февраля 2012

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

(flyspell-mode 1)

приводит к сообщению об ошибке:

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

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

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

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

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


РЕДАКТИРОВАТЬ : Этот вопрос спорный; Я нашел альтернативное решение моей первоначальной проблемы:

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

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


ОБНОВЛЕНИЕ : Возможно, я должен был спросить, почему я получаю это сообщение об ошибке ...

Ответы [ 6 ]

9 голосов
/ 23 февраля 2012

Похоже, что ваша версия режима 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))
4 голосов
/ 22 февраля 2012

Если вы не вызываете функцию в интерактивном режиме, то объявление (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))
2 голосов
/ 22 февраля 2012

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

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

ОБНОВЛЕНИЕ: я могу запустить это непосредственно .. что я упускаю из вопроса .?

(flyspell-mode '(4))

EDITED: удалена цитата для лямбда-выражения (я добавил это примечание, потому что SX заставляет редактирование иметь длину не менее шести символов, поэтому его можно удалить).

1 голос
/ 20 марта 2018

См. Мой комментарий для исправления источника вашей проблемы. Что касается ответа на ваш вопрос, то, как префиксный аргумент arg превращается в какой-то аргумент Lisp, зависит от спецификации interactive, поэтому единственный способ сделать это надежно (т.е. без предварительного знания, например, факта, что он является второстепенным). Режим функции) - это интерактивный вызов функции:

(let ((current-prefix-arg '(4)))
  (call-interactively 'flyspell-mode))
1 голос
/ 23 февраля 2012

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

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

0 голосов
/ 22 февраля 2012

Я не мастер Emacs и Elisp ( пока ;)), но я думаю, что в этом случае вы можете использовать Ctrl - u 1 Доп. - x flyspell-mode.

...