尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

如何为 Helix 编写 indents.scm 自动缩进查询并用 indent-check 验证

如何为 Helix 编写 indents.scm 自动缩进查询并用 indent-check 验证 如何为 Helix 编写 indents.scm 自动缩进查询并用 indent-check 验证【免费下载链接】helixA post-modern modal text editor.项目地址: https://gitcode.com/GitHub_Trending/he/helix当你在 Helix 中用o、O或ret插入新行时编辑器会根据当前文档的语法树为新行计算缩进。这条能力由 tree-sitter 的缩进查询文件indents.scm驱动。如果你的目标语言没有自动缩进或者现有查询对某种写法计算出了错误的缩进你需要做的是在runtime/queries/{language}/indents.scm中编写或修改查询再用cargo xtask indent-check对照测试语料验证。这篇文章给出从编写到验证的完整操作路径。准备条件已克隆 Helix 源码仓库并具备 从源码构建 所需的环境Rust 工具链、Git以及一个支持 C14 的编译器如 GCC 或 Clang用于编译 tree-sitter grammar。目标语言已在 languages.toml 中有[[language]]条目且包含indent配置例如 rust 条目中的indent { tab-width 4, unit }indent-check依赖这一配置确定缩进风格缺失时会直接报错language {stem} has no indent config。该语言的 tree-sitter grammar 已获取并编译。从源码构建hxcargo install --path helix-term --locked会在本地runtime目录中一并构建 grammar也可以单独用hx --grammar fetch获取、hx --grammar build编译过期的 grammar。如果你在源码树之外开发自己的 runtime 目录需要把环境变量HELIX_RUNTIME指向该runtime目录否则 Helix 定位不到查询文件见 添加语言指南 的 Common issues。缩进是如何计算的写查询前先理解判定规则见 缩进查询指南一行代码的缩进级别是包含它的indent作用域的数量。indent捕获在节点上打开一个作用域覆盖该节点首行之后的各行至末行。同线合并是核心不变量在同一物理行上打开的多个indent作用域合计只加一级。这保证了方法链.foo().bar()平齐而不是逐级向右阶梯。查询起点是光标所在行之前的行尾o取当前行行尾O取上一行行尾引擎从该节点向上走到语法树根收集路径上所有祖先的indent/outdent/align等捕获。支持的捕获类型捕获作用indent打开一个缩进作用域同线合并outdent降低所在行通常是}、)、]或else等闭合记号一级indent.always/outdent.always不合并版本同一行多个捕获逐级累加/抵消alignanchor将节点内部内容对齐到anchor捕获节点的起始列每个含align的模式必须恰好含一个anchorextend把节点范围扩展到行尾及缩进更深的后续行适用于 Python 这类靠缩进划界的语言extend.prevent-once阻止最近一个extend祖先的首次扩展用于return这类必定结束块的语句opaque标记字符串、heredoc、块注释等字面体其内部行保持原缩进谓词可以出现在模式任意位置参数为捕获或字符串。tree-sitter 内置#eq?/#not-eq?、#match?/#not-match?、#any-of?/#not-any-of?。Helix 为缩进查询额外提供#not-kind-eq?第一参数的节点 kind 不等于第二个字符串参数#same-line?/#not-same-line?两个捕获是否不在同一行开始#one-line?/#not-one-line?捕获是否只跨一行。另外有一个特殊作用域header默认indent作用域在捕获节点自己的首行打开节点首行本身不缩进当需要缩进的恰恰是节点首行时如无花括号的if (cond)单语句体用#set! scope header把作用域改为在父节点header行打开(if_statement consequence: (_) indent (#not-kind-eq? indent compound_statement) (#set! scope header))编写 indents.scm查询文件放在runtime/queries/{language}/indents.scm其中{language}是语言名。一个真实的最小例子是 runtime/queries/rust/indents.scm 的开头部分[ (use_list) (block) (match_block) (arguments) (parameters) (declaration_list) (field_declaration_list) (field_initializer_list) (struct_pattern) (tuple_pattern) (unit_expression) (enum_variant_list) (call_expression) (binary_expression) (field_expression) (await_expression) (tuple_expression) (array_expression) (where_clause) (type_cast_expression) (token_tree) (macro_definition) (token_repetition) (token_repetition) ] indent [ } ] ) ] outdent即上述节点打开缩进作用域}/]/)闭合记号各抵消一级。节点类型名必须以该语言 grammar 的实际 node kind 为准先编译查询再逐个修正报错。查询文件首行还可以写; inherits: lang复用另一语言的查询见 adding_languages.md。写完先做语法级校验——它只检查查询能否对 grammar 编译通过不检查缩进行为cargo xtask query-check [language]按xtask的帮助文本query-check [languages]接受语言参数不传则检查全部语言。准备缩进测试语料indent-check的语料位于tests/indent/文件必须命名为language-id.ext例如 tests/indent/rust.rs。执行时按文件主名language-id在languages.toml中解析语言找不到会报错rust.rs: no configured language with id xxx (corpus files are named language-id.ext)语料就是期望缩进正确的代码样本。检查分两个方向两种方向都对的规则才算通过reindent 模式对每一行计算期望缩进与文件中实际缩进比对typing 模式模拟在该行末尾按回车计算下一行得到的缩进。typing 模式下缩进不足computed 实际总是失败缩进过多只在下一行首个 token 不是outdent记号时才是问题输出为 note 而非失败。语料中以语言comment-tokens开头的行会被跳过、不做断言可以借注释行标注已知边界情况。tests/indent/rust.rs 就是这么用的// Assignment / destructuring RHS continued on the next line. helix // deliberately indents these continuations only when reindenting an // already-complete expression (an opinionated binary/assignment rule); // typing a newline after does not indent the RHS, because the value // is a sibling the typing-direction walk never reaches. Left commented so // the corpus stays clean in both directions.以上为语料文件原文摘录展示用注释行记录不检查的边界情况这一约定。用 indent-check 验证在仓库根目录运行cargo xtask indent-check [language][language]可省略省略时检查tests/indent/下所有语料文件见 xtask 帮助文本。例如只验证 rustcargo xtask indent-check rust输出判断依据以下消息格式取自 xtask/src/main.rs占位符为运行时实际值单行 reindent 不匹配rust.rs:23: reindent expected 8 columns, computed 4typing 方向缩进不足失败rust.rs:24: typing under-indents: computed 4 columns, expected 8 | 该行内容typing 方向缩进过多且无前置outdent提示不计失败rust.rs:25: note: typing over-indents: computed 12 columns, expected 8 (no leading outdent; review) | ...有 note 时追加汇总行Indent check: N typing over-indent note(s) (not failures; review for regressions)全部通过Indent check succeeded存在错误行Indent check failed: N line(s) with wrong indentation因此验证成功的判据是最后输出Indent check succeeded且命令返回成功失败时按行号定位到语料对应行回到indents.scm修正捕获或谓词后重跑。另外建议在编辑器里做人工复核。Helix 默认使用hybrid缩进启发式它只计算新行与已有行的缩进差值并叠加到已有行上这会使查询错误更难暴露指南明确建议测试时改用:set indent-heuristic tree-sitter该选项的取值还有simple直接复制上一行缩进选中的启发式不可用时按hybrid→tree-sitter→simple回退见 editor.md 的indent-heuristic选项说明。限制与排错indent-check对每个语料文件要求三项条件主名能解析到已配置语言、该语言有indent配置、加载器能找到该语言的缩进查询任一缺失会报对应错误no configured language with id ...、has no indent config、has no indent query。检查器内部固定以tab_width 4计算列宽见 xtask/src/main.rs比对的是缩进的列数。typing 方向的 over-indent 只是提示而非失败对缩进划界的语言如 Python 块结束后编辑器确实无法知道要回退多少级所以只统计并输出供回归比对。若切换分支后在编辑器中查询行为异常先执行hx --grammar fetch与hx --grammar build更新 grammar来自 adding_languages.md 的 Common issues。修改查询并通过indent-check后rust 语料的两个方向断言都成立即为本次任务的完成标志若要为新语言补上缩进可继续参照 添加新语言指南 中的查询文件清单。【免费下载链接】helixA post-modern modal text editor.项目地址: https://gitcode.com/GitHub_Trending/he/helix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表