^[control-codes live in libghostty-vt

Control sequences

HPR Character Position Forward

Move the cursor right n columns.

CSI Pn a
Defaults
Pn = 1
ECMA-48
§8.3.59 HPR – Character Position Forward, p. 45
VT510
HPR—Horizontal Position Relative

Move the cursor Pn columns to the right, on the line it is on. A 0 is taken as 1. The VT510 manual says that an attempt to move past the last position on the line stops at the last position.

It is a relative move, so origin mode makes no difference to it: the cursor moves Pn columns from wherever it is.

ECMA-48 names it for the data component, which a terminal does not have apart from its screen (§6, p. 14). Its counterpart going left is HPB, and the absolute form is HPA. The VT510 manual’s one-line summary of HPR is a copying error, as it is for HPA; the description beneath it is the right one.

Validation

HPR-1: One column by default

AB
\e[a
X
|AB_X_|

HPR-2: n columns

\e[2;1H
\e[3a
X
|_____|
|___X_|

HPR-3: Stops at the last column

\e[2;2H
\e[99a
X
|_____|
|____X|

HPR-4: The same in origin mode

\e[2;4r   # region is lines 2 to 4
\e[?69h   # allow left and right margins
\e[2;7s   # margins at columns 2 and 7
\e[?6h    # origin mode
\e[2;2H   # line 3, column 3 of the screen
X
\e[2a
Y
\e[?6l
|________|
|________|
|__X__Y__|
|________|

The Y should be two columns past the cell after X, on the same line, which is what esctest2’s test_HPR_IgnoresOriginMode checks. libghostty-vt moves it down as well. HPR there is setCursorPos(current line + 1, current column + 1 + Pn), and in origin mode setCursorPos adds the margins to both, so the line the cursor is on is offset by the top margin and the column by the left margin.

Every example on these pages runs in your browser, in libghostty-vt compiled to WebAssembly.