カーソル後退 (CUB)

カーソルを `n` セル左へ移動します。

  1. 0x1B
    ESC
  2. 0x5B
    [
  3. ____
    n
  4. 0x44
    D

パラメーター n は 1 以上の整数でなければなりません。n が 0 以下の 場合は n を 1 に調整します。n が省略された場合は n が既定で 1 になります。

このシーケンスは常に 保留中の折り返し状態 を解除します。

カーソルが移動できる最も左の境界は、現在のカーソル列と 左マージン によって決まります。カーソルが最初から左マージンより左にある場合、シーケンス実行中は左マージンを最左列へ変更します。カーソルが位置できる 最も左の列は左マージンです。

以上を踏まえると、ターミナルのモード状態に応じて 3 種類のカーソル後退挙動があります。 可能な挙動を以下に挙げます。競合する場合は、 最も上の挙動が優先されます。

折り返しなしの挙動では、前述の最左境界を尊重しながらカーソルを左へ n セル移動します。 最左境界に達した時点で、n の残り値がどれだけあってもカーソルの左移動を止めます。 カーソルの行は変化しません。

拡張逆方向折り返しの挙動では、前述の最左境界を尊重しながらカーソルを左へ n セル移動します。最左境界に達した際、n > 0 であればカーソルを上の行の 右マージン へ移動します。 カーソルがすでに 上マージン にある場合は、下マージン の 右マージンへ移動します。このモードではカーソルの列と行のどちらも変わり得ます。 非拡張の逆方向折り返しと比較した場合の 2 つの重要な違いは、拡張逆方向折り返しでは 前の行が折り返された行である必要がなく、拡張逆方向折り返しは下マージンへ折り返す点です。

逆方向折り返し(非拡張)の挙動では、前述の最左境界を尊重しながらカーソルを左へ n セル移動します。最左境界に達した際、n > 0 かつ 前の行が折り返された行であれば、カーソルを上の行の 右マージン へ移動します。前の行が 折り返されていなければ、n に残り値があってもカーソル左移動操作は完了です。カーソルが すでに 上マージン にある場合は、カーソルを上へ移動しません。 この折り返しモードでは、カーソル行を下マージンへ折り返しません。

拡張逆方向折り返しまたは逆方向折り返しモードでは、保留中の折り返し状態がセットされている場合、n を 1 減らします。これらのモードでは、 初期のカーソル後退カウントは保留中の折り返し状態に消費されます。空の改行で「バックスペース」を押してカーソルが前の行へ戻るのと同じです。

検証

CUB V-1: 保留中の折り返し状態が解除される

cols=$(tput cols)
printf "\033[${cols}G" # move to last column
printf "A" # set pending wrap state
printf "\033[D" # move back one
printf "XYZ"
|________XY|
|Zc________|

CUB V-2: 逆方向折り返しが無効な場合の最も左の境界

printf "\033[?45l" # disable reverse wrap
echo "A"
printf "\033[10D" # back
printf "B"
|A_________|
|Bc________|

CUB V-3: 逆方向折り返し

cols=$(tput cols)
printf "\033[?7h" # enable wraparound
printf "\033[?45h" # enable reverse wrap
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\033[${cols}G" # move to end of line
printf "AB" # write and wrap
printf "\033[D" # move back two
printf "X"
|_________Xc
|B_________|

CUB V-4: 拡張逆方向折り返し(単一行)

printf "\033[?7h" # enable wraparound
printf "\033[?1045h" # enable extended reverse wrap
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
echo "A"
printf "B"
printf "\033[2D" # move back two
printf "X"
|A________Xc
|B_________|

CUB V-5: 拡張逆方向折り返しで下へ折り返す

cols=$(tput cols)
printf "\033[?7h" # enable wraparound
printf "\033[?1045h" # enable extended reverse wrap
printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\033[1;3r" # set scrolling region
echo "A"
printf "B"
printf "\033[D" # move back one
printf "\033[${cols}D" # move back entire width
printf "\033[D" # move back one
printf "X"
|A_________|
|B_________|
|_________Xc

CUB V-6: マージン外での逆方向折り返し

printf "\033[1;1H"
printf "\033[0J"
printf "\033[?45h"
printf "\033[3r"
printf "\b"
printf "X"
|__________|
|__________|
|Xc________|

CUB V-7: 保留中の折り返し状態がある場合の逆方向折り返し

cols=$(tput cols)
printf "\033[?45h"
printf "\033[${cols}G"
printf "\033[4D"
printf "ABCDE"
printf "\033[D"
printf "X"
|_____ABCDX|