彷徨えるフジワラ

年がら年中さまよってます

空白詰めと符号化方式

CP932 (Shift-JIS ね) に関するバグを滑り込みで直すことができて、やれやれ危ういところだった、とホッとしながら、Mercurial 1.6 版を仕事で使っている環境に入れて help 出力を確認してみたら....:

 -A --addremove                 コミット前に、新規/不在ファイルを登録/除外
    --close-branch              ブランチを閉鎖し、ブランチ一覧での表示から除外
 -I --include パターン [+]  パターンに合致したファイルを処理対象に追加
 -X --exclude パターン [+]  パターンに合致したファイルを処理対象から除外
 -m --message テキスト      指定テキストをコミットメッセージとして使用
 -l --logfile FILE              コミットメッセージをファイルから読み込み
 -d --date 日時               記録される日時情報
 -u --user ユーザ            記録される作成者情報
    --mq                        パッチ管理リポジトリへの操作

あれ?オプション一覧部分のカラム揃えがガタガタだ!
おかしい。CP932 での文字化けの修正の際に確認した限りでは、こんなことは無かった筈....。あ、こっちの環境は UTF-8 環境だ。ひょっとして、符号化方式を CP932 でやってみると....やっぱりちゃんと表示される!

MBCS 文字の折り返しの件では、行末が早目に折り返されてしまう点を妥協できるならば、Python 標準の textwrap モジュールの差し替えを避ける、という条件下では、そこそこ妥当な修正に落とし込めたと思ったんだけどなぁ > UTF-8 での日本語使用

呆然としていても問題は解決しないので、例によって、地道に条件を絞り込むことに。

とりあえず、カラム揃えの崩れた表示に目を凝らす事暫し。どうやら、値指定が必要なオプションでカラム表示が崩れているっぽいように見える。っていうか、それ、俺の修正だ!! > オプションへの値指定の要否表示

更に崩れた表示に目を凝らしてみると....値表示が必要なオプションの表示の際に、値の翻訳文字列の文字数に応じてカラムがずれているっぽい気が....

わかった!オプション説明文の字下げ幅算出は、オプション表示部分(例: "-I --include パターン [+]" 部分)の文字列に対して単純に len() を適用しているのだけど、UTF-8 の日本語文字はバイト数≠文字数だから、Python の len() による算出だと駄目なんだ!

かなり自分で墓穴を掘ったっぽい感じ.... orz

気を取り直して、文字コードを意識した字下げ幅算出を行う修正をしてみると....おぉ!カラムが揃って....揃って....あれ?ちょっとは良くなったけど、微妙にズレたままだ。

ここまで来ると、20 世紀から続く由緒正しいデバッグ方法、つまりデバッグ情報出力の追加という伝家の宝刀を振るわざるを得ない状況と判断(笑)。しかし、字下げ量の算出は正しく機能しているとしか思えない出力が。

おかしい。字下げ幅の算出が正しいなら、他に空白詰めが狂う要因が....空白詰め?....あ!? Python の幅指定整形機能の空白詰め量の算出ってバイト列ベースなんじゃねぇ?

    '%-*s' % (length, string)

上記の様な文字列整形処理は、length 幅になるように string 文字列の右側に空白を詰めるのだけれど、文字列クラスってバイト列ベースだから、符号化方式とかを無視して問答無用のバイト数算出しかしないよね?

ということで、string の表示幅を width とした場合に:

    '%s%s' % (string, ' ' * (length - width))

上記の様な処理をさせてみる。....おぉ!表示が揃った!

原因がわかったのは一安心だけど、自分で何か作る時に、これって絶対盲点になりそうだなぁ。気を付けよう > Python