Asial Blog

Recruit! Asialで一緒に働きませんか?

mac の zsh で日本語の濁点・半濁点付き仮名を正常に補完できる様にする

カテゴリ :
バックエンド(インフラ)
タグ :
Mac
zsh
初めまして。7 月にエンジニアとして入社した花島と申します。

早速ですが、Mac の zsh で日本語の濁点・半濁点付き仮名を正常に補完できる様にする拙作のパッチをご紹介させて頂きたいと思います。

Mac におけるファイル名の取り扱い



まず始めに、濁点・半濁点付き仮名が補完できないという事について少し触れたいと思います。
Mac を日常的に、また仕事で利用しているという方の中には、濁点・半濁点付き仮名を入力して補完しようとして補完できなかったという経験をお持ちの方が少なからずいらっしゃるのではないでしょうか。
これは Mac のファイルシステムである HFS+ におけるファイル名の扱い方に原因があります。

HFS+ ではファイル名を Unicode (UTF-8) で格納するのですが、その際、NFD という正規化を施して格納します。
(一般的な UTF-8 では NFC という正規化がされています)
詳しくは割愛しますが、この NFD という正規化が行われると、仮名と濁点・半濁点が分解され、二つのコードポイントで扱われる様になります。
(逆に NFC では濁点・半濁点付き仮名は単一のコードポイントで扱われています)

具体的な例を挙げます。
カタカナの「」は通常の UTF-8 で使われている NFC で正規化されると "U+30D1" というコードポイントですが、
NFD で正規化されると "U+30CF U+309A" という二つのコードポイントになります。

先ほど NFD では仮名と濁点・半濁点が分解されると申し上げた通り、
U+30CFU+309A はそれぞれ「」と「」を表すコードポイントです。
(上記の「」は便宜的に表記したもので、実際の U+309A の文字とは異なります)

話を戻します。
HFS+ が NFD で正規化をして格納するのは別に困った事ではないのですが、
問題は HFS+ からファイル名を取り出すときにそれをそのまま、NFD で正規化された状態で取り出されてしまうという所にあります。
端的に言えば、保存時と読み込み時でファイル名が変わってしまうという事になります。
(保存時に NFD で正規化するのなら読み込み時に NFC で正規化し直して欲しいものですが…)

濁点・半濁点付き仮名の補完



さて、ここで話は zsh での補完に移ります。
例として「パズー.jpg」というファイルがあるとします。
」を入力後、ファイル名を補完しようとすると候補が見つからないはずです。
逆に「」と入力後に補完をすると「パズー.jpg」と補完されるはずです。
…これでは折角の補完も使い物にならないですね。

上記の様な補完が行われるのは以下の為です。
前者は入力された「」が NFC で正規化された U+30D1 (0xE3 0x83 0x91) であるのに対し、
ファイル名の「」は NFD で正規化された U+30CF (0xE3 0x83 0x8F) U+309A (0xE3 0x82 0x9A) であるため、比較が失敗(=補完されない)します。
後者は入力された「」とファイル名の「」の最初のコードポイントが共に U+30CF (0xE3 0x83 0x8F) であるため、比較が成功(=補完される)します。

この様に、zsh では濁点・半濁点付き仮名の補完が正常に行えません。

zsh にパッチを当てる



ここでようやく本題のパッチの話になります。
https://gist.github.com/1403346
(なお、パッチ対象の zsh のバージョンは 5.0.0 です)

このパッチは zsh のディレクトリのファイル名を読み込む処理に、
OS から受け取った NFD で正規化された文字を NFC で正規化された文字に変換するという変更を加えます。
これにより比較する対象がそれぞれ NFC で正規化された文字になるため、正常に補完が行える様になります。

以下にパッチ適用からインストールまでの例を示します。
  1. $ curl -L http://www.zsh.org/pub/zsh-5.0.0.tar.bz2 | tar xf - && cd zsh-5.0.0
  2. $ curl -kL https://raw.github.com/gist/1403346 | patch -p1
  3. $ ./configure && make -j 4 && make install

また、パッケージ管理に homebrew をお使いの場合はより簡単にインストールできます。
  1. $ brew tap waltarix/customs
  2. $ brew install waltarix/customs/zsh
なお、上記 homebrew でインストールした zsh にはコマンドラインで「」等のいわゆる Ambiguous width な文字が正常に扱えるようになるパッチも適用されています。
こちらについても、いずれ機会がございましたらご紹介させて頂きたく思います。

以上、Mac の zsh で濁点・半濁点付き仮名を正常に補完できる様にするパッチのご紹介でした。