# Cursor Preceding Line (CPL)

> Move the cursor up n lines, to the start of the line.

- **Sequence:** `CSI Pn F`
- **Defaults:** Pn = 1
- **ECMA-48:** [§8.3.13 CPL – Cursor Preceding Line, p. 35](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n48/mode/1up)
- **VT510:** [CPL—Cursor Previous Line](https://vt100.net/docs/vt510-rm/CPL.html)

Move the cursor `Pn` lines up and to the first character position of that
line. A `0` is taken as `1`. The VT510 manual calls it *Cursor Previous
Line*.

It is a [CUU](https://control-codes.page/csi/cuu/index.html.md) followed by a [carriage return](https://control-codes.page/c0/cr/index.html.md), and
behaves as those two do. The cursor stops at the top margin, or the first
line if it started above the margin, and never scrolls. With left and right
margins set, it goes to the left margin rather than the first column.

DEC STD 070 does not define CPL. The VT510 manual does, as does xterm.

## Validation

### CPL-1: The previous line

Input, one step per line:

```text
\e[3;3H
\e[F
X
```

Expected screen:

```text
|_____|
|X____|
|_____|
```

### CPL-2: n lines up

Input, one step per line:

```text
\e[3;3H
\e[2F
X
```

Expected screen:

```text
|X____|
|_____|
|_____|
```

### CPL-3: Stops at the top margin, without scrolling

Input, one step per line:

```text
\e[4;1H
A
\e[2;4r   # region is lines 2 to 4
\e[3;3H
\e[9F
X
```

Expected screen:

```text
|_____|
|X____|
|_____|
|A____|
```

### CPL-4: To the left margin

Input, one step per line:

```text
\e[?69h   # allow left and right margins
\e[2;4s   # margins at columns 2 and 4
\e[2;3H
\e[F
X
```

Expected screen:

```text
|_X___|
|_____|
```

---

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