Spec-Zone.ru › Elisp

Использование 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; тогда команда вызывается без аргументов. Если команде требуется один или несколько аргументов, это быстро приведёт к ошибке.
  • Это может быть строка; её содержимое — последовательность элементов, разделённых символами новой строки, по одному на каждый аргумент. Каждый элемент состоит из кодового символа (см. Кодовые символы для interactive) и, при необходимости, приглашения (которое некоторые кодовые символы используют, а некоторые игнорируют). Пример:
    (interactive "P\nbFrobnicate buffer: ")
    

    Кодовая буква ‘P’ задаёт в качестве первого аргумента команды необработанный префикс команды (см. Аргументы префикса команды). ‘bFrobnicate buffer: ’ предлагает пользователю ввести имя существующего буфера с помощью приглашения ‘Frobnicate buffer: ’; это имя становится вторым и последним аргументом.

    В строке приглашения можно использовать ‘%’, чтобы включить в приглашение значения предыдущих аргументов (начиная с первого). Для этого используется format-message (см. Форматирование строк). Например, вот как можно запросить имя существующего буфера, а затем новое имя для него:

    (interactive "bBuffer to rename: \nsRename buffer %s to: ")
    

    Если строка начинается с ‘*’, при доступе к буферу только для чтения сигнализируется ошибка.

    Если строка начинается с ‘@’ и последовательность клавиш, использованная для вызова команды, содержит события мыши, перед выполнением команды выбирается окно, связанное с первым из этих событий.

    Если строка начинается с ‘^’ и команда была вызвана посредством сдвигового перевода, перед выполнением команды устанавливается метка и временно активируется область либо расширяется уже активная область. Если команда была вызвана без сдвигового перевода, а область временно активна, перед выполнением команды она деактивируется. На уровне пользователя сдвиговый перевод управляется с помощью shift-select-mode; см. Выделение с помощью Shift в Руководстве 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 — символ, используется его определение функции. При вызове для OClosure обработка делегируется обобщённой функции oclosure-interactive-form.

Функция: oclosure-interactive-form function

Как и interactive-form, эта функция принимает команду и возвращает её интерактивную форму. Отличие в том, что это обобщённая функция, вызываемая только в том случае, если function является OClosure (см. Открытые замыкания). Она предназначена для того, чтобы некоторые типы OClosure могли вычислять свои интерактивные формы динамически, а не хранить их в одном из своих слотов.

Например, это используется для функций kmacro, чтобы уменьшить объём занимаемой ими памяти, поскольку у них у всех одна и та же интерактивная форма. Также это используется для функций advice, интерактивная форма которых вычисляется на основе интерактивных форм их компонентов. Это позволяет выполнять вычисление более лениво и правильно обновлять интерактивную форму при переопределении одного из компонентов.

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Interactive.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API