さようならはてな ;-;/

ということで次はまあ何か適当にやると思います。まあこことか見てください http://niha28.sakura.ne.jp/
折角なので最後にはてなディスっておきます!

  • はてな記法が直感とかなりずれてるので非常に不愉快
  • はてブがゴミ
  • 増田追いにくすぎる…

とかです。ありがとうございました。

screen + curses で表示がずれるよ、というお話

もうカラムの話は飽きたかも知れませんが今回も UTF 的なナニがソレのカラムの話です。
とりあえずボクは飽きました。


curses は罫線が1カラムであることを期待します。常識的に考えてそうであるべきです。し、地球上のほとんどの環境では1カラムです。
が、日本で使われてるフォントの多くは2カラムで出力します。誰がそうしたのかしりませんが、小石くらいは投げてもいいと思います。
(勿論ここに行き着く前に罫線は Ambiguous なため、CJK周りの煩雑な問題を解決(になってないけど)するパッチを当てないといけません)
どういうことか分からない人は以下のURLを開いてみましょう。
http://en.wikipedia.org/wiki/Box_drawing_characters
多分ページ内のテーブル内の罫線は全角、画像の罫線は半角に見えると思います。ギャグだと思いたい。
そんなわけで、普通に curses を使ったソフトを使うと表示が盛大にずれてしまいます。
mlterm ではこういった問題を回避するために「curses などで罫線を出力する時」だけ特別に 1 カラムの罫線を出力してくれます。なんて賢いんだ…!天…才…!
さてここまではよろしい。ここから screen ユーザー涙目な話になります。


mlterm を使っていても screen を介すと台無しになります。何故かというと screen が(端末エミュレータでもあるので当然ですが)自前でエスケープシーケンスを処理してくれるからです。具体的にどういった処理がされるかというと、当然ですが罫線に普通に置き換えられます。
これは日本以外の環境では1カラムなので問題ないので順当な処理ですが、日本人は悲しい気持ちになります。
mlterm も既に罫線に置き換えられたものはさすがにどうしようもないのでそのまま表示してずれます。泣いていい。


