Skip to content

Add ASCII rendering fallback for terminals without image protocols#158

Open
jpeletier wants to merge 5 commits into
lusingander:masterfrom
jpeletier:graphics
Open

Add ASCII rendering fallback for terminals without image protocols#158
jpeletier wants to merge 5 commits into
lusingander:masterfrom
jpeletier:graphics

Conversation

@jpeletier
Copy link
Copy Markdown

Summary

Adds a Unicode box-drawing fallback (--protocol ascii) so serie works in any terminal — gnome-terminal, alacritty, xterm, Windows Terminal, etc. — without needing the Kitty or iTerm2 image protocols. Auto-detect now uses it as the default for terminals it cannot identify, instead of unconditionally trying iTerm2.

What changed

  • New ImageProtocol::Ascii variant, selectable via --protocol ascii or core.option.protocol = \"ascii\" in config.
  • Auto-detect rewritten — picks Kitty for KITTY_WINDOW_ID / Ghostty, iTerm2 when TERM_PROGRAM matches iTerm.app / WezTerm / mintty / vscode (or LC_TERMINAL=iTerm2), and ASCII otherwise.
  • Single-width ASCII renders one character per branch column with ● ─ │ ╭ ╮ ╰ ╯ (rounded) or ┌ ┐ └ ┘ corners with --graph-style angular.
  • Double-width ASCII renders two characters per column, with for merge commits and > / < arrows in the filler slot showing which side the merged-in branch enters from. Merges are detected by LeftTop / RightTop corner edges in the row (branch-source commits stay as ).
  • 38 new unit tests cover edge_directions, ascii_symbol for both styles, render_ascii_row single + double width, merge-vs-branch-source discrimination, and arrow placement. Test count: 83 unit + 19 integration (was 45 + 19).
  • Docs updated: README, FAQ (previously claimed there was no fallback), introduction, command-line options, config file format, compatibility page, and config.schema.json.

Example

A synthetic repo with three feature branches merged back to master, rendered with --protocol ascii --graph-width double --graph-style rounded:

○<╮     ce2322a merge feature-c
│ ●     8d7fabb c1
●─╯     9c67479 m5
○<╮     9be857e merge feature-b
○<┼─╮   00516ad merge feature-a
│ ● │   02109cc b1
│ │ ●   84f0caf a2
●─╯ │   75afbd5 m4
│   ●   c5ec6e2 a1
●───╯   ca95409 m3
●       d676cb3 m2
●       468b4b8 m1
●       1efc5bb init
image

Each merge commit shows as with a < (or >) arrow pointing into it from the side the merged-in branch curls down to. Branch-source commits (like m5, m3) stay as because their corner edges are LeftBottom/RightBottom, not LeftTop/RightTop. Branch colors come from the existing palette.

In single-width mode the same graph collapses to one character per column:

○╮    merge feature-c
│●    c1
●╯    m5
○╮    merge feature-b
○┼╮   merge feature-a
│●│   b1
││●   a2
●╯│   m4
│ ●   a1
●─╯   m3

Test plan

  • cargo test --release passes (102 tests total)
  • cargo build --release produces a clean binary
  • Manual smoke test in gnome-terminal — ASCII fallback renders correctly
  • Manual smoke test with --protocol ascii --graph-style angular — produces angular corners
  • Manual smoke test with --protocol ascii --graph-width double — produces + arrows on merges

jpeletier added 5 commits May 15, 2026 02:16
Adds a new ImageProtocol::Ascii variant that renders git commit graphs
using Unicode box-drawing characters (─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼) instead of
terminal graphics protocols. Each graph column becomes a single character
cell, with commit nodes rendered as `*` and colored per branch.

Auto-detection now conservatively falls back to ASCII when the terminal
doesn't support Kitty graphics or recognized iTerm2-compatible protocols
(iTerm.app, WezTerm, mintty, VSCode, or LC_TERMINAL=iTerm2). This makes
the tool work out-of-the-box in standard terminals like gnome-terminal,
alacritty, xterm, and others, while preserving fancy image rendering for
terminals that support it.

Users can explicitly select ASCII mode with `--protocol ascii` or configure
it in their serie config file.
Honor the configured GraphStyle in ASCII rendering: use rounded
corners (╭╮╰╯) for Rounded and angular (┌┐└┘) for Angular. Render
commit nodes as ● instead of * for better visual weight.
Honor --graph-width double in ASCII mode (was previously forced to single).
In double-width mode each graph column spans two character cells: a symbol
followed by a filler that becomes ─ when a horizontal edge crosses the gap,
or a space otherwise.

Distinguish merges from branch sources by the corner type in the row:
LeftTop/RightTop corners signal a parent merging up from below, so the
commit renders as ○ with a > or < arrow pointing into it from the adjacent
filler slot. Branch sources (LeftBottom/RightBottom corners) keep the
solid ● glyph and a plain ─ filler.

Extract render_ascii_row from build_ascii_prepared_image so the row-level
rendering can be unit-tested without constructing a full Graph. Adds 38
unit tests covering edge_directions, ascii_symbol for both styles, single
and double width row rendering, merge-vs-branch-source discrimination, and
> / < arrow placement.
Update README, mdBook docs, and JSON config schema to cover the new ASCII
rendering mode added in this branch. Also reframes the project tagline
from "uses image-display protocols" to "uses image-display protocols
where available, with a Unicode fallback otherwise", and rewrites the
FAQ entry that previously stated there was no fallback.

- README: add `ascii` to the protocol enum in the help block and to the
  "Supported terminals" list; soften the tagline.
- docs/introduction: match README tagline.
- docs/faq: replace "no fallback" answer with a list of the supported
  rendering modes and how to force ASCII.
- docs/configurations/config-file-format: add `ascii` to the
  `core.option.protocol` enum and describe what each value does.
- docs/getting-started/command-line-options: list `ascii`, document the
  new auto-detect order (Kitty → iTerm-family terminals → ASCII), and
  note that ASCII honors --graph-style and --graph-width.
- docs/getting-started/compatibility: add an "ASCII fallback" section
  describing the supported glyph variants, expand the tmux entry to
  cover the ASCII case, and note that previously-unsupported environments
  (Sixel-only terminals, other multiplexers) still work via ASCII.
- config.schema.json: add `ascii` to the protocol enum.
auto_detect() correctly degraded the Kitty branch to KittyUnicode (which
wraps escapes in a tmux passthrough envelope) when running under tmux,
but the iTerm2 branch had no equivalent guard. Since iterm2_encode emits
a raw \x1b]1337;...\x07 OSC sequence with no passthrough wrapping, a
tmux session that leaks TERM_PROGRAM=iTerm.app (the common case) would
get the iTerm2 protocol selected and silently render nothing — defeating
the whole point of the ASCII fallback added in this branch.

Gate iTerm2 on !detect_tmux(). Under tmux without Kitty, auto_detect now
returns Ascii, which matches what compatibility.md already claims.

Extract the if/else into decide_protocol(kitty, iterm, tmux) so the
matrix is testable without process-global env-var mocking. Adds 7 unit
tests covering every combination of signals.

Reported in code review at #1.
@lusingander
Copy link
Copy Markdown
Owner

#66 (comment)

@jpeletier
Copy link
Copy Markdown
Author

Got it--I did this because I was frustrated I downloaded serie and no graph appeared and I had all this black area on the left, I didn't know what was happening so I added this fallback mode. I use Ubuntu, but the graph didn't appear in neither the stock console app, Alacritty or with Zellij I use. So here is my fork https://github.com/jpeletier/serie , in case anyone finds it useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants