問題
VSCodeでは等幅フォントを使っても、一部のマルチバイト文字を使うとインデント文字数がずれる。
たとえばインデント文字数4で、以下のようになる。
- 半角「A」や全角「A]の後に「タブ」「B」を入力した場合、 4文字目までインデント されて次の5文字目に「B」が表示される。
- 全角「α」の後に「タブ」「B」を入力した場合、 5文字目までインデント されて次の6文字目に「B」が表示される。(インデント文字数がずれる)
※ちなみに、ずれているのは「インデント文字数」であり、フォントが原因の位置ずれは発生していない。
全角「A」「スペース2文字」「B」と打った場合と、全角「α」「スペース2文字」「B」と打った場合で、「B」が表示される横位置は完全に一致する。
原因
ギリシャ文字や数学記号は内部的には1文字幅として扱われているのが原因
VSCode(VSCodeのエディタ部分として採用される高機能なブラウザベースのコードエディタのMonaco Editor)は、「A」や「漢字」、「全角カタカナ」は2文字幅と認識されるのに対し、「α」や「■」などのギリシャ文字や記号は1文字幅と認識している。
つまり「α」は見た目は全角に見えても内部的には半角(1文字幅)扱いされてるため、タブ位置計算がずれてしまう。
なぜギリシャ文字や数学記号は1文字幅と認識されるのか
そもそも「文字幅」というものは、シングルバイト文字は1文字幅、マルチバイト文字は2文字幅と単純に決まるものではない。
Unicodeでは各キャラクタに East Asian Width (EAW) という「文字幅のヒント」プロパティが定義されており、VSCodeはこの定義で文字幅を判定している。
- Wikipedia: East Asian Width (EAW)
https://ja.wikipedia.org/wiki/%E6%9D%B1%E3%82%A2%E3%82%B8%E3%82%A2%E3%81%AE%E6%96%87%E5%AD%97%E5%B9%85
「α」等はこのプロパティが「Ambiguous; 曖昧」と定義されており、東アジア環境では2文字幅、欧米環境では1文字幅に見えることがある文字とされている。
つまり「α」は日本語環境では全角に見えるが、OSやフォント次第で半角に見える可能性がある。
そしてVSCodeでは欧米環境を優先するために、この Ambiguous な文字を常に「1文字幅」扱いにしている。
対策は無い ※対策をご存知の方が居ればご教示ください
これは日本語で VSCode を動かすときのために、Ambiguousを2文字扱いにするような機能があれば解決する筈ではある。
しかしどうもAmbiguousを1文字扱いするのはエディタコア機能で、簡単には変更できないらしく「α」を2文字扱いする設定や拡張機能は存在しない。
一応、Ambiguousを2文字扱いするパッチはあるようだ。
https://github.com/laurent22/joplin/commit/45c73f79629a91108a1366c6e50771e67110d85a
https://github.com/laurent22/joplin/issues/2674
結論としてはVSCodeではエディタのコア機能で「α」や「■」などは1文字扱いされているため、それを2文字扱いでインデントを入れることは出来ない。
……ということになる。
(Ambiguousを2文字扱いするようコード変更してビルドしたVSCodeを使えば別だが)
うーむ、ここ数年の検索しても解けなかった疑問だったがChatGPTがこの記事の7割くらいの内容を答えてくれた。
この子、賢すぎる。