はじめに
シェルスクリプトでエスケープシーケンスを使ってターミナルの情報(ウインドウサイズとかカーソル位置とか)を取得する方法の(個人的?)メモです。
report() {
( # trap EXITを使うためのサブシェル
set -- "$1" "$(stty -g)" # 現在の端末設定のバックアップ
trap 'stty "$2"' EXIT # サブシェル脱出時に端末設定を戻す
# rawだとCTRL-Cできないしtimeやminも機能しないようなので-icanon
stty -echo -icanon time 1 min 0 # エコーバックなしとその他の設定
printf "$1" >/dev/tty # 問い合わせのエスケープシーケンスを端末に出力
dd count=1 2>/dev/null # 端末からの応答を読み取って標準出力に出力
) </dev/tty # 標準入力を端末に明示的に指定
}
# ウインドウサイズの取得
report '\033[18t' | od -An -a
# esc [ 8 ; 4 4 ; 1 4 6 t
# カーソル位置の取得
report '\033[6n' | od -An -a
# esc [ 1 5 ; 1 R
他に read -d 最後の文字
とか使ってデータを読んでいるのも見つかりましたが、対応してないシェルがあったり最後の文字を指定するのは汎用的ではないので、良さげな感じのコードで書きました。
なお、普通は tput lines
とか tput cols
とかを使ったほうが簡単です。$LINES
や $COLUMNS
を使う方法もあります。