SKKの辞書サーバーとしてyaskkserv2を使うようにしてみた
久々に4連休となったので、たまには頻度高めにブログを書いてみることにします。 今回は、前回SKKにしたということを書きましたが、それの辞書サーバーについて書いてみようと思います。 <!–more–> SKKと辞書サーバー SKKを使ったことがない方は、辞書サーバーといってもなんじゃそりゃ?となるでしょう。辞書サーバーとはそのままの意味で、SKKの辞書を提供するためのサーバープログラムを指します。 SKKの実装では、大抵はSKK辞書をインプットメソッド内にメモリとして展開し、それを利用しています。当然ながら、この形式では複数のインプットメソッドがあったら、各々でメモリを消費してしまいますし、管理が煩雑になりがちです。 そのため、SKKのほとんどの実装では、SKKプロトコルというプロトコルにもとづいたサーバーも辞書の一つとして利用できるようになっています。サーバーとして一つにまとめることで、複数のインプットメソッドから同時に利用することもできる、ということです。 ddskkでの辞書サーバーの設定 辞書サーバー、使う? さて、辞書サーバーを使うといいことあるじゃん・・・と思いたいところですが、実際は中々そうはいきません。なぜかというと、使ってみたり運用してみた限りでは、以下のような問題があります。 SKKプロトコルがEUC-JPを前提としていて、UTF-8全盛の今にそぐわないケースが多い 実際に複数のインプットメソッドから利用すると、以外と面倒くさいケースが多い そもそもメモリが多くなったので、各々で利用しても問題にならないケースが多い 一個ずつ見ていきます。 SKKプロトコルの問題 SKKが開発されたのは1987年、佐藤雅彦氏によって開発されたのが初版とされています。 参考 当然ですが、1987年当時にはUnicode consortiumすらありません。(Wikipedia)なので、日本語を扱える文字コードは、事実上 EUC-JPとShift-JISの2強 でした。Linuxにおいては、EUC-JPがデファクトスタンダードの地位を確立していた(らしい)ので、日本語のかな漢字変換プログラムであるSKKがEUC-JPを前提としていても、何の不思議もありません。 さて、しかし時は経ち、現代ではUTF-8がデファクトスタンダードとなりました。そうなると困るのは、EUC-JPでしか扱えない、というプロトコルの問題です。これはSKKプロトコルの定義を修正しない限りはなんともならないです。事実、macOSで一番使われていると思われるAquaSKKでも、serverとのやりとりはEUC-JPに固定されています(辞書はUTF-8も扱えます)。 なので、辞書がUTF-8だったり、エンコーディングがUTF-8だったりすると、上手く変換できなかったりと、問題が発生しがちです。 複数のインプットメソッドからだとめんどくさい問題 プロトコルの問題でも上げましたが、辞書と辞書サーバーの文字コード、インプットメソッド内での扱いなどが異なる場合がある、などの事情があります。なので、以外とサーバーをそのまま利用できるケース、というのは少なかったりします。 仕事用のmacOSで、AquaSKKとEmacsで共通の辞書サーバーを使おう、と思ったりしましたが、このへんが上手くいかずに挫折したりしています。 そもそもメモリが多くなった 1990年くらいのPCは、メモリがMB単位とかあるとそれだけですげー、ってなった時代でした。今は2桁GBがあたりまえです(個人の感想です)。個人所有しているPCも、32GBとか積んでいます。 片や、SKKの辞書は、他のIMEと比較してもかなり小さいほうだと思います。実際に計測してみたら、SKKが配布している辞書を全部統合した辞書(コンパイル後)で、22MBしかありませんでした。 32 * 1024MB のメモリ空間があるところに、高々数十MBの辞書をメモリに展開したところで、ほとんど影響がないのは明白でしょう・・・。 それでも辞書サーバーを使ってみる 色々問題があるにはある辞書サーバーですが、それでも使ったことがないから使ってみたい、というのは人の性でしょう。ですので使ってみます。 さて、SKKには歴史があるので、当然ながら辞書サーバーも色々な実装があります。ここで挙げるのは蛇足なので、 Wikiへのリンクを貼っておきますので、気になる方はこちらから。 Google IME≒mozcを利用して、候補を取得したりする・・・という変わり種もあったりしますが、そこまで変わり種を使いたいわけでもないので、シンプルな辞書サーバーを選択してみます。 実際、速度の面などを考えると、C/C++で作られたサーバーがいいかな・・・と最初は考えました。 yaskkservは、かなりこなれた実装でもあり、かつGentooでも使えるものです。 が、これもまた歴史のあるツールなので、色々内部構造的な問題がある、ということで、作者の方がRustでリライトした yaskkserv2というのを開発されています。 ちょうどFirefoxとかをビルドしている関係上、Rustがマシンに入っているということもあり、これを使うことにしました。(見切り発車すぎる) yaskkserv2のビルドとか これらは、Emacsの起動時に、対象のプログラムが存在していなければビルドしてインストールするようにしました。ただ、ビルド環境が無い場合は、バイナリを落として展開するようにしています。 (leaf *skk-server :after f :if my:use-skkserver :init (let ((server-program (expand-file-name "yaskkserv2" my:user-local-exec-path)) (dictionary-program (expand-file-name "yaskkserv2_make_dictionary" my:user-local-exec-path))) (cond ((and my:build-skkserver (executable-find "cargo") (not (executable-find server-program)) (not (executable-find dictionary-program))) (let ((base-path "/tmp/yaskkserv2")) (unless (f-exists? base-path) (call-process "git" nil nil t "clone" "https://github.com/wachikun/yaskkserv2" "/tmp/yaskkserv2")) (call-process "cargo" nil nil t "build" "--release" "--manifest-path" (expand-file-name "Cargo.toml" base-path)) (unless (f-exists? server-program) (f-copy (expand-file-name "target/release/yaskkserv2" base-path) server-program)) (unless (f-exists? dictionary-program) (f-copy (expand-file-name "target/release/yaskkserv2_make_dictionary" base-path) dictionary-program)) )) (t (let* ((target (cond ((eq window-system 'ns) "apple-darwin") (t "uknown-linux-gnu"))) (path (format "https://github.com/wachikun/yaskkserv2/releases/download/%s/yaskkserv2-%s-x86_64-%s.tar.gz" my:yaskkserv2-version my:yaskkserv2-version target))) (call-process "curl" nil nil t "-L" path "-o" "/tmp/yaskkserv2.tar.gz") (call-process "tar" nil nil t "-zxvf" "/tmp/yaskkserv2.tar.gz" "-C" my:user-local-exec-path "--strip-components" "1")))))) 辞書のコンパイル時の注意 yaskkserv2は、独自の辞書形式を利用しているため、SKKの辞書はそのまま利用せず、 yaskkserv2_make_dictionary というツールから変換する必要があります。 ...