Cursor Preceding Line (CPL)

Move the cursor up `n` rows and to the beginning of the line.

  1. 0x1B
    ESC
  2. 0x5B
    [
  3. ____
    n
  4. 0x46
    F

The parameter n must be an integer greater than or equal to 1. If n is less than or equal to 0, adjust n to be 1. If n is omitted, n defaults to 1.

This sequence always unsets the pending wrap state.

CPL is exactly equivalent to Cursor Up (CUU) followed by Carriage Return (CR): first move the cursor up n rows respecting the top margin, then carriage return on that row. CR lands on the left margin, not unconditionally on column 1: with origin mode set, or with the cursor at or to the right of a left margin, the cursor ends up on the left margin. With no left margin in play the left margin is column 1.

If the current cursor position is at or below the top margin, the highest point the cursor can move to is the top margin. If the current cursor position is above the top margin, the highest point the cursor can move to is the first row of the screen. This sequence never triggers scrolling.

Note

CPL is the upward counterpart of CNL. It is sometimes referred to as Cursor Previous Line in other terminal references; the ECMA-48 name is Cursor Preceding Line. Both names refer to the same sequence (CSI Pn F).

Validation

CPL V-1: Normal Usage

printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\033[3;5H" # row 3, column 5
printf "A"
printf "\033[2F" # CPL up 2 lines, to column 1
printf "X"
|Xc________|
|__________|
|____A_____|

CPL V-2: Default Parameter

printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\033[3;5H" # row 3, column 5
printf "A"
printf "\033[F" # CPL with default (1)
printf "X"
|__________|
|Xc________|
|____A_____|

CPL V-3: Stops at Top Margin

printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\033[2;3r" # scroll region rows 2..3
printf "\033[3;5H"
printf "A"
printf "\033[500F" # CPL way past the top margin
printf "X"
|__________|
|Xc________|
|____A_____|

The cursor stops on row 2, the top margin, even though row 1 is still part of the screen.

CPL V-4: Pending Wrap is Unset

cols=$(tput cols)
printf "\033[2;1H" # row 2, column 1
printf "\033[${cols}G" # move to last column
printf "A" # set pending wrap state
printf "\033[1F" # CPL cancels pending wrap
printf "X"
|Xc________|
|_________A|