Skip to main content

Select Markdown sections by heading path

Project description

mdselect

中文说明

Select Markdown sections by heading path.

mdselect is a small, zero-runtime-dependency command-line tool for inspecting a Markdown outline and extracting complete sections without losing their original formatting.

Why mdselect?

Line-oriented tools such as grep can find a heading, but they do not know where that section ends. A full Markdown AST library understands much more of the format, but usually requires writing a program and choosing rendering semantics.

mdselect fills the gap:

  • query the heading hierarchy directly from the shell;
  • return a matched heading together with its body and descendants;
  • preserve the original Markdown content without parsing and re-rendering it;
  • use regular expressions in a compact heading path expression;
  • run with only the Python standard library.

Installation

mdselect requires Python 3.10 or newer.

pipx install mdselect
# or
uv tool install mdselect
# or
python -m pip install mdselect

To install a development checkout:

python -m pip install -e ".[test]"

Quick start

Given handbook.md:

# Engineering Handbook

## Getting Started

Introductory material.

### Local Setup

Create a virtual environment.

## Operations

Operational notes.

Print its outline:

mdselect outline handbook.md
# Engineering Handbook
  ## Getting Started
    ### Local Setup
  ## Operations

Extract the complete Getting Started subtree:

mdselect select --mpath '/Engineering/Getting Started' handbook.md
## Getting Started

Introductory material.

### Local Setup

Create a virtual environment.

Add a trailing slash to omit the matched heading line:

mdselect select --mpath '/Engineering/Getting Started/' handbook.md

mpath syntax

An mpath is a slash-separated heading path:

Form Meaning
/Guide/Install Absolute query: the first segment only matches level-one headings.
Install Relative query: the first segment matches headings at any level.
/^Guide$/^Install$/ Each segment is a Python regular expression; anchors make matches exact. The trailing slash omits the matched heading.
/ Return the original document unchanged.

The complete rules are:

  1. Each non-empty segment is compiled as a Python regular expression and matched with re.search.
  2. A leading slash makes the query absolute: its first segment is tested only against level-one (#) headings.
  3. Without a leading slash, the first segment is tested against every heading.
  4. Every later segment is tested against descendants of the current matches, at any depth.
  5. A trailing slash excludes the final matched heading line while keeping its body and descendants.
  6. /, //, and an empty expression are no-ops that return the original document.
  7. A slash cannot appear inside a segment.
  8. Multiple matches retain document order and are separated by one blank line.
  9. When both an ancestor and its descendant match, only the ancestor is rendered as a result because its subtree already contains the descendant.

mdselect select -h prints these rules without requiring the README.

Exit status

Situation Status
Successful outline or selection 0
No matching section 0, with empty standard output
Invalid arguments or regular expression 2
File cannot be read non-zero

The no-match behavior is intentional so selection can be used in shell pipelines without treating an optional section as a command failure.

Supported Markdown and boundaries

  • ATX headings from # through ###### are supported when the marker starts in column one and is followed by whitespace.
  • Optional closing hash markers are removed from the heading title used for matching.
  • Backtick and tilde fenced code blocks are recognized; heading-like lines inside a fence are ignored.
  • Selected content is rendered from the original lines, preserving tables, blockquotes, blank lines, inline markup, and fences.
  • Files are read as UTF-8.
  • Setext headings are not supported.
  • mdselect does not interpret front matter, links, inline Markdown, or HTML as an AST.

Comparison

Tool Best for Structural section extraction
grep / rg Finding matching lines across files No
Markdown AST library Full parsing, transformation, and custom rendering Yes, with application code
mdselect Shell-friendly outline and heading-subtree selection Yes, directly from the CLI

Use grep or rg to discover candidate files, then use mdselect when the unit you need is a Markdown section rather than a line.

Python API

from mdselect import outline, select

print(outline(markdown_text))
section = select(markdown_text, "/Guide/Install")

The package also exports Section, parse, render_subtree, and InvalidPattern.

Contributing and security

See CONTRIBUTING.md for development and pull request guidance. Report security issues privately as described in SECURITY.md.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mdselect-0.1.0.tar.gz (16.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mdselect-0.1.0-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file mdselect-0.1.0.tar.gz.

File metadata

  • Download URL: mdselect-0.1.0.tar.gz
  • Upload date:
  • Size: 16.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mdselect-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d2fe9208e4c9cb5a7339c9ced274ba654a13152f027812c487f8ff7019815cd3
MD5 fd9d0c3605c63040c822e054ca8787df
BLAKE2b-256 e40f42d9d483eb7bc3184d6261e26d63489d277df06b7585d29487499c8c5641

See more details on using hashes here.

Provenance

The following attestation bundles were made for mdselect-0.1.0.tar.gz:

Publisher: release.yml on stevenybw/mdselect

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mdselect-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mdselect-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mdselect-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9cdf6f1134d1cb6a26f9e50aab852f4507551fd40c6aecde267dcb6436f43483
MD5 7abf906e18a6c063d398280d486790e0
BLAKE2b-256 a5ba2f1c0a61e5843929b8e15dce93d16e7663459d3206bef74399b15474db94

See more details on using hashes here.

Provenance

The following attestation bundles were made for mdselect-0.1.0-py3-none-any.whl:

Publisher: release.yml on stevenybw/mdselect

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page