この記事はえとるねん Advent Calendar 2023 7日目の記事です。

この記事ではフォント(特にターミナルやコーディングで使うのに適したもの)や、 それを実際に使うための設定方法などを徒然と書き連ねるつもりです。 ちなみにあまりフォントそのものについては詳しくないので、 記事のハイライトはArch Linuxでのフォントの扱い方になりそうです

ユニコード?

フォントの話を始める前に、まず文字とは何なのかをはっきりさせようと思ったのでUnicodeについて少し調べてみます。

Wikipediaの記事によると、

Unicode(ユニコード)は、符号化文字集合や文字符号化方式などを定めた、文字コードの業界標準規格。

とあります。

符号化文字集合?

符号化文字集合 とは、 符号化(たとえばU+3042)された文字(たとえば’あ’)の集まりで、 文字と、それらに対応する記号(数字)を集めたものになります。 文字には

  • Name(名前)
  • Age(どのバージョンで追加されたか)
  • Plane(面)
  • General Category(文字の大雑把な種類)
  • Bidi class(右から左にかくとかの情報)
  • Decomposition(分解)
  • East Asian Width(いわゆる半角/全角)

といった様々な情報が含まれています。 この属性(properties)はUAX#44で見れます1。 それぞれの文字(コードポイント)の属性は UAX#ナントカ にある書式で、 なんちゃら.txt にかかれてます。 (ほぼ)全部の属性を1つのファイルで見たい!という方には、 UAX#42で定義されてるXML形式のファイルを見ればいいです(大きいです)2。 こういったデータは https://www.unicode.org/Public/UCD/latest/ で手に入ります。 いろんなプロパティがあって面白いなーとなれます。

実際は複数の符号で一つの文字を表したり (たとえば🙇‍♂️は4つのコードポイントで表されます)、 見た目が変わることもあって複雑です。

weztermの絵文字入力機能で入力しようとしている

文字がどういった情報を持ってるのか気になった方にはciceroをおすすめします。 こんな感じでコードポイントの情報やフォントまで見れて幸せになれます。

cicero –tuiでいろんな文字を見てみる 3

入力の方法は色々あります。 いくつか挙げると

  • VimのC-V (:h i_CTRL_V_digit) (コードポイントから)
  • Fcitix5のUnicode (コードポイントや名前から)
  • Weztermの絵文字入力 (コードポイントや名前から)
  • 何らかのプログラミング言語でコードポイントから直接指定 (コードポイントから)
  • UnicodePad(Android)

などがおすすめです。

文字を表示するときには、これらのプロパティをもとに並べて表示する必要があるわけなのですが、 こういった面倒な部分は多分ICU4CとかICU4Xといったライブラリがやってくれます(よく知りません)。 pacman -Qs icuしたらicuパッケージが入ってたし、 pactree -r icuしたらたくさんのパッケージが依存してました(直接で32個)。 SATySFiはlib-satysfi/dist/unidata/にいくつかのtxtファイルがあるみたいです。

文字符号化方法?

ここまでの話を見てると、 「文字列はコードポイントを並べて表現するのかな」 と考えられますが、実際はいくつかの方法があって、UTF-8やUTF-16などがあります。 これで大抵はバイト列になって実際にコンピューターが扱う形式になります。 UTF-8とUTF-16での表現はciceroでも見れます。

この符号化の規則があるので任意のバイト列は妥当なutf-8の文字列にならないんですね4。 あとWindowsではUTF-16を使ってるらしいです。

フォント

で、ここまでの話ではフォントは全く出てきてません。 フォントは簡単には、コードポイントと見た目の組のセットです。

フォントはフォントでいろんな分類や特性があって全然把握しきれていませんが、 実際に扱うファイル形式としては5.otf.ttfが多くて、 一部のフォントは文字列でフォントの見た目を変えることができます(🤯)。

Unicodeのときと同様にとりあえずフォントやその中身を眺めてみたいものです。 先程Unicodeコードポイントの情報を得るのに用いたciceroではシステムにインストールされたフォントのグリフを表示してくれます。 Google Fontsも有名ですね。 フォントファイル自体をいじりたくなったらFont Forgeが一番有名だとおもいます。

個人的に複数のフォントをブラウジングするのにおすすめなのはfont-managerです。 フォントに入っているグリフの一覧が見れるのが便利なところです。 フォントのライセンスやウェイトなどの属性も見れます。

font-managerでUnifontのcharacter一覧を見てる

ターミナルで使うフォント

フォントについてざっくりと書きました。 で、本題(?)6の主にターミナルで使うフォントの話です。

まずターミナル用やコーディング用のフォントとはどういうものなのかということですが、 以下のような特徴が挙げられると思います。

  • monospace(等幅)7
  • 視認性が高い
  • 私用領域に記号が充実してる

