38.2 Использование парсера Tree-sitter

В этом разделе описывается создание и настройка парсера tree-sitter. В Emacs каждый парсер tree-sitter связан с буфером. Когда пользователь редактирует буфер, связанный парсер и синтаксическое дерево автоматически поддерживаются в актуальном состоянии.

Переменная: treesit-max-buffer-size

Эта переменная содержит максимальный размер буферов, в которых может быть активирован tree-sitter. Основные режимы должны проверять это значение при принятии решения о включении функциональности tree-sitter.

Функция: treesit-parser-create language &optional buffer no-reuse tag

Создать парсер для указанных buffer и language (см. Грамматика языка Tree-sitter) с tag. Если buffer опущен или равен nil, он обозначает текущий буфер.

По умолчанию эта функция повторно использует парсер, если он уже существует для language с tag в buffer, но если no-reuse не равен nil, эта функция всегда создаёт новый парсер.

tag может быть любым символом, кроме t, и по умолчанию равен nil. Разные парсеры могут иметь одинаковый тег.

Если этот буфер является косвенным буфером, вместо него используется его базовый буфер. То есть косвенные буферы используют парсеры своего базового буфера. Если базовый буфер сужен, косвенный буфер может не иметь возможности получить информацию о той части текста буфера, которая невидима в базовом буфере. Программы на Lisp должны при необходимости расширять буфер, если они хотят использовать парсер в косвенном буфере.

Имея парсер, мы можем получить информацию о нём.

Функция: treesit-parser-buffer parser

Эта функция возвращает буфер, связанный с parser.

Функция: treesit-parser-language parser

Эта функция возвращает язык, используемый parser.

Функция: treesit-parser-p object

Эта функция проверяет, является ли object парсером tree-sitter, и возвращает не nil, если это так, и nil в противном случае.

Нет необходимости явно разбирать буфер, поскольку разбор выполняется автоматически и отложенно. Парсер выполняет разбор только тогда, когда программа на Lisp запрашивает узел в его синтаксическом дереве. Поэтому, когда парсер только создан, он не разбирает буфер; он ждёт, пока программа на Lisp впервые запросит узел. Аналогично, когда в буфере вносятся изменения, парсер не выполняет повторный разбор немедленно.

Когда парсер выполняет разбор, он проверяет размер буфера. Tree-sitter может обрабатывать буферы размером не более примерно 4 ГБ. Если размер превышает это значение, Emacs сигнализирует об ошибке treesit-buffer-too-large с данными сигнала в виде размера буфера.

После создания парсера Emacs автоматически добавляет его во внутренний список парсеров. При каждом изменении буфера Emacs обновляет парсеры в этом списке, чтобы они могли постепенно обновлять своё синтаксическое дерево.

Функция: treesit-parser-list &optional buffer language tag

Эта функция возвращает список парсеров buffer, отфильтрованный по language и tag. Если buffer равен nil или опущен, по умолчанию используется текущий буфер. Если этот буфер является косвенным буфером, вместо него используется его базовый буфер. То есть косвенные буферы используют парсеры своего базового буфера.

Если language не равен nil, включить только парсеры для этого языка и только парсеры с tag. tag по умолчанию равен nil. Если tag равен t, включить в возвращаемый список парсеры независимо от их тега.

Функция: treesit-parser-delete parser

Эта функция удаляет parser.

Обычно парсер «видит» весь буфер, но когда буфер сужен (см. Сужение), парсер видит только доступную часть буфера. Насколько может судить парсер, скрытая область была удалена. Когда буфер позже расширяется, парсер считает, что текст вставлен в начале и в конце. Хотя парсеры учитывают сужение, режимы не должны использовать сужение как средство для работы с многоязычным буфером; вместо этого следует установить диапазоны, в которых парсер должен работать. См. Разбор текста на нескольких языках.

Поскольку парсер выполняет разбор отложенно, когда пользователь или программа на Lisp сужает буфер, парсер не затрагивается немедленно; до тех пор, пока режим не запрашивает узел, пока буфер сужен, парсер не знает о сужении.

Помимо создания парсера для буфера, программа на Lisp может также разбирать строку. В отличие от буфера, разбор строки является однократной операцией, и нет способа обновить результат.

Функция: treesit-parse-string string language

Эта функция разбирает string с использованием language и возвращает корневой узел сгенерированного синтаксического дерева.

Получение уведомлений об изменениях в синтаксическом дереве

Программа на Lisp может захотеть получать уведомления о тексте, затронутом инкрементальным разбором. Например, вставка закрывающего маркера комментария преобразует текст перед этим маркером в комментарий. Даже если текст не был отредактирован напрямую, он тем не менее считается «изменённым».

Emacs позволяет программам на Lisp регистрировать функции обратного вызова (т.н. уведомители) для таких изменений. Функция-уведомитель принимает два аргумента: ranges и parser. ranges — это список cons-ячеек вида (start . end), где start и end обозначают начальную и конечную позиции диапазона. parser — это парсер, отправляющий уведомление.

Каждый раз, когда парсер выполняет повторный разбор буфера, он сравнивает старое и новое синтаксические деревья, вычисляет диапазоны, в которых изменились узлы, и передаёт эти диапазоны функциям-уведомителям. Обратите внимание, что начальный разбор также считается «изменением», поэтому функции-уведомители вызываются при начальном разборе с диапазоном, равным всему буферу.

Функция: treesit-parser-add-notifier parser function

Эта функция добавляет function в список функций-уведомителей об изменениях parser. function должна быть символом функции, а не лямбда-функцией (см. Анонимные функции).

Функция: treesit-parser-remove-notifier parser function

Эта функция удаляет function из списка функций-уведомителей об изменениях parser. function должна быть символом функции, а не лямбда-функцией.

Функция: treesit-parser-notifiers parser

Эта функция возвращает список функций-уведомителей parser.