Horizontal Position Relative (HPR)
Move the cursor forward `n` columns without changing the row.
- 0x1B
- ESC
- 0x5B
- [
- ____
- x
- 0x61
- a
The parameter x must be an integer greater than or equal to 1. If x is
less than or equal to 0, adjust x to be 1. If x is omitted, x
defaults to 1.
This sequence always unsets the pending wrap state.
HPR moves the cursor x columns to the right of its current position. HPR
is paired with HPA the same way
CUF is paired with CHA: HPA selects an absolute
column, HPR selects a column relative to where the cursor is now.
HPR is handled as an absolute move to the current row and the current
column plus x. With origin mode off, the result is clamped to
the last column of the screen, so HPR runs past a
right margin instead of stopping at it. With origin mode on, the
clamp is the right margin. The cursor stops at whichever boundary applies
regardless of the remaining value of x; this sequence never wraps to the
next line and never modifies cell content.
Because the move is absolute, the row goes through the same resolution as the column. It is unchanged with origin mode off, but with origin mode on the current row is offset by the top margin and clamped to the bottom margin, so HPR can move the cursor down a row as well as across.
Note
HPR and CUF (Cursor Forward,
CSI Pn C) agree as long as no right margin is set, and both unset pending wrap, but they are not the same handler. CUF always stops at the right margin; HPR only respects the right margin when origin mode is set, and otherwise carries the cursor to the edge of the screen.
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "A"
printf "\033[3a" # HPR forward 3 columns
printf "X"
|A___Xc____|
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "A"
printf "\033[a" # HPR with default (1)
printf "X"
|A_Xc______|
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "A"
printf "\033[500a" # HPR way past the edge
printf "X"
|A________Xc
cols=$(tput cols)
printf "\033[${cols}G" # move to last column
printf "A" # set pending wrap state
printf "\033[1a" # HPR cancels pending wrap
printf "X"
|_________X|
Printing A in the last column leaves the cursor there with pending wrap
set, so HPR asks for one column past the screen edge and is clamped back to
the column the cursor is already on. The X overwrites the A.