HPA / HPR / VPR — Position absolute & relative (CSI ` / CSI a / CSI e)
ECMA-48's row/col-preserving cursor moves — HPA (absolute column), HPR (relative column), VPR (relative row) — completing the trio anchored by VPA.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[<col>` (HPA) \x1b[<n>a (HPR) \x1b[<n>e (VPR)\033[10` / \033[5a / \033[3e\e[10` / \e[5a / \e[3eESC [ col ` / ESC [ n a / ESC [ n e1b 5b ... 60 / 1b 5b ... 61 / 1b 5b ... 65Description
Three ECMA-48 cursor-positioning primitives that preserve the orthogonal axis — same shape as VPA (`\x1b[<row>d`) and CHA (`\x1b[<col>G`, slug `cursor-column`) but covering the gaps. **HPA** (`\x1b[<col>`` ` `) Horizontal Position Absolute — move to absolute column `<col>` (1-based), keep current row. Semantically identical to CHA (`G`); final byte differs only because ECMA-48 § 8.3.57 (HPA) predates / parallels § 8.3.9 (CHA). **HPR** (`\x1b[<n>a`) Horizontal Position Relative — move `n` columns right, keep row. Same effect as CUF (`\x1b[<n>C`) but the final byte `a` distinguishes the ECMA-48-canonical form. **VPR** (`\x1b[<n>e`) Vertical Position Relative — move `n` rows down, keep column. Same as CUD (`\x1b[<n>B`) by final byte `e`. All three default to `n=1` / `col=1` when omitted; out-of-range values clamp to the visible region (or DECSTBM/DECSLRM region when those are active). In practice most modern code emits CHA/CUF/CUD/CUB instead — but every ECMA-48-conformant terminal accepts the HPA/HPR/VPR aliases, and curses' default capability table contains them, so any parser must recognize the alternative final bytes. The HPA backtick ` ` ` final byte is also the easiest of any CSI final to mistype — note it's 0x60, **not** apostrophe 0x27 (which would be DECIC / DECDC's intermediate byte).
Spec citation: ECMA-48 §8.3.57 (HPA) / §8.3.59 (HPR) / §8.3.160 (VPR)
Parameters
| col / n | HPA: absolute column (1-based). HPR: columns to move right. VPR: rows to move down. Default 1 if omitted. |
Examples
printf '\033[40`status: ok' # HPA: jump to col 40, keep row (note backtick, not single quote)import sys; sys.stdout.write('\x1b[5a') # HPR: move 5 cols rightfmt.Print("\x1b[3e") // VPR: move 3 rows downprocess.stdout.write('\x1b[1`') // HPA: column 1 (== CR but doesn't move row)printf("\x1b[10a"); /* HPR: 10 cols right — same effect as \x1b[10C */Terminal support
- xterm
- yes
- Linux console (fbcon)
- yes
- macOS Terminal.app
- yes
- iTerm2
- yes
- Windows Terminal
- yes
- cmd.exe / ConPTY
- partial
- kitty
- yes
- alacritty
- yes
- WezTerm
- yes
- Ghostty
- yes
- GNOME Terminal
- yes
- Konsole
- yes
- tmux
- no
- GNU screen
- no
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | yes | yes | yes | yes | partial | yes | yes | yes | yes | yes | yes | no | no |