# Single Shift Two and Three (SS2, SS3)

> Print the next character from the G2 or G3 set.

- **Sequence:** `ESC N`
- **ECMA-48:** [§8.3.141 SS2 – Single-Shift Two, p. 70](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n83/mode/1up)
- **DEC STD 070:** [§3.8.3.2 Single Shift Two, p. 3-80](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n184/mode/1up)
- **VT220:** [§4.4.4 Invoking Character Sets with Single Shifts](https://vt100.net/docs/vt220-rm/chapter4.html#S4.4.4)
- **VT510:** [4.2 Control Characters](https://vt100.net/docs/vt510-rm/chapter4.html#S4.2)

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](https://control-codes.page/c0/so/index.html.md) for designating and invoking sets.

SS3 is
[ECMA-48 §8.3.142, p. 70](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n83/mode/1up)
and [DEC STD 070 §3.8.3.2, p. 3-81](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n185/mode/1up).

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. xterm likewise clears its single shift only when
it writes text (`WriteNow` in
[`charproc.c`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L1703-L1715)).

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.

## Validation

### SS2-1: One character from G2

Input, one step per line:

```text
\e*0      # G2 is DEC Special Graphics
\eN       # SS2
qq
```

Expected screen:

```text
|─q________|
```

### SS2-2: One character from G3

Input, one step per line:

```text
\e+0      # G3 is DEC Special Graphics
\eO       # SS3
qq
```

Expected screen:

```text
|─q________|
```

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

Input, one step per line:

```text
\e*0      # G2 is DEC Special Graphics
\e)B      # G1 is ASCII
\eN       # SS2
\x0e      # SO, which may come between
q
```

Expected screen:

```text
|─_________|
```

---

This is the Markdown version of <https://control-codes.page/esc/ss2/>. On that page every validation case runs live in libghostty-vt, the terminal emulation core of Ghostty, compiled to WebAssembly.

The validation cases are written in the notation described in <https://control-codes.page/notation/index.html.md>.
