Something went wrong. Try again.
A reference for terminal control sequences whose examples run live in libghostty-vt compiled to WebAssembly.
Something went wrong. Try again.
6.3 kB · 124 lines
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125---.title = "Notation",.description = "How syntax diagrams and validation cases are written on this site.",.date = .date("2026-10-01T00:00:00"),.layout = "page.shtml",---# Syntax diagrams
Each sequence page opens with the sequence laid out byte by byte. The name ofeach piece is on top and the byte it stands for is underneath, in hexadecimal.
- `ESC` is the byte `1B`.- `CSI` is the Control Sequence Introducer, `ESC [`. ECMA-48 also defines a single-byte CSI, `9B`, but terminals that decode their input as UTF-8 do not accept it, so it is not shown.- `OSC` is the Operating System Command introducer, `ESC ]`.- `ST` is the String Terminator, `ESC \`. Most terminals also accept `BEL` (`07`) in its place.- A dashed box is a parameter. `Pn` is a number, `Ps` is a number that selects one of a fixed set of behaviors, and `Pt` is text. A parameter left out takes its default, and several parameters are separated by `;`.
# Validation cases
A case is two blocks: the input, and the screen it should produce. A freshterminal is made for every case, exactly as wide and as tall as the expectedscreen, and the input is written to it.
## Input
One line of input is one *step*: the stepping controls under each caseadvance a line at a time. Leading and trailing spaces on a line are ignored,and anything after a `#` that follows a space is a comment, which is shownbeside the step.
| Escape | Byte || --- | --- || `\e` | `1B`, ESC || `\a` `\b` `\t` `\n` `\v` `\f` `\r` | `07` `08` `09` `0A` `0B` `0C` `0D` || `\s` | `20`, a space || `\xNN` | the byte `NN` in hexadecimal || `\NNN` | the byte `NNN` in octal, so `\033` is ESC || `\u{NNNN}` | the code point `U+NNNN`, encoded as UTF-8 || `\\` `\#` | a backslash, a `#` |
Everything else is written as UTF-8. Note that `\n` is only a line feed: itmoves the cursor down without returning it to the left margin, because that iswhat the byte does.
## Expected screen
Each row of the screen is written between bars, `|like this|`, with `_` foran empty cell. The number of rows and the width of the first row set the sizeof the terminal. After the rows can come any of these:
| Line | Checks || --- | --- || `cursor R,C` | the cursor is at row `R`, column `C`, counting from 1 || `pending-wrap yes` | the cursor is in the last column with a wrap pending (or `no`) || `cursor-visible no` | the cursor is hidden (or `yes`, shown) || `title "text"` | the window title, as a JSON string || `progress text` | the progress reports sent with [OSC 9 ; 4](/osc/progress/), in order and separated by commas, such as `set 50, remove`; `progress none` for none || `pointer name` | the mouse pointer's shape, set with [OSC 22](/osc/pointer/), by its CSS name, such as `text` or `wait` || `pwd "text"` | the working directory last reported with [OSC 7](/osc/cwd/), as a JSON string; `""` for none || `attr R,C words…` | the style of the cell at row `R`, column `C` || `reply text` | everything the terminal sent back to the host, in the input's escape notation, or `reply none` for nothing || `bell N` | how many times the bell rang |
The words an `attr` line takes are `bold`, `italic`, `faint`, `blink`,`inverse`, `invisible`, `strikethrough`, `overline` and `underline` (or`underline=double`, `curly`, `dotted`, `dashed`), each of which can be negatedwith a leading `-`; `fg=N` and `bg=N` for a palette color, `fg=#rrggbb` for adirect color and `fg=default`; `link` for a cell that is part of an[OSC 8](/osc/hyperlink/) hyperlink; `semantic=prompt`, `semantic=input` or`semantic=output` for what [OSC 133](/osc/prompt/) marked the cell as; and`plain` for a cell with no styling at all.
## Replies
Some sequences make the terminal answer the host: a status report, itscursor position, what kind of terminal it is. The runner collects thoseanswers, in order, from libghostty-vt's callbacks, and a `reply` line checksall of them together. On a page, a case that checks a reply or the bellshows what was sent back as you step through it.
Some answers are the host's to choose rather than libghostty-vt's. Forthose the runner gives a default xterm's answers, as it does for the colorsbelow: Device Attributes reports a VT420,`\e[?64;1;2;6;9;15;17;18;21;22;28c` for the primary attributes and`\e[>41;412;0c` for the secondary, xterm's patch number among them, and theanswerback message ENQ asks for is empty, as xterm's `answerbackString` isby default. A size report,[`CSI 18 t`](/csi/xtwinops/), gives the case's own size, as a default xtermwould; the size of a cell in pixels is an arbitrary 6 by 13.
Colors are the host's choice too, and for those the runner follows a defaultxterm, since the cases do: the terminal starts with xterm's palette and itsblack text on white, with the cursor in the foreground color. That is what acolor query such as [`OSC 4`](/osc/palette/) or [`OSC 11`](/osc/background/)answers, and what `fg=N` resolves to. The screens on this site are stilldrawn in the page's own colors wherever a cell has the default ones.
## Known differences
A case that libghostty-vt is known not to pass is marked as a *knowndifference*. A case's expectation follows what a default xterm does, bugsincluded, even where DEC STD 070 or ECMA-48 says otherwise. That includesignoring a function a default xterm ignores, so a function libghostty-vtimplements and xterm does not is a known difference too; the[sources](/sources/) page says more. A knowndifference is still run on every page load, and its badge says whether thedifference is still there; the page's prose explains it.
## Host settings
Some functions depend on a setting made by the host, the program theterminal runs in: one that allows a function a terminal leaves off, or onethat holds a function back. A case that needs one says so with anotherattribute, and runs in a terminal with that setting made:
| Attribute | Setting || --- | --- || `checksum-report` | [DECRQCRA](/csi/decrqcra/) answers: xterm's `GetChecksum` window operation allowed, libghostty-vt's `GHOSTTY_TERMINAL_OPT_XT_CHECKSUM_REPORT` set || `no-column-resize` | [DECCOLM](/modes/deccolm/) keeps the width: xterm's `ColumnMode` window operation disallowed; libghostty-vt has no such setting |