^[control-codes
live in libghostty-vt

Escape sequences

SS2, SS3 Single Shift Two and Three

View as Markdown

Print the next character from the G2 or G3 set.

SS2 Single Shift Two

ESC N
ECMA-48
§8.3.141 SS2 – Single-Shift Two, p. 70
DEC STD 070
§3.8.3.2 Single Shift Two, p. 3-80
VT220
§4.4.4 Invoking Character Sets with Single Shifts
VT510
4.2 Control Characters

SS2 prints the next character from the G2 set, and SS3 (ESC O) from the G3 set, without changing the set the characters after it come from. The VT510 manual puts it as temporarily mapping the set into GL “for the next graphic character”. G2 and G3 are filled with ESC * F and ESC + F; see SO and SI for designating and invoking sets.

SS3 is ECMA-48 §8.3.142, p. 70 and DEC STD 070 §3.8.3.2, p. 3-81.

DEC STD 070 says what may come between the single shift and its character. If the next character is not a graphic character, the single shift “is ignored and the received character is processed as if the single shift had not been received”. The exception is one SO or SI, which is carried out but “does not cancel the Single Shift”. libghostty-vt instead keeps a single shift until the next character it prints: print in Terminal.zig clears it, and no control character does. A combining character counts, and uses the single shift up. xterm likewise clears its single shift only when it writes text (WriteNow in charproc.c).

SS2 and SS3 are C1 controls. ECMA-48 defines them both as the single bytes 8E and 8F and as ESC N and ESC O. libghostty-vt decodes its input as UTF-8, so it accepts only the ESC forms.

Support

TerminalVersionSupportNotes
VT220manual, 2nd ed., 1984Yes§4.4.4 Invoking Character Sets with Single Shifts
VT510manual, 1st ed., 1993YesTable 4–2
xtermpatch 412, xterm-411aYesthe single shift lasts until text is written
libghostty-vt0f171f6Yesthe single shift lasts until the next printed character
kitty0.49.1, run in a VMNofails the 3 cases that show it working
foot1.28.0, run in a VMPartlyfails SS2-3 of the 3 cases that show it working
pyte0.8.2, run as a libraryNofails the 3 cases that show it working
xterm.js headless6.0.0, run as a libraryNofails the 3 cases that show it working
alacritty_terminal0.26.0, run as a libraryNofails the 3 cases that show it working
ConEmubuild 230724, its documentationNonot in ConEmu’s ANSI escape codes
rxvt-unicode9.31, run in a VMNofails the 3 cases that show it working
VTE0.84.1, run as a libraryNofails the 3 cases that show it working

Validation

SS2-1: One character from G2

\e*0      # G2 is DEC Special Graphics
\eN       # SS2
qq
|─q________|

SS2-2: One character from G3

\e+0      # G3 is DEC Special Graphics
\eO       # SS3
qq
|─q________|

SS2-3: An SO in between does not cancel it

\e*0      # G2 is DEC Special Graphics
\e)B      # G1 is ASCII
\eN       # SS2
\x0e      # SO, which may come between
q
|─_________|
Every example on these pages runs in your browser, in libghostty-vt compiled to WebAssembly.