Использование interactive
В этом разделе описано, как написать форму interactive, которая делает функцию Lisp интерактивно вызываемой командой, и как проверить форму interactive команды.
- Специальная форма: interactive &optional arg-descriptor &rest modes
-
Эта специальная форма объявляет, что функция является командой и может быть вызвана интерактивно (через M-x или с помощью последовательности клавиш, связанных с ней). Аргумент arg-descriptor объявляет, как вычислять аргументы команды при её интерактивном вызове.
Команду можно вызывать из программ Lisp, как и любую другую функцию, но в этом случае вызывающая сторона предоставляет аргументы, и arg-descriptor не имеет эффекта.
Форма
interactiveдолжна находиться на верхнем уровне тела функции или в свойствеinteractive-formсимвола функции (см. Свойства символов). Она действует, потому что цикл обработки команд ищет её перед вызовом функции (см. Интерактивный вызов). После вызова функции выполняются все её формы тела; в этот момент, если формаinteractiveвстречается в теле, эта форма просто возвращаетnil, даже не оценивая свой аргумент.Список modes позволяет указать режимы, в которых предназначена использоваться команда. Подробнее о влиянии modes и о том, когда его использовать, см. Режимы команд.
По соглашению, вы должны поместить форму
interactiveв тело функции, как первую форму верхнего уровня. Если формаinteractiveсодержится как в свойстве символаinteractive-form, так и в теле функции, приоритет имеет первая.Свойство символа
interactive-formможет быть использовано для добавления интерактивной формы к существующей функции или изменения способа обработки её аргументов интерактивно без переопределения функции.
Существует три возможности для аргумента arg-descriptor:
- Его можно опустить или
nil; тогда команда вызывается без аргументов. Это быстро приведёт к ошибке, если команда требует один или несколько аргументов. - Это может быть строка; её содержимое — последовательность элементов, разделённых символами новой строки, по одному на каждый аргумент15. Каждый элемент состоит из символа кода (см. Интерактивные коды), за которым необязательно следует приглашение (некоторые символы кода используют его, а некоторые игнорируют). Вот пример:
(interactive "P\nbFrobnicate buffer: ")
Символ кода ‘P’ устанавливает первый аргумент команды в исходный префикс команды (см. Аргументы префиксной команды). ‘bFrobnicate buffer: ’ запрашивает у пользователя ввод имени существующего буфера, который становится вторым и последним аргументом.
В строке приглашения можно использовать ‘%’ для включения значений предыдущих аргументов (начиная с первого аргумента) в приглашение. Это делается с помощью
format-message(см. Форматирование строк). Например, вот как можно прочитать имя существующего буфера, а затем новое имя для этого буфера:(interactive "bBuffer to rename: \nsRename buffer %s to: ")
Если ‘*’ появляется в начале строки, то при чтении буфера генерируется ошибка, если он только для чтения.
Если ‘@’ появляется в начале строки, и если последовательность клавиш, используемая для вызова команды, включает какие-либо события мыши, то окно, связанное с первым из этих событий, выбирается до запуска команды.
Если ‘^’ появляется в начале строки, а команда вызвана с помощью сдвига перевода, то устанавливается метка и временно активируется область, или расширяется уже активная область, перед запуском команды. Если команда вызвана без сдвига перевода, а область временно активна, то область деактивируется перед запуском команды. Сдвиг перевода контролируется на уровне пользователя с помощью
shift-select-mode; см. Сдвиг выбора в Руководстве по GNU Emacs.Можно использовать ‘*’, ‘@’ и
^вместе; порядок не имеет значения. Фактическое чтение аргументов контролируется остальной частью строки приглашения (начиная с первого символа, который не является ‘*’, ‘@’ или ‘^’). - Это может быть выражение Lisp, которое не является строкой; тогда это должна быть форма, которая оценивается для получения списка аргументов для передачи команде. Обычно эта форма будет вызывать различные функции для чтения ввода от пользователя, чаще всего через минибуфер (см. Минибуферы) или непосредственно с клавиатуры (см. Чтение ввода).
Предоставление точки или метки в качестве значения аргумента также обычно используется, но если вы это делаете и читаете ввод (независимо от использования минибуфера), убедитесь, что вы получаете целочисленные значения точки или метки после чтения. Текущий буфер может получать выходные данные подпроцесса; если выходные данные подпроцесса появляются, когда команда ждёт ввода, точка и метка могут сместиться.
Вот пример того, что не следует делать:
(interactive (list (region-beginning) (region-end) (read-string "Foo: " nil 'my-history)))Вот как избежать проблемы, проверив точку и метку после чтения ввода с клавиатуры:
(interactive (let ((string (read-string "Foo: " nil 'my-history))) (list (region-beginning) (region-end) string)))
Предупреждение: значения аргументов не должны включать типы данных, которые не могут быть напечатаны, а затем прочитаны. Некоторые средства сохраняют
command-historyв файле для последующего чтения; если аргументы команды содержат тип данных, который выводит информацию с помощью синтаксиса ‘#<…>’, эти средства не будут работать.Однако есть несколько исключений: использование ограниченного набора выражений, таких как
(point),(mark),(region-beginning), и(region-end), допустимо, так как Emacs распознаёт их особо и помещает выражение (а не его значение) в историю команд. Чтобы узнать, является ли написанное выражение одним из этих исключений, запустите команду, а затем проверьте(car command-history).
- Функция: interactive-form function
Эта функция возвращает форму
interactiveфункции function. Если function — интерактивно вызываемая функция (см. Интерактивный вызов), то значением является формаinteractiveкоманды(interactive spec), которая определяет, как вычислять её аргументы. В противном случае значением являетсяnil. Если function — символ, используется его определение функции.
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Interactive.html