でまあそこから、「screen に ESC(0 を処理させずに mlterm に処理させる」とか「Unicode に半角の罫線とかその代わりになるいい感じの文字あるんじゃね」とか色々やったんですが、ボクが悪かったのか何が悪かったのか結局どれも駄目で、個人的な結論としては普通に「-+|」に置き換えよう、という話になってしまいました。
それが嫌だから1週間頑張ったんですけどね!
もしそんなダサい形でも直したいという酔狂な人がいたら encoding.c の「/* 0: special graphics (line drawing) */」とコメントしてある辺りを以下のように適当に書き換えましょう。

  { 0x30, 0 },		
  { 0x005f, 0x25AE }, { 0x0060, 0x25C6 }, { 0x0061, 0x2592 },
  { 0x0062, 0x2409 }, { 0x0063, 0x240C }, { 0x0064, 0x240D },
  { 0x0065, 0x240A }, { 0x0066, 0x00B0 }, { 0x0067, 0x00B1 },
  { 0x0068, 0x2424 }, { 0x0069, 0x240B }, { 0x006a, 0x002B },
  { 0x006b, 0x002B }, { 0x006c, 0x002B }, { 0x006d, 0x002B },
  { 0x006e, 0x002B }, { 0x006f, 0x23BA }, { 0x0070, 0x23BB },
  { 0x0071, 0x002D }, { 0x0072, 0x23BC }, { 0x0073, 0x23BD },
  { 0x0074, 0x002B }, { 0x0075, 0x002B }, { 0x0076, 0x002B },
  { 0x0077, 0x002B }, { 0x0078, 0x007C }, { 0x0079, 0x2264 },
  { 0x007a, 0x2265 }, { 0x007b, 0x03C0 }, { 0x007c, 0x2260 },
  { 0x007d, 0x00A3 }, { 0x007e, 0x00B7 },
  { 0, 0}, 

ちなみに大抵のツールは「curses による罫線の出力にASCII文字を使う」みたいなオプションが存在すると思いますが、まあないのもあるかもしれないのでこちらのほうがいい、と思います。
自分で書く時にわざわざあほなオプションつけなくていいし…


まあまさか1週間以上時間かけてこんなしょんぼりした結果を向かえるとは自分でも思ってなかったので正直がっかりです…
端末周りの知識が足りず(エスケープシーケンスってなんぞー)コード読むのにめちゃくちゃ時間がかかってしまいました。得られた物は所謂バッドノウハウとか化石とかに近いものだと思うので、ちょっと悲しいですね。
なんにせよもう Unicode まわりの煩雑な問題には二度と関わらないようにして、これからは幸せな人生を歩みたいと思います。ありがとうございました。



追記:ちなみにこの辺の曖昧な問題に対する回答として「エスケープシーケンスでカラム数を指定してやろう」という案があって、以下にちゃんとした提案としてまとまっています。
http://www.cl.cam.ac.uk/~mgk25/ucs/scw-proposal.html
が、今回のような「1カラムが期待される文字に大して2カラムの文字しか用意されていない」場合、そもそも端末側では解決することができません。ないものはないんです。
前回の「BULLETが本来1カラムなのに2カラムで計算されちゃってずれるよー」という逆の問題はそれでいけるのですが…
幸せ逃しそうなのでこの辺で止めます。


追々記:何か結局悔しくて続けてたんですが、普通に実装できました。よかったですね!無視するんじゃなくて、出力すればいいじゃんという感じで…
ansi.c の DesignateCharset で

  if (c == '0' && n == G0)
    {
      AddStr("\033(0");
      linedrawing = 1;
      return;
    }
  if (c == 'B')
    {
      if (linedrawing && n == G0)
        {
          AddStr("\033(B");
          linedrawing = 0;
          return;
        }
      c = ASCII;
    }

とか。linedraw はグローバル変数として適当に宣言。
デフォルトだと as ae が ^N ^O だったりするかもしれないので適当に termcap なり terminfo なりごにょってください。おつかれさまでした。ありがとうございました。

Unicode の曖昧な文字幅の話

ちょっと色々調べたことをまとめておきます。
「曖昧な文字幅」の話でもあり、「曖昧な」文字幅の話でもあります。間違いとかあるかもしれないのであったら教えてくれるとにはさんが小躍りとかします。


Unicode には、文字ごとに文字幅というのが決まっています。これは、グラフィカルなアプリケーションではあまり重要ではないと思うのですが、コンソールアプリケーションでは非常に重要になってきます。
文字幅にはいくつか種類があるのですが、そのなかに「Ambiguous」という非常に不愉快なものがあって、これは文字幅が「文脈依存」という、まあ常識的に考えてありえないものです。
勿論そういったものが存在する理由はあるのですが、文字幅が曖昧とかぶっちゃけめちゃくちゃ迷惑な話ですね。つけあがるなよ。


多くのソフトウェアでは、この Ambiguous な文字を「1カラム」で計算してしまいます。
(ちゃんと調べてないので不正確な感じですが、 glibc の wcwidth か何かの実装がそうなってしまっているためだと思います。嘘かもしれません。)
現実には Ambiguous な文字というのは、そのほとんどが2カラムを期待しています。
1カラムで表示されると、当然文字は重なってしまいます。困りました。
ということで、場当たり的な解決にしかなっていないのですが、多くの場合パッチを当てることで解決することになります。
このパッチというのが一般的にどういったものかというと「Ambiguous な文字を2カラムで処理する」というものです。
これによって、ひとまずは文字が重なるという問題は解決されることになります。めでたしめでたし。


でまあここで終われたらよかったねーという話なんですが、続きます。
どうやら Ambiguous な文字の中には、1カラムの文字もあるようなのです。
これが、厳密にカラム数を計算する必要のあるアプリケーションで問題になります。
例えば w3m です。


w3m には UL 要素内の LI 要素の表示に使われる記号の中に「•」というものがあります。
(この記号は、フォントによっては表示されないかもしれません。最近 Osaka を使うようになったのですが Osaka では表示されませんでした。もうこんな文字は捨てろということですね!)
これは BULLET と呼ばれる記号で、文字幅は Ambiguous です。パッチを当ててオプションを適切に設定した w3m なら、2カラムで計算されることでしょう。
で、よく見てほしいんですが、これ「•」所謂「半角」に見えると思います。1カラム幅なんですね。しかし w3m はこれを2カラムと解釈してしまう。それの何が問題なのか。
ここで LI 要素内に A 要素があったとします。
http://niha.sakura.ne.jp/bullet01.png
春香さんです。かわいいですね。光ってる部分が実用面で非常に問題なのですが、画像編集基本的にウィンドウズでしかやったことないのに今ウィンドウズマシンがなくって困…
違います!!!!!リンクにカーソルを持っていってみましょう。
http://niha.sakura.ne.jp/bullet02.png
w3m はフォーカスの当たったリンクに下線を引くため再描画しようとします。リンクの位置を計算するためにカラム数を数えますが、ここで「実際のカラム数」とのずれが生じてしまいます。
1カラムの文字を2カラムで計算してしまっているため、実際の位置よりも1カラム後ろから再描画してしまい、ずれが発生してしまうわけですね。
今のところ BULLET 以外の文字ではこういった問題を確認していないのですが、他にもありそうな気がしてドキがムネムネします。


この様な問題が起きるのは Ambiguous な文字を全て2カラム決め打ちしてしまっているためなのですが、何故2カラム決め打ちというような、ぶっちゃけていえばお粗末な話になってしまっているのか。
これはボクの推測なんですが、どのパッチも既に存在した他のパッチを参考に作られていると思うんですね。で、その一番始めにできたパッチというのが「厳密なカラム数の計算が必要でないアプリケーション」に対するものだったんじゃないかなあと考えています。


結論ですが、ボクが言いたいのは「厳密なカラム数を計算するパッチ」を書く必要がある、ということではなく…
そもそも Unicode という統一された規格に関することで、各アプリケーションがパッチを当てないといけないというのは、どう考えても間違っているし、爆発して欲しいし、ニートだって暇じゃないんでこんなことに1週間以上も悩んだりしたくないわけです。
で、ここで「GNU あたりが何か頑張れよ!」って言って終わりたかったんですが、まだきちんと調べてない問題があって、そもそも「フォントによって Ambiguous な文字の文字幅が違う」とか、その辺は大丈夫なんですかね…
冷静に考えると、全ての文字をサポートすることさえ大変なのに、全ての文字でありもしない標準に合わせてカラムを設定するというようなことは、できている気が全くしません。
それどころか、実はボクが見落としているだけで本当は Ambiguous な文字は全て2カラムであるべきで、1カラムとかふざけんなよ爆発しろ!とか…うーん。
全然まとまらない状態で書き始めたのでやっぱりまとまりませんでした。ありがとうございました。
ぶっちゃけ何が本当に問題なのかまだ分かってない気がします。分かってるか分からないし分からないか分からない。


最後に全然関係ない話ですが screen + ncurses で box 使って枠線つけたらずれる理由が全く分からない。
こっちはカラム数の計算間違えるという問題は発生しないはずなので別の理由のはずなのですが、ちょっと調べたくらいだと全く分からないし、いい加減疲れてもううんざりなので誰か分かる人いたら教えてくれてついでにパッチとか設定とか書いてくれると小躍りします。

screen

git レポジトリの最新版をつかいましょう。
git レポジトリの最新版をつかいましょう。
git レポジトリの最新版をつかいましょう。


あまりの大事さに三回言った。
まあ focus は追加されてなかったので、よかった(?)


あ、うわー。昨日の記事きえた。そういえばはてなは六時になるまでは日付変わらないんだっけ。あちゃー。上書きしてしまったよよよ…

何があったか書いとくと vertically な split が可能になるパッチがあったけどバグってて悲しいので直してついでに focus を強化した。という話だったんですが git のほうならパッチとかあてなくてもいいしバグも取れてて最高っすね!っていう話です。

あけました

おめでとうございます。


去年の抱負はなんだったかしらとしばらく考えたのですが、思い出すことができませんでした。
仕方がないので今年の抱負は「抱負を忘れない」にしたいと思います。


よろしくお願いします。

SRM

topcoderSRM を始めました、といいたいのですが。

  • 21日:気づいたら人いっぱい
  • 24日:12時間ほど時間を誤解

とかで、このまま「始めたかったけどやめました!」みたいにしたほうがいいんじゃ…と思っています。嘘です。
何かグループとかあるらしいのではいりました。
http://topcoder.g.hatena.ne.jp/
基本的には問題が読めません。おしまい。