Table of contents
Markdown support
Answers are parsed and rendered as they stream in, and re-rendered on every frame until they are complete — see How it works.
What gets formatted
Headings, bold, italic, strikethrough, inline code, bulleted and ordered lists with nesting, task checkboxes, quotes, rules, aligned tables shrunk to fit the terminal, and clickable OSC 8 links — the link text is shown, never the URL.
No markdown marker is ever printed: **bold** arrives as bold text, not as
text with asterisks around it.
Tables are measured in display columns, so a table of accented or CJK text stays rectangular where a byte-counting renderer would leave it ragged.
Code blocks
Code blocks are boxed, labelled with their language, and coloured by a small in-house tokenizer — comments, strings, numbers, keywords, call sites and types:
╭─ rust ───────────────────────────────────╮
│ // comment │
│ fn main() { │
│ let x = 1; │
│ } │
╰──────────────────────────────────────────╯
Recognised: rust, python, js/ts/tsx/jsx, java/kotlin/scala/groovy, c/c++/c#,
go, sh/bash/zsh, sql, json, yaml/toml/ini, and diff. Anything else renders
in one colour rather than guessing.
The highlighter is approximate by construction — it is a tokenizer, not a grammar. A real one (syntect) would cost about thirty extra crates for a better-coloured code block, which is not the trade papote makes.
Indentation inside a code block is preserved when it wraps; prose is wrapped
on word boundaries, with French spacing rules so a lone ? or » is never
stranded at the start of a line.
papote
Getting started
Using it
Under the hood