Skip to content

✨ feat(selector): add recursive descent selector (..)#1234

Merged
harehare merged 4 commits intomainfrom
feat/recursive-selector
Feb 8, 2026
Merged

✨ feat(selector): add recursive descent selector (..)#1234
harehare merged 4 commits intomainfrom
feat/recursive-selector

Conversation

@harehare
Copy link
Copy Markdown
Owner

@harehare harehare commented Feb 8, 2026

Add a new .. recursive selector that matches and returns all descendant nodes of a markdown element. Rename TokenKind::RangeOp to TokenKind::DoubleDot to clarify its dual role as both the range operator and the recursive selector token. Refactor eval_selector to return RuntimeValue directly instead of bool.

Add a new `..` recursive selector that matches and returns all
descendant nodes of a markdown element. Rename `TokenKind::RangeOp`
to `TokenKind::DoubleDot` to clarify its dual role as both the range
operator and the recursive selector token. Refactor `eval_selector`
to return `RuntimeValue` directly instead of `bool`.
Copilot AI review requested due to automatic review settings February 8, 2026 02:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a .. recursive descent selector to return all descendant Markdown nodes and updates the language pipeline to treat selectors as value-producing expressions rather than boolean predicates.

Changes:

  • Introduces Selector::Recursive (..) and parses it through lexer/CST/AST.
  • Renames TokenKind::RangeOp to TokenKind::DoubleDot and wires it through parsers.
  • Refactors eval_selector to return RuntimeValue, adding recursive traversal evaluation.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
crates/mq-markdown/src/node.rs Adds a children() accessor used to traverse descendants for ...
crates/mq-lang/src/selector.rs Adds the Recursive selector and display/parse tests.
crates/mq-lang/src/lexer/token.rs Renames token kind for .. to DoubleDot.
crates/mq-lang/src/lexer.rs Emits TokenKind::DoubleDot for ...
crates/mq-lang/src/eval/builtin.rs Changes selector evaluation to return RuntimeValue; implements recursive descent.
crates/mq-lang/src/eval.rs Adapts evaluator to new selector return type.
crates/mq-lang/src/cst/parser.rs Updates CST parsing to accept DoubleDot where RangeOp was used.
crates/mq-lang/src/ast/parser.rs Updates AST parsing/precedence and introduces .. as a selector expression.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Feb 8, 2026

CodSpeed Performance Report

Merging this PR will not alter performance

Comparing feat/recursive-selector (3b0ebb4) with main (7c6e391)

Summary

✅ 29 untouched benchmarks

Copilot AI review requested due to automatic review settings February 8, 2026 13:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

crates/mq-lang/src/cst/parser.rs:1

  • The DoubleDot selector branch returns node without attaching children (and likely without recording the selector token in the CST), unlike the TokenKind::Selector(_) branch. This can lead to an incomplete CST node for ... Align the DoubleDot handling with the selector path by populating the CST children/token consistently.
use std::{collections::BTreeSet, fmt::Display, iter::Peekable};

@harehare harehare requested a review from Copilot February 8, 2026 13:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

crates/mq-lang/src/cst/parser.rs:1

  • TokenKind::DoubleDot returns node without showing how it gets converted into a Selector::Recursive CST node (unlike the AST parser which explicitly maps DoubleDotSelector::Recursive). This risks producing an incorrect/empty selector node in the CST. Suggest explicitly setting the selector kind for DoubleDot here (or update Selector::try_from(&Token) / token-to-selector conversion to support TokenKind::DoubleDot directly, and then reuse the same path as other selectors).
use std::{collections::BTreeSet, fmt::Display, iter::Peekable};

Comment on lines +3841 to +3842
pub fn eval_selector(node: &mq_markdown::Node, selector: &Selector) -> RuntimeValue {
let is_match = match selector {
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eval_selector now constructs RuntimeValue::Markdown(node.clone(), None) on match, which can drop existing per-value metadata carried in the second field of RuntimeValue::Markdown (previously preserved by returning runtime_value.clone() in eval_selector_expr). Consider either (a) keeping eval_selector as a predicate and letting the caller return the original RuntimeValue, or (b) changing eval_selector to accept the full &RuntimeValue (or metadata) so it can preserve the original (node, meta) for non-recursive selectors.

Copilot uses AI. Check for mistakes.
@harehare harehare merged commit 7476aba into main Feb 8, 2026
7 checks passed
@harehare harehare deleted the feat/recursive-selector branch February 8, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants