本文へ移動
Hikari 仕様

std:term/screen — 端末出力 (ANSI 制御列)

標準ライブラリモジュール (index.md)。本書中の裸の §N は本書の節を指す。言語の意味論は ../../language-spec.md を参照。

std:term (../term.md) が入力 (read_key) と端末サイズ (size) を担うのに対し、本モジュールは出力側の ANSI エスケープ列 — 代替画面バッファー・カーソル制御・画面消去・カーソル移動・前景色 (8 色と 24bit)・文字装飾 — を文字列として提供する。入力イベントのデコードは event.md を参照。

各メンバーは端末に直接触れず、print に渡すための文字列を組み立てるだけの純粋な値・関数。したがってヘッドレス環境でも決定的で、出力の検証にそのまま使える。

import { enter_alt, exit_alt, hide_cursor, show_cursor, clear, move } := "std:term/screen"

本モジュールは効果を1 つも持たない../../language-spec.md §17.9)。各メンバーは ANSI 制御を文字列として組み立てるだけで自分では書き出さないためである — 書き出すのは print で、そこで Io が付く。

1. 画面・カーソル制御 (文字列定数)

名前 意味
enter_alt 代替画面バッファーへ切り替え (CSI ?1049h)。全画面 TUI はこれで (1,1) をビューポート先頭に固定でき、終了時に元画面 (シェル履歴) を復元する
exit_alt 代替画面バッファーから復帰 (CSI ?1049l)
hide_cursor カーソル非表示 (CSI ?25l)
show_cursor カーソル表示 (CSI ?25h)
clear 画面全消去してホームへ (CSI 2J + CSI H)
home カーソルをホーム (1,1) へ (CSI H)
clear_line 現在行を消去 (CSI 2K)
reset 文字装飾を解除 (CSI 0m)

2. move — カーソル移動

  • 形: move(row, col)
  • 1 始まりの row 行・col 列へカーソルを移す (CSI row;col H) 文字列を返す
print(move(3, 10) + "x")   # 3 行 10 列に "x"

3. 文字装飾 (SGR ラッパー)

対象文字列を SGR コードで囲み、末尾に reset を付けて返す。装飾の表示幅は 0 なので、レイアウト計算は装飾前のプレーン文字列で行い、装飾は最後に適用する。

名前 意味
sgr sgr(code, s) 任意の SGR codes を囲む (CSI code m + s + reset)
bold bold(s) 太字 (sgr(1, s))
dim dim(s) 減光 (sgr(2, s))
reverse reverse(s) 反転 (sgr(7, s))
fg fg(color, s) 前景色 colors を囲む (sgr(color, s))

3.1 装飾を置く形 (sgr_set)

上の 5 つが対象を囲むのに対し、sgr_set は制御列だけを返す — 対象を取らず reset も付けない。装飾の切り替えを呼び手が自分で組むための形で、多数の断片を続けて描く差分描画が、断片ごとに reset を挟まずに済む。既定へ戻すのは前景 39・背景 49・全解除は reset

名前 意味
sgr_set sgr_set(code) SGR code を設定する制御列 (CSI code m) を返す
print(sgr_set(red) + "error" + reset)

4. 前景色 (SGR コード定数)

前景色の SGR コード (Int)。fg(color, s) に渡すか、SGR 列を自前で組むのに使う。背景色は +10、太字は 1

名前 コード
black 30
red 31
green 32
yellow 33
blue 34
magenta 35
cyan 36
white 37
print(fg(red, "error") + " " + bold("!"))

4.1 24bit 色 (truecolor)

fg_rgb / bg_rgb は 24bit の色を設定する制御列を返す。§3.1sgr_set と同じく対象を囲まない — 戻すのは呼び手の仕事である。各成分は 0..255 の Int で、範囲外は端末の解釈に委ねる (この層は丸めない)。

名前 意味
fg_rgb fg_rgb(r, g, b) 前景色を 24bit で設定する制御列 (CSI 38;2;r;g;b m)
bg_rgb bg_rgb(r, g, b) 背景色を 24bit で設定する制御列 (CSI 48;2;r;g;b m)

前景と背景を同時に置くと、半ブロック (U+2580) の上半分と下半分へ別々の色を割り当てられる。1 セルで縦 2 画素になるので、端末の縦解像度が 2 倍になる。

print(fg_rgb(220, 60, 70) + bg_rgb(20, 24, 32) + "▀" + reset)

24bit 色を解さない端末ではこの制御列が無視され、文字は既定の色で出る (配置は崩れない)。

4.2 持たないもの

  • 256 色 (CSI 38;5;n m) は持たない。8 色 (§4) と 24bit (§4.1) の間を埋める段で、呼び手が SGR コードを自分で組んで sgr_set へ渡せば書ける。名前付きの面が要ると分かってから足す
  • 端末の色能力の検出は持たない。本モジュールは端末に触れず文字列を組み立てるだけで、能力の問い合わせは応答の読み取り (入力側) になる。色を落とす退避が要る呼び手は、COLORTERM 等を自分で見て 8 色 (§4) と 24bit (§4.1) を選び分ける

5. 典型的な全画面 TUI の枠組み

std:termraw_modestd:term/eventnext_event/mouse_on/mouse_off と組み合わせる。

import { raw_mode } := "std:term"
import { next_event, mouse_on, mouse_off } := "std:term/event"
import scr := "std:term/screen"

raw_mode {
  print(scr.enter_alt + scr.hide_cursor + mouse_on + scr.clear)
  # … next_event() ループで描画・更新 …
  print(mouse_off + scr.reset + scr.show_cursor + scr.exit_alt)
}