Summary
Render blocks containing {{query: ...}} syntax by executing the query against the API and displaying results inline. Queries are one of Roam's power features for creating dynamic views of data.
Roam web behavior: {{query: {and: [[tag1]] [[tag2]]}}} renders as an embedded list of blocks matching the boolean query. Supports and, or, not, and between operators with page/tag references.
TUI adaptation: Read-only rendering — show query results inline as a collapsible list of matching blocks. No query editor (too complex for TUI). Users write queries in edit mode using standard text, and they render when exiting edit mode. Results are cached with a TTL to avoid excessive API calls.
Implementation hints
Parser
src/markdown.rs:34-63 — already parses {{...}} syntax for TODO/DONE/embed
- Add detection for
{{query: ...}} or {{[[query]]: ...}}
- Extract the query body (everything between
{{query: and }})
- Parse boolean operators:
{and: [...] [...]}, {or: [...]}, {not: [...]}
- Extract page references from the query conditions
Query translation
- Convert Roam query syntax to Datalog:
{and: [[tag1]] [[tag2]]}
→
[:find (pull ?b [:block/string :block/uid {:block/page [:node/title]}])
:where [?b :block/string ?s]
[?b :block/refs ?r1] [?r1 :node/title "tag1"]
[?b :block/refs ?r2] [?r2 :node/title "tag2"]]
src/api/queries.rs — add query_from_roam_syntax(query_body: &str) -> String
Rendering
src/ui/main_area.rs — add VisibleLine variant for query results:
QueryHeading { block_index, result_count } — shows "Query: N results" with toggle
QueryResult { depth, text, block_index } — each result block
- Collapsed by default (show count), expand to see results
- Results render with full markdown formatting
Caching
src/app.rs — add query result cache:
pub query_cache: HashMap<String, (Vec<Block>, Instant)>, // query_hash → (results, fetched_at)
- TTL: 60 seconds (configurable)
- Refetch on manual refresh
Supported operators (v1)
{and: [[A]] [[B]]} — blocks referencing both A and B
{or: [[A]] [[B]]} — blocks referencing A or B
{not: [[A]]} — blocks NOT referencing A
- Nested:
{and: [[A]] {not: [[B]]}} — A but not B
Acceptance criteria
Summary
Render blocks containing
{{query: ...}}syntax by executing the query against the API and displaying results inline. Queries are one of Roam's power features for creating dynamic views of data.Roam web behavior:
{{query: {and: [[tag1]] [[tag2]]}}}renders as an embedded list of blocks matching the boolean query. Supportsand,or,not, andbetweenoperators with page/tag references.TUI adaptation: Read-only rendering — show query results inline as a collapsible list of matching blocks. No query editor (too complex for TUI). Users write queries in edit mode using standard text, and they render when exiting edit mode. Results are cached with a TTL to avoid excessive API calls.
Implementation hints
Parser
src/markdown.rs:34-63— already parses{{...}}syntax for TODO/DONE/embed{{query: ...}}or{{[[query]]: ...}}{{query:and}}){and: [...] [...]},{or: [...]},{not: [...]}Query translation
src/api/queries.rs— addquery_from_roam_syntax(query_body: &str) -> StringRendering
src/ui/main_area.rs— addVisibleLinevariant for query results:QueryHeading { block_index, result_count }— shows "Query: N results" with toggleQueryResult { depth, text, block_index }— each result blockCaching
src/app.rs— add query result cache:Supported operators (v1)
{and: [[A]] [[B]]}— blocks referencing both A and B{or: [[A]] [[B]]}— blocks referencing A or B{not: [[A]]}— blocks NOT referencing A{and: [[A]] {not: [[B]]}}— A but not BAcceptance criteria
{{query: {and: [[tag1]] [[tag2]]}}}renders with results inlineand,or,notoperators work correctly