Readline

プロンプトが壊れる件について

readlineのバグだったとか寝言言ってたけど違った。君のせいにしてごめんよ。 ソースコード読んでみて分かったんだけど、readline はエスケープシーケンスを考慮して文字数計算するみたいなことは もともとやってくれない。そのかわりに、文字数の計算で無視したい部分を ここ で定義してある RL_PROMPT_START_IGNORE (\001) と RL_PROMPT_END_IGNORE (\002) ではさむことによって プロンプトが崩れないようにする。 Bash のプロンプトを設定するときにはそれぞれ \[ と \] で挟むとこれらの文字に置き換えてくれるっぽい (これは挙動から推測しているだけで、正確には Bash のソースコードを読んでいないので分からない)。 これはちゃんと Bash の Manual page にも書いてある。 \[ begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt \] end a sequence of non-printing characters man 読みましょうね。 …といっても readline は色付けのエスケープシーケンス無視する機能くらい持っててもいいと思うんだ……。

readlineのバグだった

注意: この記事の内容は間違っています。 こちらを参照してください。 この記事 で Bash のプロンプトが壊れるとか いろいろ言っていたが、いまさらながら調査した。 その結果、プロンプトにエスケープシーケンスが含まれていると、その文字数だけ履歴が残ったり 行の途中で折り返してしたりすることが分かった。 たぶんプロンプトから残りの文字数を計算する部分でエスケープシーケンスが処理されていない? 以下 PoC。 #include <stdio.h> #include <readline/readline.h> #include <readline/history.h> int main(void) { for (;;) { char *line = readline("\033[1mfoobar\033[0m"); if (line == NULL) { break; } add_history(line); } } これで 22222... の行まで入れたあとに 2 つ履歴を遡るとこれになる。 特に騒がれてないということはロケールとかフォント依存だったりするのかな……。 コード読んたりするのは明日以降に…。 というか今日プロンプトを2行にしてワークアラウンドしたんだけど、 2 行のプロンプト見にくくてあんまり好きじゃないのでなんとか解消したいんだよなぁ。 まあ太字にするのやめればいいんだけど。