コマンドラインツールでタイトルケース変換したい

日本人にとって馴染みのないものに、タイトルケースがある。 タイトルケースというのは、大文字小文字の使い分け規則のひとつで、 英語圏で新聞や広告の見出しのタイポグラフィなどに使われる。 名詞を中心に単語の先頭文字を大文字に変換するのだが、例えば、"This is a pen.“ を "This is a Pen.” といった風に変換する。 すべてを先頭大文字にするわけでも、すべてを小文字にするわけでもなく、 いい感じにキャピタライズされるので、見た目がサマになる。

このタイトルケースだが、変換規則が標準化されていない。 実質的な標準といわれるものすらなく、書く人によってキャピタライズが変わってくる。 標準化されていないというよりも、もともとそういうラフなケースのようだ。

いい感じにかっこよくなるので、自分は README の見出しに使うことがある。 ただ、どうしても自分で変換していると、明らかに間違うようなこともある。 兼ねてから自動化が必要だと考えていたので、調べてみた。

タイトルケースの生成の多くは、Web サービスにおいてサポートされている。 title case で検索すれば、多くの変換サービスがヒットする。 しかし、Web サービスなのでセキュリティ的な問題もあるし、Web 広告も目に付く。

自分は Atom を常用しているが、初めはこれのプラグインパッケージとして使えるものを探そうとした。 ただし、これの弱点はポータブルでないことである。 SNS などブラウザ上で文章の編集が必要なことが最近は少なくないし、そのうち別のエディタに乗り換えるかもしれない。 非常にプレーンな解決策である、コマンドラインツールを探すことにした。

一番最初に思いついたのは ICU だ。 Unicode の標準化団体が管理する、文字を扱う上では最強のライブラリである。 たしか、タイトルケースに変換する関数も提供されていた。 ICU がライブラリの一部としてコマンドラインツールも提供していると、自分の望みは満たせる。 調べてみると、ICU は確かにタイトルケースへの変換はサポートしていた。 しかし、残念なことにコマンドラインツールを提供していなかった。

次に、node の change-case を調べた。 このライブラリをバインドした Atomプラグインもあるので、共通して使える。 期待したものの、すべてを先頭大文字にするという残念な仕様だった。

$ vi try.js 
const titleCase = require('title-case')

const sample = 'the vitamins are in my fresh california raisins.'
console.log(titleCase(sample))
$ node try.js 
The Vitamins Are In My Fresh California Raisins
// ところで、ピリオドが消えているのはいいのだろうか・・・。

ふと思い立って、ICU でタイトルケース変換するプログラムを書いてみた。

$ vi try.cc 
#include <stdio.h>
#include <unicode/unistr.h>

int main(int argc, char *argv[]) {
  icu::UnicodeString ustr("This is a pen.", "utf8");
  ustr = ustr.toTitle(NULL);
  std::string buf;
  ustr.toUTF8String(buf);
  printf("%s\n", buf.c_str());
}
$ c++ -licuuc try.cc && ./a.out 
This Is A Pen.

あれ、ICU でも同じじゃん・・・。

残念ながら、気の利いたタイトルケース変換を提供するコマンドラインツールは見つからなかったが、一般的なライブラリにおいて、タイトルケースは「全ての単語の先頭文字を大文字に変換」で実装されていることがわかった。