Precomputed metadata for Unicode pseudographic characters
Table of Contents
Before and After
Overview
Here you will find several data files and the code that generates them. The
files describe, in various forms, all possible stackings among the characters in
the Unicode ranges Box Drawing
and Block Elements, mappings
between the drawing character pairs and the best corner that connects them,
mapping of relations between them, and more. The goal is to make it easier to
work with these drawing characters. The files:
- Stacking
- all-stacks.csv
146K
file:🗀 all-stacks.csv
- all-stacks-unquoted.csv
97K
file:🗀 all-stacks-unquoted.csv
- stack-table.csv
155K
file:🗀 stack-table.csv
- stack-table-dense.csv
88K
file:🗀 stack-table-dense.csv
- all-stacks.csv
- Borders
The rest of this document describes the files and some ideas on how to use them.
Reading is not at all required for using the simple and self-explanatory files
listed above, but it may help.
Usage
Stacking
If you need to find the stacking of two characters, search for the row that includes them both. The all-stacks-unquoted.csv
is probably best for this. For example in a bash
function:
And then use it to stack characters so:
all-stacks.csv
A row describes a possible stacking: a triplet of two input characters and a result, in three columns:
- left – first character being stacked
- right – second character being stacked
- result – stack result character
Some of the stackings for horizontal and vertical lines, for example, will be found at rows 22
, 23
and 150
, as shown in the example table to the right. The file describes 8,177
such triplets.
all-stacks-unquoted.csv
Is exactly like all-stacks, but skips the character quoting.
stack-table.csv
This is the cartesian product of all characters with themselves, showing at each
cell the stacking of the characters in the cell’s row & column headers, much
like a multiplication table. Like a multiplication table, it is also symmetric
on the diagonal.
If we were stacking only three characters, the table would look like the example
to the right. The real table stacks 173
characters vs.
themselves, and is composed of 29,929
cells, of which 16,620
are non-empty
(56%
).
The table is made up of four parts:
-
Top-left corner cell is empty
-
First row features the column headers. All characters below a column header
are the result of stacking it with some other character, except on the
diagonal where you see it stacking with itself -
First column shows the row headers. All characters right of a row header
are the result of the stacking it with some other character, except of course
on the diagonal -
Table body is filled with the stackings of the characters in the row &
column headers. Stackings which are impossible because the stacking of the
headers creates a shape which looks like no Unicode character, are given as a
single space character. For example the stacking of“ ▀ ”
and“ │ ”
will
appear as a quoted space character (“ ”
), because no Unicode character
matches their stacking.
stack-table-dense.csv
A table showing the stackings between characters exactly like
stack-table.csv, except you will find here only 121
of the
173
characters included in stack-table.csv
. Any character that does not stack
with every other character has been removed. What remains is a dense table with
no holes: any character here can be stacked with every other character in
the file, and so can their stacking result.
stack-table-dense.ods
This is a version of stack-table-dense.csv formatted as
a LibreOffice Calc spreadsheet.
named-border-sets.csv
This file lists 28 named border sets. A border set is composed of 8 characters, one for each border direction:
↖
top left↑
top center↗
top right←
middle left×
middle center→
middle right↙
bottom left↓
bottom center↘
bottom right
The CSV file encodes this as a row for each border set, with the name of the set followed by the 8 characters in the order of the list above. For example on named-border-sets.csv you will find the definition of the simple line border. Here is the row next to a rendering of the border set it describes:
"line" ,"┌", "─", "┐", "│", "│", "└", "─", "┘", ┌────┐
│line│
└────┘
The Named
Border Sets diagram shows every border set. Click a border to copy the
border characters to your clipboard or an individual glyph to copy just one
character.
named-border-sets.json
Is exactly like named-border-sets.csv, but in JSON. It
is an array of named border set entries. A named border entry in Typescript is a
Record
of strings with a name
key for the border set name, and keys for each
border direction:
- topLeft
- topCenter
- topRight
- middleLeft
- middleRight
- bottomLeft
- bottomCenter
- bottomRight
The value is the border character at the given direction.
Here for example, is the entry for the hMcGugan border set:
{ "name": "hMcGugan", "topLeft": "▁", "topCenter": "▁", "topRight": "▁", "middleLeft": "▏", "middleRight": "▕", "bottomLeft": "▔", "bottomCenter": "▔", "bottomRight": "▔" },
In named-border-sets.txt file this border should look like the image below:
named-border-sets.txt
Here you will find the exact same information as in the
named-border-sets.csv file, but shows the borders in a
7×4 grid, each bordering its own name. The image on the right
shows how it would appear in a text editor.
This can be used as a visual index to the corresponding CSV file, or as a source
from which borders are copied and then resized.
There are 56
border characters in the union of all named border set. Here are
all the border characters from all sets:
─ ╌ ┄ ┈ │ ┃ ┌ ┐ ┍ ┑ ┎ ┒ ┏ ┓ ╒ ╕ ╓ ╖ ╔ ╗
═ ║ ╱ ╲ ╎ ╏ └ ┘ ┕ ┙ ┖ ┚ ┗ ┛ ╘ ╛ ╙ ╜ ╚ ╝
━ ╍ ┅ ┉ ┆ ┇ ▀ ▐ ▕ ▁ ▛ ▜ ▝ ▘ ▚ ╭ ╮ █
┊ ┋ ▄ ▌ ▏ ▔ ▙ ▟ ▗ ▖ ▞ ╰ ╯

The All Border
Glyphs diagram shows every character from every named border. Click to copy
one into your clipboard.
Plan
- stack
- border sets
- relations
- elbows
- classification
- border set relations
- CLI and web helpers
See Also
- Unicode Box Drawing range
- Unicode Block Elements range
- The “joining-borders” feature of the Haskell brick library
- reunions – the Typescript library that computes these things
Project Development
Why?
Terminals display a grid of cells. Each can hold a single character. When we
write a character to a cell the existing character is immediately destroyed and
the new character is displayed.
But the non-destructive stacking of visuals on top of one another is
fundamental to all visual work, from Neanderthal hand stencils to CSS3 filters.
Terminal pseudographics are an
extreme visual form thanks to the ultra low resolution, yet such non-destructive
composition is highly non-trivial.
Eventually someone (me) got tired of hacking around this tiny annoyance and
decided to build this temporary fix. It is temporary because, as everybody
knows, we will soon be replacing our clunky Disco-era terminals with the science
fiction UIs of the future.
As long we as are still using terminals, we could improve the APIs a bit. For
example, make them more composable by making it easy to place a glyph in any
terminal cell without destroying existing content.
If we are to be stacking anything, then the minimum needed is a pair of
characters. But which pair? Converting your intent into a pair of characters is
another annoying chore. You will find here files that support various glyph
finding use cases:
- Navigating glyphs by property – for example find the 90ᵒ degree rotation
of the thin horizontal center line:“─” ↻ “│”
- Finding all possible elbows that connect four glyphs – for example find
the possible elbows for the lines{↑: “═”, →: