Spec-Zone.ru › Elisp

Определение новых типов

В предыдущих разделах мы описали, как создавать сложные спецификации типов для defcustom. В некоторых случаях может потребоваться дать такой спецификации типа имя. Очевидный случай — когда один и тот же тип используется для многих пользовательских параметров: вместо того чтобы повторять спецификацию для каждого параметра, можно присвоить спецификации типа имя и использовать это имя каждый раз defcustom. Другой случай — когда значение пользовательского параметра представляет собой рекурсивную структуру данных. Чтобы тип данных мог ссылаться на самого себя, ему необходимо имя.

Поскольку пользовательские типы реализованы в виде виджетов, новый настраиваемый тип определяется созданием нового виджета. Здесь мы не будем подробно описывать интерфейс виджетов; см. Введение в Библиотеку виджетов Emacs. Вместо этого мы продемонстрируем на простом примере минимальную функциональность, необходимую для определения новых настраиваемых типов.

(define-widget 'binary-tree-of-string 'lazy
  "A binary tree made of cons-cells and strings."
  :offset 4
  :tag "Node"
  :type '(choice (string :tag "Leaf" :value "")
                 (cons :tag "Interior"
                       :value ("" . "")
                       binary-tree-of-string
                       binary-tree-of-string)))

(defcustom foo-bar ""
  "Sample variable holding a binary tree of strings."
  :type 'binary-tree-of-string)

Функция для определения нового виджета называется define-widget. Первый аргумент — это символ, который мы хотим использовать как новый тип виджета. Второй аргумент — символ, представляющий существующий виджет; новый виджет будет определён как отличающийся от существующего. Для определения новых типов настройки идеально подходит виджет lazy, поскольку он принимает аргумент-ключевое слово :type с тем же синтаксисом, что и аргумент-ключевое слово функции defcustom с таким же именем. Третий аргумент — строка документации для нового виджета. Эту строку можно посмотреть с помощью команды M-x widget-browse RET binary-tree-of-string RET.

После этих обязательных аргументов следуют аргументы-ключевые слова. Самый важный из них — :type, описывающий тип данных, которому должен соответствовать этот виджет. Здесь binary-tree-of-string описывается как строка либо cons-ячейка, car и cdr которой также являются binary-tree-of-string. Обратите внимание на ссылку на тип виджета, который мы сейчас определяем. Ещё один важный аргумент-ключевое слово — :tag, поскольку для нового виджета мы используем виджет lazy. По умолчанию у виджета lazy нет метки, и в её отсутствие буфер настройки показывает всё значение виджета (то есть значение настраиваемого пользовательского параметра). Поскольку это почти никогда не бывает хорошей идеей, мы задаём строку, которая будет обозначать виджет binary-tree-or-string. Аргумент :offset нужен, чтобы дочерние узлы располагались с отступом в четыре пробела относительно родительского узла, благодаря чему структура дерева становится очевидной в буфере настройки.

В defcustom показано, как новый виджет можно использовать в качестве обычного типа настройки.

Название lazy объясняется тем, что другие составные виджеты преобразуют подчинённые виджеты во внутреннее представление при создании экземпляра виджета в буфере. Это преобразование рекурсивно, поэтому подчинённые виджеты преобразуют свои подчинённые виджеты. Если сама структура данных рекурсивна, такое преобразование приводит к бесконечной рекурсии. Виджет lazy предотвращает рекурсию: он преобразует свой аргумент :type только при необходимости.

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/Defining-New-Types.html

Spec-Zone.ru

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