最後の特徴はNerd Fontsで説明します。 そしてこのような要件を満たすフォントはたくさん作られてるわけですが8、 残念ながら日本語のグリフは収録されてないことがほとんどです。 ユーザー数は相対的に少ない上に漢字の数は膨大なので当然のことですが。 それで、日本語に対応したコーディング用フォントを作るには、 日本語フォントとしてASCII文字をデザインするという手もありますが、 一般的には既存の主にASCII用のフォントと別の日本語用フォントを組み合わせて作ることが多いです。 MS Wordのように日本語と英語で別のフォントを用いるという方法もありますが、この方法には、

  1. ターミナルなどが複数フォントの使用に対応してない(Alacrittyなど)
  2. ベースラインや幅がズレてて一体感がない

といった問題があります。 そこで先程でたfont forgeを使って、 日本語フォントとASCIIフォントを多少の調整をしたり、 被ってるところを選択しつつ合成した9フォントを使うことが主流になっています。 このようなフォントとして有名なのは

  • Ricty(古い)
  • Cica
  • Firge
  • PlemolJP
  • HackGen

と言ったあたりでしょうか。 これらのフォントは元となった2つのフォント名を組み合わせて作られてることが多くて わかりやすさと個性が出てると思います。

Nerd Fonts

Unicodeの私用面を使うことで、自由に10文字を追加することができます。 ここにコーディングなどであると便利なアイコンを登録することで、 ターミナルなどでの表現をリッチにするものが Nerd Fonts です。 以下の画像のような文字が追加されます。

Nerd Fontsで追加されるグリフの例

ターミナルで実際に使われるとこんな感じです(starshipとezaが使ってます)。

ターミナルでの例(eza)

これらの文字は私用面に含まれるため、通常のフォントとコードポイントの衝突が起こりません。 すなわち、簡単に合成ができるので、 このパッチを行うpythonスクリプトが(察しの通り、Font Forgeを使います)配布されてます。 著名なフォントではこれらの合成が行われたものが多いので、特に設定せずに使えます。

数式 on terminal

Unicodeにはいろんな文字が登録されていますが、 その中でも数式系は異質なものの一つです。 特にラテンアルファベットは複数の書体がコードポイントとして登録されており、 SNSのようなシンプルなテキストがベースの場所では簡易的な文字装飾として使われることがありますね。 そんな数式の文字の中にはかなり変わった文字もあり、 それらをターミナル上で使いたい!11となるとこれから紹介するフォントがおすすめです。

変な文字の例

ベクトルです。 a vec

詳細です。 vec codepoint

たくさんつけられます。

JuliaMono, Juisee

これらの文字は組み合わせて表示されるので、 組み合わせの数は膨大で、普通のフォントでは簡単に表示が崩れます。 これらの組み合わせや様々な書体を、先程並べたコーディングフォントとしての要件を満たすように作られたのが、 JuliaMonoです。 リガチャや前述のStylistic Setsもあるので、見た目を多少いじることもできます。

様々な文字が表示できるというのはロマンがあるので、 このフォントを使いたいところですが、このフォントには重大な問題があります。 それは日本語が収録されていないことです。 しかし、JuliaMonoと日本語フォントを合成したフォント Juiseeが今年の6月にできました🎉。 数々の合成フォントを作ってる方によるフォントで、半角と全角の比も2種類用意されてます。

しかし、このフォントにはnerd fontsのパッチが施されていません。 幸い、このパッチは簡単にできるので、自分はJuiseeのHW(半角と全角の幅が1:2)にNerd Fontsのパッチを当てたものをメインに使ってます。

これがターミナルのフォント設定

リガチャを無効化したり、0のスタイルを変えたりしてます。 VS Codeでも同様の設定をしてます。 Neovimはこんな感じになります。

Neovim with JuiseeHW Nerd Fonts

気に入ってます。

突然ですが…

なんか結構長くなったし、カレンダーに空きがあるし、中身も分けたほうが記事として良さそうなので、 後半は別の日に書きます。

仮まとめ

いろんなフォントを見たりUnicodeをみてみよう! OpenTypeとかの仕様も見てみたいね12


ではまた


  1. UAXはUnicode Standard Annexの略 ↩︎

  2. https://github.com/qwjyh/UCDxml.jl/tree/add_properties はXMLのUCD(Unicode Character Database)をパースしてJuliaに変換するパッケージを作ろうとしたが、 あまりのプロパティの多さで飽きてしまって放棄された残骸。 でかいのでdeps/build.jlで自動で生成するようになってる。 ↩︎

  3. たとえば「ゔ」が「う」と濁点に分解可能なことが書かれてます。 ↩︎

  4. たぶんrustのStringVec<u8>の違いの由来です。Cだとどうなるんでしょうか ↩︎

  5. 後で使うので ↩︎

  6. というより自分の興味のある? ↩︎

  7. つまり文字数と表示の幅が比例してるわけですが、残念ながらプロポーショナルフォントの対義語です(面白い!)。 ↩︎

  8. Termux Styleを入れると代表的なものがついてきます ↩︎

  9. 合成が大変そう!となりますが、Font ForgeはPythonによるスクリプティングも使えるので、 文字の種類にたいして自動で特定の変更を加えるといったことができます。 ↩︎

  10. The Unicord Consortiumに縛られずに ↩︎

  11. JuliaやLeanのときは使います ↩︎

  12. フォントの見た目をソフトウェア側で変えられる仕様とかあります ↩︎