codeblocks
Extract and process code blocks from Markdown files. Now you can keep code examples automatically:
- formatted (e.g. using black for Python)
- type checked
- unit tested
- linted
- up-to-date with
--help
- etc
Quick start
(if uv is available)
Try codeblocks
without installing:
uvx codeblocks --help
Install to PATH
:
uv tool install codeblocks
codeblocks --help
Install with Python package manager
With pip
:
pip install codeblocks
With uv
:
uv add codeblocks
With poetry
:
poetry add codeblocks
Usage
Usage: codeblocks [OPTIONS] LANGUAGE FILE [COMMAND]...
Extract or process LANGUAGE code blocks in Markdown FILE.
Extract Python code blocks:
codeblocks python README.md
Reformat Python code blocks with `black`, in place:
codeblocks python README.md -- black -
Options:
--wrap Wrap each code block in a function.
--check Do not modify the file, just return the status. Return code 0
means block matches COMMAND output. Return code 1 means block
would be modified.
--version Show the version and exit.
--help Show this message and exit.
Examples
Extract Python code blocks:
codeblocks python README.md
Check formatting of Python code blocks with black:
codeblocks --check python README.md -- black -
Reformat Python code blocks with black, in place:
codeblocks python README.md -- black -
Type check Python code blocks with mypy (--wrap
puts each code block into its own function):
mypy somemodule anothermodule <(codeblocks python --wrap README.md)
Insert the output of codeblock --help
into usage
block in this README.md:
codeblocks usage README.md -- codeblocks --help
Check that usage
block in this README.md is up-to-date with --help
output:
codeblocks --check usage README.md -- codeblocks --help
Full type checking example
def plus(x: int, y: int) -> int:
return x + y
plus(1, '2')
$ mypy --pretty <(codeblocks python README.md)
/dev/fd/63:5: error: Argument 2 to "plus" has incompatible type "str"; expected "int" [arg-type]
plus(1, '2')
^~~
Found 1 error in 1 file (checked 1 source file)
Rationale
There are alternative tools, but none of them supported all of the cases above.