はじめに
わたしはコンソールアプリ上級者ではありません
ただ色々制作していた中でたまたまCSIを知って感動したので書きました。
CSIとは
エスケープシーケンスの一種です。
エスケープと聞いて真っ先に思い浮かぶのは、\n
でしょう。
\n
はUnix系において改行を意味する非常に簡単なエスケープですが、今回はもう少し込み入った特殊表現を行います。
ちなみに、CSIはControl Sequence Introducerの頭文字です。
なにができるか
代表的なものは
- カーソルの移動
- 画面の消去(カーソル以前の全消去、カーソル以後の全消去も可)
- 行の消去
- 文字の消去
- 矩形単位での文字消去
- 文字スタイル(太字、文字色、背景色など)の設定
- ウィンドウ情報(サイズなど)の制御
などなど…
こちらに制御の種類と方法が全て掲載されています。
動作について
Bashは簡単にエスケープさせてくれないようです(参考)。
[追記:コメント情報]
Bashでもエスケープできるようです。echo -e
のように-e
オプションをつけると、エスケープが適用されます。
また、上記リンクは別の議論でした。訂正させていただきます。
CSIを使ってみる
さて、先の例では改行をするための\n
を示しました。
CSIは複数の制御ができるので制御コードは一通りではありませんが、CSIであることを認識させるための接頭辞があります。
それが\e[
または\033[
ないしは\0x1b[
です。
[追記]
bashがエスケープできないと思っていた件、\e[
が対応していないだけでした。\033[
なら可能です。
eは文字型、033は8進数、0x1bは16進数なので本質的には変わりませんが、eの方が楽でしょう。
CSIは狭義の1エスケープシーケンスの一種です。始めに\e
を挿入することでエスケープシーケンスの始まりを伝え、さらに[
でCSIであることを伝えます。
この後に何を書くかによってCSIの制御が変わってきます。
CSI制御一覧(一部)
制御文字(スペースは不要) | 動作 |
---|---|
n A | n行(指定がなければ1行)カーソルを上げる |
n B | n行(指定がなければ1行)カーソルを下げる |
n C | n文字(指定がなければ1文字)カーソルを進める |
n D | n文字(指定がなければ1文字)カーソルを戻す |
n E | カーソルをn行(指定がなければ1行)下の先頭に合わせる |
n F | カーソルをn行(指定がなければ1行)上の先頭に合わせる |
n G | カーソルを現在の行のn文字目(指定がなければ1文字目)に合わせる |
n; m H | カーソルをn行目のm文字目(指定がなければ1行1文字:左上)に合わせる |
n J | 画面消去(詳細は後述) |
n K | 行消去(詳細は後述) |
n S | n行(指定がなければ1行)画面をスクロールして進める |
n T | n行(指定がなければ1行)画面をスクロールして戻す |
n L | カーソルのある行の前にn行(指定がなければ1行)挿入 |
n M | カーソルのある行からn行(指定がなければ1行)削除 |
n P | カーソルの位置からn文字(指定がなければ1文字)削除 |
n P | カーソルの位置からn文字(指定がなければ1文字)を空白置換 |
n ` | カーソルを現在の行のn文字目(指定がなければ1文字目)に移動 |
n a | カーソルをn文字(指定がなければ1文字)進める |
n d | カーソルを現在の位置のn行(指定がなければ1行)上げる |
n m | SGR(Select Graphic Rendition)パラメータを指定する(詳細は後述) |
s | 現在のカーソル位置を記憶する |
u | 記憶したカーソル位置を呼び出す |
> 3; a; b; c; d J | (b, a)から(d, c)まで矩形消去 |
> 3; a; b; K | 現在の行のa文字目からb文字目まで消去 |
画面消去(CSI n J)と行消去(CSI n K)の挙動
n | 挙動 |
---|---|
無指定 | カーソルより後ろを画面(行)先頭まで消去 |
0 | カーソルより後ろを画面(行)先頭まで消去 |
1 | カーソルより手前を画面(行)末尾まで消去 |
2 | 画面(行)全体を消去 |
SGRパラメータ(代表的なもの)
n | 意味 |
---|---|
なし | パラメータリセット |
0 | パラメータリセット |
1 | 太字 |
2 | 薄字(広くはサポートされていない) |
3 | 斜体(広くはサポートされていない、反転表示(n=7)になることも) |
4 | 下線 |
5 | 点滅:150回/分以内 |
6 | 高速点滅:150回/分以上(広くはサポートされていない) |
7 | 反転表示:前景と背景の色が入れ替わる |
8 | 文字を隠す(広くはサポートされていない) |
9 | 取り消し線(広くはサポートされていない) |
10 | デフォルトのフォント |
11–19 | (n-10)番目の代替フォントを使用 |
20 | フラクトゥールフォント(ほとんどサポートされていない) |
21 | 太字OFF(広くはサポートされていない), 二重下線(ほとんどサポートされていない) |
22 | 色と強調(太字・薄字)を元に戻す |
23 | 斜体とフラクトゥールを元に戻す |
24 | 下線を取り消す |
25 | 点滅を取り消す |
28 | 文字の隠蔽を取り消す |
29 | 取り消し線を消す |
30–37 | 前景色(要は文字色)を(n-30)番に変更させる(色番号は後述) |
38 | 前景色設定拡張。\e[38;5;n でカラーインデックスを指定できる(0...255)。\e[38;2;r;g;b でRGBを設定できる(各0...255)。 |
39 | 前景色をリセット |
40–47 | 背景色を(n-40)番に変更させる(色番号は後述) |
48 | 背景景色設定拡張。\e[48;5;n でカラーインデックスを指定できる(0...255)。\e[48;2;r;g;b でRGBを設定できる(各0...255)。 |
49 | 背景色をリセット |
なんだこのサポートされてない嵐…
色番号
番号 | 色 |
---|---|
0 | 黒 |
1 | 赤 |
2 | 緑 |
3 | 黄 |
4 | 青 |
5 | マゼンタ |
6 | シアン |
7 | 白 |
SGRの使い方
実際にSGR設定を行うときは
echo "\e[31mred\e[m"
とやれば赤文字でred
と表示してくれます。
また、
echo "\e[31;43mred&yellow\e[m"
とやれば、赤文字黄背景でred&yellow
と表示してくれます。
このようにオプションを;
区切りで打っていけば複数のオプションを一度に設定できます。
CSI終了後に予想外の挙動をしないように、必ず最後に\e[m
または\e[0m
でオプションを切りましょう。
-
厳密には
\n
はエスケープシーケンスではありません。狭義にはESC(0x1B)
から始まる制御バイト列のことを指すそうです。 ↩