Repository navigation
readaloud 2.0.0
The computational half of readaloud is now Rust, and a source file is read through its
syntax tree and coloured like an editor would.
A Rust core
- Everything that is computation moved out of Python into a compiled extension,
readaloud._core, built with PyO3 and maturin: terminal cell widths (wide CJK and
emoji), the pronunciation engine, word and sentence splitting and chunking, the
escape-sequence parser with its Markdown cleanup, and the alignment of Kokoro's
timestamps onto the spoken words. The Python that remains is the interface: the
config file, the document model, the TUI, playback. - Each port is checked against the Python it replaced, on random input as well as the
known cases, so a file reads exactly as it did. The Unicode tables are generated from
Python's own database, so the two sides never disagree about a character. - The Homebrew bundle ships the extension built on the macOS 14 runner with the pinned
Rust; nothing is compiled on your machine.
Source code, read and coloured through its grammar
- A
.pyfile is parsed with tree-sitter and said node by node the way you describe
it in a[syntax.py]section:def foo(bar: int, baz: str='') -> str:can be
"function foo takes bar type int and baz type string with a default of empty string
and returns type string", a|in a type annotation "or" and one between sets
"pipe",foo().bar"foo dot bar",__init__"dunder init". A rule names a node's
fields ($name,$parameters), the node in full ($0) or its parts ($*), and may
be confined to a context (type/binary_operator) or a field
(function_definition.return_type). Comments, strings and docstrings are untouched
unless a rule names them. See Syntax. - The file is coloured by the grammar's own highlights query, in the terminal's
colours: keywords, strings, comments, function and type names.highlight = noor
--no-colorleaves it plain. - Grammars are plug-ins. readaloud ships the tree-sitter runtime and no grammar; a
language's grammar is loaded at run time from itstree-sitter-<language>package
(prebuilt wheels, no compiler) or from a Neovimparser/directory. The Homebrew
install has Python's;uv tool install readaloud --with tree-sitter-rustadds Rust. - Each spoken word lights the word it came from: "takes" lights the first
parameter, "or" the type after the|, and a body of code keeps its lines. - A section can apply to one file type:
[config.py],[parts.py],[shapes.py],
[pronunciations.py]and[syntax.py]lay over the general ones for a file with
that suffix, andmarkdown = noreads it as written, so code keeps its#,*args
and underscores. See File types.
Shapes
- Shapes and parts live in the config file, with none built in: a
[shapes]line is
a regular expression and how to say what it matched,[parts]the named pieces the
patterns are built from. The shipped file readssettings.py:281-283as "settings dot
pie lines 281 to 283",localhost:8080as "local host port 8080", a URL with its
scheme, host, port and each slash of its path, and leaves a time as written. - Named shapes (
param: /pattern/ = wording) let a wording say a list of any
length:${params|param|,=and}says every match ofparamin the group, with "and"
for each comma. A shape may span 48 words and several lines. - What a shape or a rule says goes through the pronunciation entries and the patterns
once more, so.py = dot pieand/__(\w+)__/ = dunder $1apply inside them.
Config file: one change to make
- The settings section is
[config], not[readaloud]. A file that still says
[readaloud]is warned about and its settings fall back to their defaults until the
header is renamed. Everything else in an existing file reads as before. - The file a first run writes, and
--write-config, isreadaloud.confshipped as it
is, with one-line comments and the pronunciations in groups.
Other changes
follow_margindefaults to 5 rows: the spoken word stays about six rows from the top
in follow mode, with the text below it in view.- The README no longer suggests
mdcat --ansi notes.md | readaloud: a piped table reads
line by line;-mdreads it cell by cell. tests/fixtures/edge-cases.mdgathers the text that is hardest to read well, for
listening to by hand.