Часто бывает полезно уметь идентифицировать и находить определённые объекты в буфере, например определения функций и классов, операторы, блоки кода, строки, комментарии и т. д. Emacs позволяет пользователям определять, какой узел tree-sitter соответствует “объекту”. Это даёт возможность удобных функций, таких как переход к следующей функции, выделение блока кода в точке или транспозиция двух аргументов функции.
Функционал “объектов” в Emacs независим от механизма сопоставления с образцом tree-sitter и сравнительно менее мощный, но более подходит для навигации и обхода дерева разбора.
Вы можете определять объекты с помощью treesit-thing-settings, получать предикат определённого объекта с помощью treesit-thing-definition и проверять, определён ли объект, с помощью treesit-thing-defined-p.
Это ассоциативный список определений объектов для каждого языка. Ключ каждой записи — символ языка, а значение — список определений объектов вида (объект предикат), где объект — это символ, представляющий объект, например defun, sexp или sentence; а предикат задаёт, какой узел tree-sitter является данным объектом.
предикат может быть строкой регулярного выражения, которая соответствует типу узла; может быть функцией, которая принимает узел в качестве аргумента и возвращает логическое значение, указывающее, подходит ли узел под объект; или может быть парой (регэксп . функция), что является комбинацией регулярного выражения регэксп и функции функция — узел должен одновременно соответствовать регэксп и удовлетворять функция, чтобы считаться объектом.
предикат также может быть рекурсивно определён. Он может быть (or предикат…), что означает, что удовлетворение любого из предикатов делает узел объектом. Он может быть (not предикат), что означает, что неудовлетворение предиката делает узел объектом.
Наконец, предикат может ссылаться на другие объекты, определённые в этом списке. Например, (or sexp sentence) определяет нечто, что является либо объектом sexp, либо объектом sentence, как определено другими правилами в ассоциативном списке.
Вот пример treesit-thing-settings для C и C++:
((c
(defun "function_definition")
(sexp (not "[](),[{}]"))
(comment "comment")
(string "raw_string_literal")
(text (or comment string)))
(cpp
(defun ("function_definition" . cpp-ts-mode-defun-valid-p))
(defclass "class_specifier")
(comment "comment")))
Обратите внимание, что этот пример изменён для дидактических целей и не совсем точно соответствует тому, как режимы C и C++ определяют объекты.
Встроенные функции Emacs уже используют некоторые определения объектов. Команда treesit-forward-sexp использует определение sexp, если основной режим его определяет; treesit-forward-sentence использует определение sentence. Функции перемещения по defun, такие как treesit-end-of-defun, используют определение defun (определение defun переопределяется переменной treesit-defun-type-regexp для обратной совместимости). Основные режимы также могут определять comment, string, text (обычно комментарии и строки).
Остальная часть этого раздела перечисляет несколько функций, которые используют определения объектов. Кроме перечисленных ниже функций, некоторые другие функции, описанные в других местах, также используют функционал объектов, например функции обхода дерева, такие как treesit-search-forward, treesit-induce-sparse-tree и т. д. См. Получение узлов.
Эта функция проверяет, является ли узел объектом.
Если узел является объектом, возвращает не nil, иначе возвращает nil. Для удобства, если узел равен nil, эта функция просто возвращает nil.
объект может быть либо символом объекта, например defun, либо просто предикатом, определяющим объект, например "function_definition" или (or comment string).
По умолчанию, если объект не определён или имеет неправильный формат, эта функция сигнализирует об ошибке treesit-invalid-predicate. Если игнорировать-отсутствие равно t, эта функция не сигнализирует об ошибке, когда объект не определён, а просто возвращает nil; но она всё равно сигнализирует об ошибке, если объект является предикатом с неправильным форматом.
Эта функция возвращает первый узел перед позицией, который является указанным объектом. Если такого узла нет, возвращает nil. Гарантируется, что если узел возвращён, то его конечная позиция меньше или равна позиции. Иными словами, эта функция никогда не возвращает узел, который охватывает позицию.
Опять же, объект может быть либо символом, либо предикатом.
Эта функция аналогична treesit-thing-prev, но возвращает первый узел после позиции, который является объектом. Она также гарантирует, что если узел возвращён, то его начальная позиция больше или равна позиции.
Эта функция основана на treesit-thing-prev и treesit-thing-next и предоставляет функциональность, полезную для команд навигации. Она возвращает позицию после перемещения через арг экземпляров объекта от позиции. Если недостаточно объектов для перемещения, возвращает nil. Функция не перемещает точку.
Положительный арг означает перемещение вперёд на указанное количество экземпляров объекта; отрицательный арг — перемещение назад. Если сторона равна beg, эта функция останавливается в начале объекта; если end — в конце объекта.
Как и в treesit-thing-prev, объект может быть символом объекта, определённым в treesit-thing-settings, или предикатом.
тактика определяет, как эта функция перемещается между объектами. Она может быть nested, top-level, restricted или nil. nested или nil означает обычную вложенную навигацию: сначала пытается перемещаться по родственным узлам; если на текущем уровне не осталось родственных узлов, переходит к родителю, затем к его родственным узлам и так далее. top-level означает перемещаться только по объектам верхнего уровня и игнорировать вложенные объекты. restricted означает, что перемещение ограничено объектом, который охватывает позицию, если такой объект существует. Эта тактика полезна для команд, которые хотят оставаться на текущем уровне вложенности и не подниматься выше.
Эта функция возвращает наименьший узел, который является объектом и охватывает позицию; если такого узла нет, возвращает nil.
Возвращённый узел должен охватывать позицию, то есть его начальная позиция меньше или равна позиции, а конечная позиция больше или равна позиции.
Если строгий не равен nil, эта функция использует строгое сравнение, то есть начальная позиция должна быть строго больше позиции, а конечная позиция должна быть строго меньше позиции.
объект может быть либо символом объекта, определённым в treesit-thing-settings, либо предикатом.
Существуют также некоторые удобные функции-обёртки. treesit-beginning-of-thing перемещает точку в начало объекта, treesit-end-of-thing перемещает в конец объекта, а treesit-thing-at-point возвращает объект в точке.
Существуют также команды defun, которые специально используют определение defun (как запасной вариант для treesit-defun-type-regexp), например treesit-beginning-of-defun, treesit-end-of-defun и treesit-defun-at-point. Кроме того, эти функции используют treesit-defun-tactic в качестве тактики навигации. Они более подробно описаны в других разделах (см. Разработка основных режимов с использованием tree-sitter).