24.5 Imenu

Imenu — это возможность, позволяющая пользователям выбирать определение или раздел в буфере из меню, в котором перечислены все они, чтобы перейти непосредственно к этому месту в буфере. Imenu работает путём построения индекса буфера, в котором перечислены имена и позиции в буфере определений или других именованных частей буфера; затем пользователь может выбрать один из них и переместить точку к нему. Основные режимы могут добавить пункт в строке меню для использования Imenu с помощью imenu-add-to-menubar.

Команда: imenu-add-to-menubar имя

Эта функция определяет локальный пункт строки меню с именем имя для запуска Imenu.

Команды пользовательского уровня для использования Imenu описаны в Руководстве Emacs (см. Imenu в Руководстве Emacs). В этом разделе объясняется, как настроить метод Imenu для поиска определений или частей буфера для конкретного основного режима.

Обычный и самый простой способ — установить переменную imenu-generic-expression:

Переменная: imenu-generic-expression

Если эта переменная не равна nil, она является списком, задающим регулярные выражения для поиска определений для Imenu. Простые элементы imenu-generic-expression выглядят так:

(заголовок-меню регвыр индекс)

Здесь, если заголовок-меню не равен nil, это означает, что совпадения для этого элемента должны помещаться в подменю индекса буфера; сам заголовок-меню задаёт имя для подменю. Если заголовок-меню равен nil, совпадения для этого элемента помещаются непосредственно на верхний уровень индекса буфера.

Второй элемент списка, регвыр, является регулярным выражением (см. Регулярные выражения); всё, что ему соответствует в буфере, считается определением и должно быть упомянуто в индексе буфера. Третий элемент, индекс, является неотрицательным целым числом, указывающим, какая подвыражение в регвыр соответствует имени определения.

Элемент также может выглядеть так:

(заголовок-меню регвыр индекс функция аргументы…)

Каждое совпадение для этого элемента создаёт элемент индекса, и когда пользователь выбирает этот элемент индекса, он вызывает функцию с аргументами, состоящими из имени элемента, позиции в буфере и аргументов.

Для режима Emacs Lisp imenu-generic-expression может выглядеть так:

((nil "^\\s-*(def\\(un\\|subst\\|macro\\|advice\\)\
\\s-+\\([-A-Za-z0-9+]+\\)" 2)
 ("*Vars*" "^\\s-*(def\\(var\\|const\\)\
\\s-+\\([-A-Za-z0-9+]+\\)" 2)
 ("*Types*"
  "^\\s-*\
(def\\(type\\|struct\\|class\\|ine-condition\\)\
\\s-+\\([-A-Za-z0-9+]+\\)" 2))

Установка этой переменной делает её локальной для буфера в текущем буфере.

Переменная: imenu-case-fold-search

Эта переменная управляет тем, учитывается ли регистр при поиске соответствия регулярным выражениям в значении imenu-generic-expression: значение t (по умолчанию) означает, что поиск должен игнорировать регистр.

Установка этой переменной делает её локальной для буфера в текущем буфере.

Переменная: imenu-syntax-alist

Эта переменная является ассоциативным списком модификаторов таблицы синтаксиса, используемых при обработке imenu-generic-expression для переопределения таблицы синтаксиса текущего буфера. Каждый элемент должен иметь такую форму:

(символы . синтаксис-описание)

CAR, символы, может быть либо символом, либо строкой. Элемент указывает, что указанному символу или символам следует назначить синтаксис, заданный синтаксис-описанием, которое передаётся в modify-syntax-entry (см. Функции таблицы синтаксиса).

Эта возможность обычно используется для присвоения синтаксиса слова символам, которые в обычных условиях имеют синтаксис символа, и таким образом упрощения imenu-generic-expression и ускорения поиска соответствий. Например, режим Fortran использует это так:

(setq imenu-syntax-alist '(("_$" . "w")))

В регулярных выражениях imenu-generic-expression затем можно использовать ‘\\sw+’ вместо ‘\\(\\sw\\|\\s_\\)+’. Имейте в виду, что этот метод может быть неудобным, когда режиму требуется ограничить начальный символ имени меньшим набором символов, чем разрешено в остальной части имени.

Установка этой переменной делает её локальной для буфера в текущем буфере.

Другой способ настройки Imenu для основного режима — установка переменных imenu-prev-index-position-function и imenu-extract-index-name-function:

Переменная: imenu-prev-index-position-function

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

Установка этой переменной делает её локальной для буфера в текущем буфере.

Переменная: imenu-extract-index-name-function

Если эта переменная не равна nil, её значением должна быть функция, возвращающая имя для определения, при условии, что точка находится в этом определении в том положении, в котором её оставила функция imenu-prev-index-position-function.

Установка этой переменной делает её локальной для буфера в текущем буфере.

Последний способ настройки Imenu для основного режима — установка переменной imenu-create-index-function:

Переменная: imenu-create-index-function

Эта переменная задаёт функцию, используемую для создания индекса буфера. Функция не должна принимать аргументов и должна возвращать ассоциативный список индекса для текущего буфера. Она вызывается внутри save-excursion, поэтому то, где она оставит точку, не имеет значения.

Ассоциативный список индекса может содержать элементы трёх типов. Простые элементы выглядят так:

(имя-индекса . позиция-индекса)

Выбор простого элемента приводит к перемещению в позицию позиция-индекса в буфере. Специальные элементы выглядят так:

(имя-индекса позиция-индекса функция аргументы…)

Выбор специального элемента выполняет:

(funcall функция
         имя-индекса позиция-индекса аргументы…)

Элемент вложенного подсписка выглядит так:

(заголовок-меню . подсписок)

Он создаёт подменю заголовок-меню, заданное подсписком.

Значение по умолчанию для imenu-create-index-function — imenu-default-create-index-function. Эта функция вызывает значение imenu-prev-index-position-function и значение imenu-extract-index-name-function для создания ассоциативного списка индекса. Однако если какая-либо из этих двух переменных равна nil, функция по умолчанию использует imenu-generic-expression.

Установка этой переменной делает её локальной для буфера в текущем буфере.

Если Emacs собран с tree-sitter, он может автоматически генерировать индекс Imenu, если основной режим устанавливает соответствующие переменные.

Переменная: treesit-simple-imenu-settings

Эта переменная указывает Emacs, как генерировать индексы Imenu. Она должна быть списком вида (категория регвыр предикат функция-имени).

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

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

функция-имени должна быть либо nil, либо функцией, которая принимает узел определения и возвращает имя этого определения, например, имя функции для определения функции. Если функция-имени равна nil, вместо неё используется treesit-defun-name (см. Разработка основных режимов с tree-sitter).

treesit-major-mode-setup (см. Разработка основных режимов с tree-sitter) автоматически настраивает Imenu, если эта переменная не равна nil.