Skip to content

section selectors: add min and max levels#419

Open
yshavit wants to merge 4 commits intomainfrom
section-headings
Open

section selectors: add min and max levels#419
yshavit wants to merge 4 commits intomainfrom
section-headings

Conversation

@yshavit
Copy link
Owner

@yshavit yshavit commented Mar 16, 2026

Syntax

#{2} "matches exactly h2 sections"
#{2,} "matches h2 - h6 sections"
#{,2} "matches h1 - h2 sections"
#{2,4} "matches h2 - h4 sections"

Note that mdq always returns the first element that matches, along with all its children. Thus, if you have:

# Some heading

Lorem ipsum.

## Subheading

Dolor sit amet.

... then #{1} will return the whole thing, as a single matched entity. The #{1} matches the # Some heading, and then everything else gets brought in with it.

In practice, this means that #{n,} is only useful if headings get defined in the wrong order (h3 before h2 before h1, as in the "preamble" headings in the integ tests on this PR.)

Resolves #120.

Breaking changes

Adds fields to SectionMatcher

@yshavit yshavit added bug Something isn't working enhancement New feature or request ai-review Tag a PR with this to get an AI review. breaking change Non-backwards-compatible change to API or CLI. CLI Affects the CLI API Affects the API labels Mar 16, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

Adds optional heading-level options to section selectors. Grammar changes introduce section_opts, section_num, and section_comma and update section_start to accept optional {min[,max]}-style level notation. Parser and selector construction (selector_try_from.rs) parse and validate level bounds (1–6) and populate level_min/level_max on SectionMatcher. Those fields are propagated into SectionSelector and enforced in selection logic (sel_section.rs) to accept or reject sections by depth. Traversal/composite structs and tests are updated to carry and exercise the new tag fields and behaviors. Error-message mappings for the new grammar rules are added.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • yshavit/mdq PR 338: Modifies SectionMatcher and its conversion paths used by selector construction—overlaps with the added level_min/level_max fields.
  • yshavit/mdq PR 375: Alters grammar/selector paths (grammar.pest, selector_try_from.rs, sel_section.rs) and introduces replacement features that intersect with these parsing and selector changes.
  • yshavit/mdq PR 403: Rewrites selection/replacement flow in sel_section.rs and touches the same selector types and try_select logic adjusted here.

Grade: A-

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding min/max level constraints to section selectors.
Docstring Coverage ✅ Passed Docstring coverage is 82.76% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The PR description clearly explains the new section-level selector syntax and its behavior, directly aligned with the changeset across grammar, parsing, and selection logic.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch section-headings
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can generate a title for your PR based on the changes with custom instructions.

Set the reviews.auto_title_instructions setting to generate a title for your PR based on the changes in the PR with custom instructions.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/select/selector.rs`:
- Around line 41-46: The doc for the `level_max` field is inverted: clarify that
`level_max` is an inclusive upper bound on heading depth so a heading with level
n matches when n ≤ level_max; update the example in `selector.rs` to show that
`##` (h2) matches `level_max: 2` and `level_max: 3` but not `level_max: 1`, and
note that if `level_max` is None all levels are allowed; make sure to keep the
field name `level_max` and its Option<u8> semantics unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9f053318-9fc1-4f73-9e3a-1b1c5973ef6e

📥 Commits

Reviewing files that changed from the base of the PR and between 811e303 and 44a5ada.

📒 Files selected for processing (8)
  • src/query/grammar.pest
  • src/query/pest.rs
  • src/query/selector_try_from.rs
  • src/query/traversal_composites.rs
  • src/select/sel_section.rs
  • src/select/selector.rs
  • tests/md_cases/bad_queries.toml
  • tests/md_cases/select_sections.toml

chatgpt-codex-connector[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

@PhilipHayes
Copy link

This looks great, also, if I wanted to just get the headers so that I have a skeleton of an MD file what would you suggest?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Tag a PR with this to get an AI review. API Affects the API breaking change Non-backwards-compatible change to API or CLI. bug Something isn't working CLI Affects the CLI enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants