Skip to content
← All projects

DML (Display Markdown & LaTeX)

A command-line tool that reads Markdown and LaTeX from standard input, renders math as terminal images via the Kitty graphics protocol, and applies rich Markdown formatting.

Go Command Line LaTeX

DML is a command-line tool designed for developers and scientists who live in the terminal. It reads Markdown and LaTeX from standard input, dynamically renders math expressions into terminal images using the Kitty terminal graphics protocol, and applies rich Markdown formatting to the output. Built in Go, it’s a single statically-linked binary with no runtime dependencies beyond a TeX distribution and ImageMagick.

Key Features

  • Inline & Display LaTeX Math: Renders $formula$ (inline) and $$formula$$ (display) as terminal images. Inline math is rendered to exact pixel baseline and stays neatly on a single terminal line — no line-breaking artifacts.
  • Rich Markdown Formatting: Supports bold (**text**), italic (*text*), strikethrough (~~text~~), lists (- item, 1. item), blockquotes (> text with prefix), links ([text](url) as underlined text), inline code (`code` in reverse video), and horizontal rules (--- as box-drawing lines).
  • Unicode Tables: Automatically renders Markdown tables with crisp Unicode box-drawing characters (┌─┬─┐ style).
  • High-Performance Caching: Disk-backed LRU PNG cache at ~/.cache/dml/ (default 100 MB). Cache keyed on SHA-256 of LaTeX source + colour + DPI + display/inline. Repeated renders load instantly from disk.
  • Adaptive DPI: Automatically scales the render resolution to match your exact terminal cell height (default range 96–600 DPI) by querying the terminal’s cell dimensions via the Kitty protocol.
  • Unicode Fast Path: Simple expressions (e.g. \alpha → α, x^2 → x²) render directly as Unicode without invoking the LaTeX pipeline.
  • Customisable Colour: Set the colour for rendered LaTeX images with --colour (-c), accepting named colours or hex codes.

Code Structure

cmd/dml/        ← CLI entry point and flag processing
internal/
├── cache/      ← Disk-backed LRU PNG cache
├── colour/     ← Colour processing and management
├── latex/      ← LaTeX rendering pipeline + ImageMagick conversion
├── markdown/   ← Markdown processing, AST traversal, table rendering
├── regex/      ← Math delimiter detection patterns
├── terminal/   ← Kitty protocol, cell size queries, adaptive DPI
└── unicode/    ← Unicode fast-path for simple expressions

Rendering Pipeline

  1. Input arrives via stdin, processed line-by-line with block buffering for complex structures.
  2. The Markdown processor tokenises input into an AST, distinguishing text, headings, lists, blockquotes, code blocks, tables, and math delimiters.
  3. For each math expression, DML first checks if it’s a simple Unicode-renderable expression. If so, it renders instantly. Otherwise, it computes a cache key and checks the disk cache.
  4. On a cache miss, the expression is wrapped in a LaTeX template, compiled with pdflatex (display mode) or latex + dvipng (inline mode), converted to PNG via ImageMagick, and stored in the cache with metadata (dimensions, baseline offset).
  5. The terminal renderer outputs formatted text and sends PNG data via the Kitty graphics protocol with exact placement and baseline alignment.

Installation

git clone https://github.com/JamieLittle16/dml && cd dml
./build.sh            # builds the binary
./build.sh install    # installs to /usr/local/bin + man page

Prerequisites: Go 1.18+, pdflatex/latex (TeX distribution), ImageMagick, and a Kitty-compatible terminal (also works with Ghostty and iTerm2).

Usage Examples

cat my_document.md | dml
echo '$E=mc^2$ and **bold text**' | dml --colour blue
dml --cache-stats         # show cache hits/misses
dml --cache-clear         # purge all cached renders
dml --render-all-latex < file.md  # render entire doc as one LaTeX image