# String Terminator (ST)

> End a control string, such as an operating system command or a device control string.

- **Sequence:** `ST`
- **ECMA-48:** [§8.3.143 ST – String Terminator, p. 70](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n83/mode/1up)
- **DEC STD 070:** [§3.5.1.2.5 Universal Terminator, p. 3-19](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n123/mode/1up)
- **VT510:** [4.2 Control Characters](https://vt100.net/docs/vt510-rm/chapter4.html#S4.2)

ST closes a *control string*: one opened by [OSC](https://control-codes.page/osc/title/index.html.md),
[DCS](https://control-codes.page/esc/dcs/index.html.md), or [SOS, PM or APC](https://control-codes.page/esc/sos/index.html.md). Everything between the
opener and ST is the string's content, which the terminal reads as a whole
rather than printing.

xterm also accepts [BEL](https://control-codes.page/c0/bel/index.html.md) in place of ST, but only to end an OSC.
In any other string it rings the bell and the string goes on
([`CASE_BELL`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L3691-L3705)).
libghostty-vt also ends only an OSC with BEL.

DEC STD 070 makes ST a *universal terminator*: sent on its own, it gets the
terminal back to a known state whatever it was in the middle of
([§3.5.1.2.5, p. 3-19](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n123/mode/1up)).
Its `ESC` cancels any escape or control sequence in progress, it ends any
control string normally, and with nothing in progress it is ignored. So a
program that is not sure what it last left unfinished can send `ESC \` and
carry on.

ST is a C1 control. ECMA-48 also defines it as the single byte `9C`, which
a terminal reading UTF-8 does not take as ST: a string opened with `ESC ]`
goes on past it, in a default xterm and in libghostty-vt alike. The
[UTF-8](https://control-codes.page/parser/utf8/index.html.md) page has the details.

## Validation

### ST-1: Ends an operating system command

Input, one step per line:

```text
\e]2;hello\e\\
X
```

Expected screen:

```text
|X_____|
title "hello"
```

### ST-2: On its own, it is ignored

Input, one step per line:

```text
A
\e\\
B
```

Expected screen:

```text
|AB____|
cursor 1,3
```

### ST-3: It cancels a control sequence in progress

Input, one step per line:

```text
A
\e[2;     # an unfinished CUP
\e\\
B
```

Expected screen:

```text
|AB____|
|______|
cursor 1,3
```

### ST-4: The 8-bit form does not end a string

Input, one step per line:

```text
\e]2;hello
\x9c      # not valid UTF-8 on its own
X         # still part of the command
```

Expected screen:

```text
|______|
title ""
```

---

This is the Markdown version of <https://control-codes.page/esc/st/>. 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>.
