初歩のシェルスクリプトで遊ぶ[端末の256色カラーセレクタ(7)]

カラーパレットにカーソル表示する見えない数字

---- ${colorTableViewCode} -------------------------------------------
     1:0        12
     2:1        12
     3:2        12
     4:3        12
     5:4        12
     6:5        12
     7:6        12
     8:7        12
     9:0        -1
    10:8        12
    11:9        12
    12:10       12
    13:11       12
    14:12       12
    15:13       12
    16:14       12
    17:15       12
    18:0        -1
    19:232      8
    20:233      8
    21:234      8
    22:235      8
    23:236      8

デバッグモードで表示されるシェル変数の一つで、これがカラーパレット表示の設計図になってます。色の番号のみが並んだ、元の表形式データから、表の列数が変わっても画像の横幅を一定にする計算をして作ります。
インデックスカラー0番が12文字分の幅、同様に1番、2番と続き、9行目で改行。表示幅が負の数なら改行、というルールです。
ここから端末表示するための画像データを作るわけですが、問題はどうやって選択中の色を指し示すカーソルを重ねるか、ということ。
このシェル変数から画像データを作るときに、同時にカーソルも書き込んでしまうのがいちばん簡単で、それでもそこそこ動いてくれたんですが。

カーソルを押しっぱなしにして移動させると、連続書き換えが追いつきません。矢印キーの文字が端末に漏れて、ちらつきます。dashならそこそこいけますが、遅いシェルにすると、矢印キー押しっぱなし操作は無理です。

案1:書き換えた行のみ書き換える

カーソルが重なっている行のみ書き換えることを試しました。これでもそこそこ結果は出たんですが、この場合は

  • カーソルを書き加えるだけなら簡単だが、移動前のカーソルを消さなければならない。
  • そのためには、古いカーソルが描かれた行を覚えておかなければならない。

という仕組みになるので、そのぶんメインのスクリプトがシェル変数を保持して管理しなければなりません。これが煩雑だった。

案3:awkに書き換える

案2じゃなくて案3。これは最後までは組んでません。上記の元データから画像データを作りつつ、カーソルも加えて一気に描くスクリプトawkで組むと、まぁ速いというか、printfが外部コマンドになってるシェルに配慮するのがバカバカしくなる。
awkで一気に書いて、余計な小細工はしないのが単純でいいようにも思えましたが、案2ですでに出来ていたし、これはシェルスクリプトなので、awk案は廃案。

案2:画像データをほぼ描き上げてシェル変数に保持しておき、カーソルのみsedで上書きする

デバッグモードで表示される、これですね。この状態で、メインスクリプトのシェル変数に保存しておき、この上にカーソルを上書きします。

この画像データの中には、見えない数字として、セパレータ文字が埋め込んであります。デバッグモードのこれは、awkによって可視化したものです。
数字で識別できる目印を画像の中に埋め込んでおけばいいわけですが、普通のアラビア数字は使えません。
代わりに、o034,o035,o036,o037の4文字を、それぞれ数字の3,2,1,0と見なして、4進数4桁で、0-255の数字とみなし埋め込んでおきます。
カーソルを移動するたびに、sedでこの見えない4進数を探して、見えるカーソルに入れ替える、という仕組みです。

実装では、不可視数字入れ替え用のsedスクリプトには、ちらつき防止の上書きスクリプトと、フォーカス矢印表示スクリプトも同梱してます。
これらは制作終盤まで、それぞれ別のスクリプトに分離してました。分けたかったんですが、高速化を優先しました。これらを一つのsedスクリプトにまとめることで、カーソル移動のループで起動するパイプを、4つ減らせました。