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
- yes
- GNU screen
- yes
| 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 | yes | yes |