如何为 Helix 编写 tags.scm 查询实现文档与工作区符号选择器
【免费下载链接】helixA post-modern modal text editor.项目地址: https://gitcode.com/GitHub_Trending/he/helix
Helix 对没有语言服务器(LSP)配合的语言,可以基于 tree-sitter 语法树提供 LSP 式的文档符号和工作区符号选择器,前提是你要为该语言编写一个tags.scm查询文件。这篇文章的任务就是:为一个已有 tree-sitter grammar 的语言写出tags.scm,让 Helix 的Space-s(文档符号)和Space-S(工作区符号)选择器能列出该语言的函数、类、模块等符号及它们的引用位置。
前置条件:该语言已经有可用的 tree-sitter grammar,并在 Helix 中配置了 grammar(即languages.toml中有对应的[[grammar]]条目)。
查询文件放在哪里
按 tags 指南 的说明,文件位置分两种情况:
- 正式向 Helix 贡献时,放在
runtime/queries/{language}/tags.scm(其中{language}是语言名,与languages.toml中的name一致),例如仓库自带的 Picat 示例 就位于runtime/queries/picat/tags.scm。 - 本地测试阶段,可以把查询文件放到本机的 runtime 目录,文档以 Linux 为例:
~/.config/helix/runtime。
tags.scm是 查询文件列表 中可选的文件之一(只有highlights.scm是必需的),其用途一栏写的是 "document/workspace symbol pickers"。如果你在开发中使用自己维护的runtime目录,按 语言添加指南 的常见问题一节,需要把环境变量HELIX_RUNTIME指向该runtime目录,否则 Helix 可能找不到你的查询。
编写 @definition.* 捕获:定义符号
tags.scm的核心工作是把语法树中"有意义的节点"打上捕获。第一类捕获是@definition.*,标记一个符号的定义位置。文档符号选择器只识别以下捕获名,列表外的捕获名会被忽略:
| 捕获名 |
|---|
definition.class |
definition.constant |
definition.enum |
definition.field |
definition.function |
definition.interface |
definition.macro |
definition.module |
definition.section |
definition.struct |
definition.type |
因此规则是:语言特有的构造应映射到上表中最接近的种类,而不是自创新捕获名。
写规则时遵守两个约定:
@definition.*捕获整个定义节点;- 同一个匹配中再用
@name捕获该定义内部的名字标识符节点。
文档给出的示例(以function_definition/class_definition节点为例):
(function_definition name: (identifier) @name) @definition.function (class_definition name: (identifier) @name) @definition.class对照仓库中真实的 Picat 查询,可以看到一个更完整的定义模式:多个构造(function_definition、predicate_definition、actor_definition)通过[...]列表归入同一个@definition.function捕获,并用name: (_) @name捕获名字节点;文件末尾还有(module_declaration (_) @name) @definition.module这样的模块定义。
编写 @reference.* 捕获:引用位置
第二类捕获标记调用点或类型引用,供工作区符号搜索定位用途(usages)。常见变体是@reference.call(函数调用)和@reference.class(类引用),同样用@name捕获标识符:
(call function: (identifier) @name) @reference.callPicat 示例中的对应写法是(function_call function: (_) @name @reference.call)。
验证查询是否可用
查询写好后,有两层验证:
编译期检查:在 Helix 源码仓库中运行
cargo xtask query-check [language]把
[language]替换为你的语言名。该命令校验查询文件能否针对对应 grammar 编译通过——语言添加指南 要求所有查询文件都能通过这一检查。效果检查:用 Helix 打开该语言的文件,按
Space-s打开文档符号选择器、Space-S打开工作区符号选择器(见 键位表 中 space 模式条目,两者都标注为LSPorTS,即语言服务器不可用时回退到 tree-sitter 的tags.scm)。如果选择器里列出了你在查询中标记的定义与引用,说明查询生效。
另外,如果你在切换分支或新增 grammar 后运行 Helix 出现错误,按同一指南的常见问题一节执行hx --grammar fetch拉取 grammar、hx --grammar build重建过期 grammar。
限制
- 只有
@definition.*列表中列出的捕获名会被符号选择器识别,其余捕获名一律忽略。 tags.scm本身不决定符号选择器的按键与过滤行为;选择器文档 说明工作区符号选择器会把搜索词直接传给语言服务器,而基于语法的符号路径(TS 回退)由本文的查询决定内容。
下一步如果你需要为该语言补齐高亮或嵌入语法,可继续参考 查询文件对照表 中的highlights.scm、injections.scm等条目,并同样用cargo xtask query-check [language]校验。
【免费下载链接】helixA post-modern modal text editor.项目地址: https://gitcode.com/GitHub_Trending/he/helix
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考