Определение новых типов
В предыдущих разделах мы описали, как создавать сложные спецификации типов для 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 описывается как либо строка, либо ячейка конс, у которой car и cdr сами являются binary-tree-of-string. Обратите внимание на ссылку на тип виджета, который мы в данный момент определяем. Атрибут :tag — это строка для именования виджета в пользовательском интерфейсе, а аргумент :offset служит для обеспечения того, что дочерние узлы отступлены на четыре пробела относительно родительского узла, делая структуру дерева очевидной в буфере настройки.
Пример defcustom показывает, как новый виджет может использоваться как обычный тип настройки.
Причина названия lazy в том, что другие составные виджеты преобразуют свои подчиненные виджеты во внутренний формат при создании виджета в буфере. Это преобразование рекурсивно, поэтому подчиненные виджеты также преобразуют свои подчиненные виджеты. Если структура данных сама по себе рекурсивна, это преобразование приведет к бесконечной рекурсии. Виджет lazy предотвращает рекурсию: он преобразует свой аргумент :type только при необходимости.
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/Defining-New-Types.html