# Tabulation Clear (TBC)

> Clear the tab stop at the cursor, or every tab stop.

- **Sequence:** `CSI Ps g`
- **Defaults:** Ps = 0
- **ECMA-48:** [§8.3.154 TBC – Tabulation Clear, p. 73](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n86/mode/1up)
- **DEC STD 070:** [§5.4.5 Tabulation Clear, p. 5-66](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n320/mode/1up)
- **VT510:** [TBC—Tab Clear](https://vt100.net/docs/vt510-rm/TBC.html)

Clear horizontal tab stops, chosen by `Ps`:

| `Ps` | Clears |
| --- | --- |
| `0`, or left out | the tab stop at the cursor's column, if there is one |
| `3` | every tab stop |

The cursor does not move, and nothing on the screen changes; only where the
next [HT](https://control-codes.page/c0/ht/index.html.md) or [CHT](https://control-codes.page/csi/cht/index.html.md) stops. Clearing a column that has no
tab stop does nothing.

ECMA-48 defines four more values, for line tabulation stops and for clearing
only the stops in the active line, but DEC STD 070 and the VT510 manual both
define only `0` and `3`, and the VT510 manual says there are "only two
values". Other values are ignored.

Tab stops are set again one at a time with [HTS](https://control-codes.page/esc/hts/index.html.md), or all reset to
every eight columns with `CSI ? 5 W`.

## Validation

### TBC-1: Clear the stop at the cursor

Input, one step per line:

```text
\e[?5W    # reset tab stops
\e[1;9H   # the tab stop at column 9
\e[0g
\e[1;1H
\tX       # skips column 9
```

Expected screen:

```text
|________________X___|
```

### TBC-2: The parameter left out

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

```text
\e[?5W    # reset tab stops
\e[1;9H   # the tab stop at column 9
\e[g
\e[1;1H
\tX       # skips column 9
```

Expected screen:

```text
|________________X___|
```

libghostty-vt ignores `CSI g` without a parameter, so the tab stop at column 9
stays and the `X` lands there. Its dispatcher in `src/terminal/stream.zig`
accepts the sequence only with exactly one parameter, and a left-out
parameter is no parameter at all. ECMA-48 gives `0` as the default, DEC STD
070 says "an omitted parameter or a parameter value of zero" clears the stop
at the cursor, the VT510 manual lists "0 or none (default)", and esctest2's
`test_TBC_Default` checks for it.

### TBC-3: Clear every stop

Input, one step per line:

```text
\e[?5W    # reset tab stops
\e[3g
\tX       # nothing to stop at but the right margin
```

Expected screen:

```text
|___________________X|
```

### TBC-4: Where there is no stop

Input, one step per line:

```text
\e[?5W    # reset tab stops
\e[1;10H  # column 10 has no tab stop
\e[0g
\e[1;1H
\t\tX     # columns 9 and 17 are still stops
```

Expected screen:

```text
|________________X___|
```

### TBC-5: Other values are ignored

Input, one step per line:

```text
\e[?5W    # reset tab stops
\e[1;9H
\e[2g     # ECMA-48's "stops in the active line"
\e[1;1H
\tX
```

Expected screen:

```text
|________X___________|
```

---

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