ncurses 6.1にアップデートしたらatopなどのレイアウトが崩れる問題には環境変数TERMを変えれば良いことがわかりました, エスケープシーケンスrepが原因でした
要約
シェルの設定に
export TERM=gnome-256color
と書けば解決.
問題
ncursesが6.1にアップデートしてから, システム監視ツールのatopのレイアウトが崩れるという問題が発生していました.
I upgrade to ncurses 6.1, atop layout broken. · Issue #25 · Atoptool/atop
環境に関する情報提供もありましたし, 今回調査してバグ修正を行ってみようとしました.
issueに寄せられたコメントによると,
TERM
環境変数によって動作が変わるようです.
TERMに使えるメジャーな環境変数はtoe
コマンドで取得できます.
2018-06-11T15:13:26 ncaq@strawberry/pts/6(0) ~/Desktop/LilyTerm
% toe
screen VT 100/ANSI X3.64 virtual terminal
screen-256color GNU Screen with 256 colors
xterm xterm terminal emulator (X Window System)
xterm-color generic color xterm
xterm-256color xterm with 256 colors
ansi ansi/pc-term compatible with color
dumb 80-column dumb tty
linux linux console
rxvt rxvt terminal emulator (X Window System)
rxvt-unicode rxvt-unicode terminal (X Window System)
vt52 dec vt52
vt100 dec vt100 (w/advanced video)
vt102 dec vt102
vt220 dec vt220
崩れるものと崩れないものの調査
まずいろいろなTERMを試してみて, 崩れるものと崩れないものを分類してみることにしました.
崩れなかった
screen
screen-256color
xterm-color
linux
rvxt
rxvt-unicode
vt100
vt102
vt220
gnome
gnome-256color
崩れた
- xterm
- xterm-256color
- ansi
論外
- dumb
- vt52
崩れる条件の設定項目を探しました
を見て, 崩れたxtermとxterm-colorの間で両方出力して, 崩れたxtermの内容を二分探索的にxterm-colorに置換していきました.
そうすると項目rep=%p1%c\E[%p2%{1}%-%db,
が書かれている場合はatopが崩れることがわかりました.
ncursesのソースコードでどのように生成されているか
ncursesのソースコードを読んでみたところ,
misc/terminfo.src
のxterm-new
にuse=ansi+rep
が指定されているのが生成の元凶らしいです.
6.1のアナウンスでxterm-newにrepを追加したと書かれていますね.
add rep to xterm-new, available since late 1996.
repとは一体何なのか
terminfo(5) manページによるとrepは文字を繰り返すらしいです.
繰り返す…? つまりループ構文ですかね…? しかしそれがカスタム出来るというのは一体どういうことなのでしょう.
terminfoを参考にrepを使うプログラムを書いてみましょう.
ncursesのソースコードを読んで理解しようとしたけれどものすごい難しい.
サンプルコードであるtparm(repeat_char, 'x', 5)
を打ち込んでも文字が全く増殖しない…
以下のコードを実行しても文字が増えなくて悩んでいました.
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <term.h>
int main() {
setupterm(NULL, fileno(stdout), NULL);
putp(tparm(repeat_char, 'x', 5));
return 0;
}
何もわからないのでncursesをビルドしてデバッグシンボル付きのものをGCCのスタティックリンクの順番は大事 – ブーログを教えて貰って, start-groupでリンクしてgdbでたどってみることにしました.
かれこれソースコードを眺めること3時間. ふとKonsoleではこの問題は解決したということを思い出して, このプログラムをKonsoleで実行してみることにしました. そうしたら文字が増えました. LilyTerm, というかvteのこのバージョンがrepの形式に対応していなかったということのようですね.
xを5回繰り返すrepをtinfoが解凍したらエスケープシーケンスはxESC[4b
になります.
KonsoleによるとREPは Standard ECMA-48 の8.3.103に定義されているようですね. Konsoleのソースによるとbでトークンが終わる場合REPになって, 前の数値が追加する数になるようですね. そんな定義PDFの何処にも見つからないんですけど何処に書いているんでしょうか…
解決法
解決法は原因を調べるずっと前からわかっていて,
export TERM=gnome-256color
と書くだけです. これでrepの設定が消えてncursesは正常に動くようになります.
lilytermの設定で
emulate_term = gnome-256color
とか書けば良いかと思いましたがこれはダメで, termcapを見に行くのでterminfoを見に行きません.
LilyTerm側で解決する方法が思いつかなかったので, とりあえず調査内容を関連issueに書き込んでおきました.
Default to TERM=xterm-256color · Issue #127 · Tetralet/LilyTerm
ひとまずzsh側で対策を取ることが出来てしまいましたが, 根本的な解決には至りませんでした… LilyTermのvteのバージョンを上げれば良いのでしょうか? Konsoleはrepに対応することで対策したようですね. これで休日使い切ってしまい意欲も使い切ってしまってこれ以上調べる気になれません. 今日はここまでです.
エスケープシーケンスrepに何の意味があるんでしょうか
同じ文字を追加するエスケープシーケンスの存在価値がわからない. アプリケーション側で出力する文字を増やせば良いじゃないですか… データ通信量節約にしても数文字節約することに価値を感じません.