cl-termdown parses a restrained Markdown subset into terminal-oriented semantic spans. It preserves Unicode cell widths, whole-word wrapping, bullets and numbered lists, inline emphasis and code, bounded pipe tables, fenced syntax highlighting, and speculative streaming previews.
Rows are lists of neutral cons spans whose car is a keyword role and whose
cdr is text. The caller styles them.
(asdf:load-system :cl-termdown)
(let ((renderer (termdown:markdown-renderer-create :width 48)))
(termdown:markdown-render-line
renderer
"- render **strong** and `code` spans"))
;; => (((:PLAIN . " ")
;; (:BRAND . "• ")
;; (:PLAIN . "render ")
;; (:STRONG . "strong")
;; (:PLAIN . " and ")
;; (:CODE . "code")
;; (:PLAIN . " spans")))One renderer retains fenced-code and pipe-table state across logical lines.
Call markdown-render-line when a newline commits that logical line.
(multiple-value-bind (committed live retained)
(termdown:markdown-render-partial renderer "unfinished **strong")
(values committed live retained))markdown-renderer: stateful renderer classmarkdown-renderer-create: create a renderer with:widthmarkdown-renderer-width: read its effective row widthmarkdown-renderer-closed-code-source: the raw text of the fence that just closed, ornilonce another fence opens; its closing row ends in a:code-copyspan that applications may turn into a copy controlmarkdown-render-line: render and commit one logical linemarkdown-render-inline: render inline Markdown within an exact widthmarkdown-render-partial: preview an uncommitted logical line as three valuesmarkdown-render-finish: flush an unfinished buffered diagram as source at EOFmake-span,span-p,span-role,span-text: neutral(role . text)spansspans-width: total Unicode terminal-cell width of a span rowcolumn-widths: allocate cell-aware table column widthsfit-text: clip and align a single table cellspans-text: concatenate sanitized visible text, optionally as one linefit-spans: clip sanitized spans by cells without splitting graphemesrender-spans: render sanitized text with an optional trusted:style-functionaccepting(role text)and returning presentationmake-widget,widget-p,widget-role,widget-label,widget-action: a label shown like a span of its role that carries an application action; every span function above presents it as its labelpresentation-spans: replace widgets by the spans of their labelswidget-regions: the(start end action)character extents of the widgets in a row, indexingspans-text, from an optional:startoffsetshift-regions,region-action: move regions after their text is joined to other text, and find the action covering a character offsetselector-table-rows: span rows for a vertical Clinedi selector’s visible window as a table, with a selection marker, a label column, further columns from:column-functionsreturning strings or spans and aligned across the visible rows, and a heading row wherever:group-functionchanges group; columns empty in every visible row are left out, and the roles are keyword arguments; a selector that is not vertical signalsselector-arrangement-error, atype-errorwhoseselector-arrangement-error-selectorreturns the selector
Semantic roles include :plain, :brand, :dim, :strong, :emphasis,
:code, :code-copy, :notice, and the :syntax-* roles produced by Colordiff.
./script/bootstrap
./script/check
./script/check --fix./script/check runs CL-TERMDOWN/TESTS in an isolated source registry, then
checks the source with cheque as
cheque.sexp configures it. --fix skips the tests and repairs what cheque can
repair. cheque and its tools are development dependencies: checks/qlfile
lists them, and the check installs them on first use into
~/.cache/cheque/tools/.
cl-termdown uses Clinedi for Unicode geometry and wrapping, Clermaid for terminal diagrams, ColorLisp and Colordiff for fenced-code highlighting, and Serapeum for declarations. Qlot pins the tested dependency revisions.
cl-termdown uses COLL-Attribution. The authoritative terms are in
LICENSE.lisp.
Fenced blocks tagged mermaid render through Clermaid when they close.
Read the original body from markdown-renderer-closed-code-source and use the
closing row’s :code-copy span to add a copy control. Unsupported, malformed,
excessively large, or too-wide diagrams display numbered source with a :notice
diagnostic before it. The diagnostic includes Clermaid’s failure category and
condition report, sanitized and wrapped to the renderer’s terminal-cell width.
A source-limit diagnostic appears as soon as a fence exceeds the buffering limit.
Open diagrams appear only in speculative previews. Call markdown-render-finish
at the end of a document or interrupted stream to display incomplete source.
See Clermaid’s README for the supported syntax.
Flowchart subgraphs render as labeled frames, including nested groups and edges between grouped nodes. For example:
flowchart TD
subgraph Local["Local machine"]
C[Client] --> S[Server]
end
S --> R[Remote]
Clermaid parses the groups and draws their frames and connections. Use the same Markdown rendering API for grouped and ungrouped diagrams.