From 606bf7457ff74092dec38464603d27b497168971 Mon Sep 17 00:00:00 2001 From: Daniel Hanson Date: Tue, 8 Sep 2026 19:13:56 -0500 Subject: [PATCH] add exports query --- CLAUDE.md | 5 +++-- queries/exports.scm | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 queries/exports.scm diff --git a/CLAUDE.md b/CLAUDE.md index 3735456..ab09c8e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -225,8 +225,9 @@ filter added from a library belongs in it. `queries/locals.scm` relies on the `v binding from a reference — another reason to keep `asVariable` uniform. `{% blocktranslate %}`'s `asvar` target carries an `asvar:` field instead, because it is written inside the tag but assigned outside it: the scope on `blocktranslate_group` confines the `with` and `count` bindings, and would swallow `asvar` -too if it were spelled the same way. Defining it in the surrounding scope is left to the tool, since a -locals query cannot let a definition out of the scope that contains it. +too if it were spelled the same way. `queries/exports.scm` names it for a tool to +bind in the scope around the block, which a locals query cannot do: it places a definition in the innermost +scope containing it and offers no way out again. ## Testing diff --git a/queries/exports.scm b/queries/exports.scm new file mode 100644 index 0000000..6497eb3 --- /dev/null +++ b/queries/exports.scm @@ -0,0 +1,25 @@ +; Names a tag binds in the scope *around* it rather than in the scope it opens. +; +; queries/locals.scm cannot express this: a locals query places a definition in +; the innermost @local.scope whose span contains it, and there is no way to let +; one out again. A tool reads this file alongside locals.scm and binds +; @export.name in the nearest scope enclosing @export.from, not inside it. +; +; Only blocktranslate does this. Its asvar target is written inside the opening +; tag — which is inside the scope, because the "with" and "count" bindings in +; that same tag do belong to the block — but it holds the rendered text and is +; read after the block: +; +; {% blocktranslate with bar=foo asvar var %}…{% endblocktranslate %} +; {{ var }} +; +; It carries an "asvar" field rather than "variable" so locals.scm leaves it +; alone. Every other "as name" clause is written in a tag that opens no scope, +; so locals.scm already places those correctly and none of them belong here. +; +; asvar and the "with" bindings may be written in either order, so no single +; scope span could have separated them; that is why this is a separate file +; rather than a narrower scope in locals.scm. + +(blocktranslate_group + asvar: (identifier) @export.name) @export.from