2015/06/28

Re:VIEWで売り物の本を作ってみた(InDesign抜き)

本を作って出版する仕事をしています。 今回、はじめてRe:VIEWを実際の仕事に使ってみたので、忘れないうちに感想とメモを殴り書きしておきます。 ちなみに、作ったのは『エクストリームプログラミング』という本です。

公式サイトのREADMEに「an easy-to-use digital publishing system for books and ebooks」とあるように、 Re:VIEWは日本語の技術書をできるだけ簡単に作るための仕組みです。 テキスト原稿に比較的簡便なマークアップをマニュアルどおりに施し、本全体の構造をYAMLに書けば、それなりに体裁が整った日本語の技術書PDFを編纂してくれます。 同じソースからepubも出せます。InDesignへネイティブに取り込めるような出力もはけるので、テキスト原稿をInDesignに流し込んでバッチ組版とかも可能です。 自分が今回使ったのは、主にpLaTeXを介したPDFの出力機能なので、以降はその話だけします。

「Re:VIEW、わりといいじゃん」と思ったところ

Re:VIEW以外にも、マークアップされたテキスト原稿から書籍PDFを編纂できる仕組みはいくつもあります。 実際、自分も普段はまったく別のツール群を使っています。 Re:VIEWでなければできないことは、特にありません。

Re:VIEWが他のツールに比べて勝っている点は、「それなりに体裁の整った日本語の技術書」がわりと気楽に作れることでしょう。 理由は主に2つあると思います。

とにかくデフォルトの設定だけで、それなりに本の形になる

本の執筆は、ある程度まとまった形になって人に見せられる段階になるまで、どうしても孤独な集中力が要求される作業です。 そんなときに進捗をあきらめないための方策として有効なのは、「自分が書いた文章が本っぽい形になってるようす」をときどき見てにやにやすることでしょう。

Re:VIEWと似た仕組みを提供するツールとしては、Sphinxもあります。 SphinxもRe:VIEWも、原稿を執筆するだけで継続的インテグレーションの開始まで一瞬でもっていけるという点について、優劣はありません。 ただし、そこから実際に本として作り込んでいくところで、かなり使い勝手が変わると思います。 作り込みには、それぞれPythonなりRubyなりを必然的に使うことになるので、そのへんの好みにもよるでしょう。

これは完全に主観ですが、日本語の技術書を書いてみたい、拡張とかいっさい興味ない、という場合、Re:VIEWはよい選択肢です。 まっさらなつるしの状態でツールを使って日本語の技術書らしい体裁を得るなら、いまのところRe:VIEWがいちばん簡単な手段に思えます。 技術書界のRuby on Railsと呼んでもいいかもしれません。

マークアップが妥当

エディタでテキストを編集しているときの見た目は、そのテキストから生成される本のレイアウトに期待するものだと助かります。 InDesignのようなWISIWYGは不要というか邪魔ですが、マークアップとその出力結果には、なるべく自然な対応がついていてほしい。 太字にするつもりだったところが数式として扱われるとか、意図しないところに空白が発生するとか、そういうのは困ります。 Re:VIEWのマークアップとその処理系には、好き嫌いは別にして、そのような問題はあまりありません。

また、どうしても視界にまぎれてくるタグやインデントは、なるべく気が散らない見た目で、なおかつ本文とは違う性質の要素であることが明確にわかるものであってほしい。 この要求をいちばんうまく実装しているマークアップは、たぶんMarkdownでしょう。 しかしMarkdownそのものにはマークアップを拡張するための標準的な仕組みがなく、拡張はすなわち新しい方言の創造を意味します。 これは地獄です。その点、Re:VIEWには、好き嫌いは別にして、標準的なマークアップ拡張の仕組みがあります。

テキスト原稿に対するマークアップに何を選択するかは、宗教化しているかもしれないので断言しにくいのですが、 日本語の技術書を執筆するという目的がはっきりしているならRe:VIEWが採用しているマークアップは妥当だと思いました。

Re:VIEWで商業出版の本を作る

ここから先は、デフォルトのRe:VIEWで作れるPDFでは気が済まない人向けの雑多な話です。 Re:VIEWのバージョンは1.5.0を想定しています。

本の全体構造をいじりたい

本の背骨となる構造はcatalog.ymlというYAMLファイルで与えることになっています。 部や章のような本の中身となるコンテンツは、前づけや本文や付録などのグループに分けてここに並べます。

ただし、目次や索引のような、自分で書くわけでもないしRe:VIEWで生成するわけでもないコンテンツはcatalog.ymlには並べられません。 これらはすべてデフォルトの位置に挿入されてしまいます。 この挙動を変えるには、テンプレート(layouts/layout.tex.erb)の修正が必要です。

局所的に必要になる独自の構造

書籍では、「序文」の末尾に執筆者の署名と日付を入れることがよくあります。 Re:VIEWには、「段落を右寄せにする環境」がデフォルトであるので、同人誌などではこれを使うことで署名をそれっぽい仕上がりにできるでしょう。 しかし商業出版だと、出版社ごとにハウスルールが決まっていたりするので、右寄せにすればいいというわけにもいきません (そもそも、文章の構造の一部になってる要素に対してレイアウトだけ指定して済ませるというのは、あまりお勧めできない)。

このような、局所的な独自構造が必要な場合、自分で新しいマークアップの構文とその挙動を出力形式ごとに定義できます。 新しいインライン要素やブロック要素と、それらのレンダリングの動作を定義するには、 トップディレクトリにreview-ext.rbというファイルを用意し、その中でReVIEWモジュールのLATEXBuilderクラスやHTMLBuilderクラスに追加のメソッドを定義します。

たとえば、署名のための構文をこんなふうに書けるようにしようと考えたとします。

@<signature>{2015年7月|鹿野桂一}

このインライン要素(意味的にはブロック要素にすべきなんだろうけど)に対する処理は、こんな感じに定義すればいいでしょう (LaTeXの\signatureコマンドやCSSのdiv.signatureの定義はそれぞれ別に必要です)。

ReVIEW::Compiler.definline :signature

...(中略)

module ReVIEW
  class LATEXBuilder
    def inline_signature(name_author)
      "\\signature{%s}{}{%s}{}" % name_author.split(/\|/)
    end
  end
  class HTMLBuilder
    def inline_signature(name_author)
      "<div class=\"signature\" sigdate=\"%s\">%s</div>" \
        % name_author.split(/\|/)
    end
  end
end

なお、Re:VIEWにはLaTeXを経由してPDFを作るときに標準的に使える索引のためのマークアップがありません(InDesign用ならあるようです)。 そのため、たとえばmendexを使って索引が作りたかったら、LaTeXの\indexコマンドにマッピングされるような独自のマークアップをreview-ext.rbで同じように定義し、 layouts/layout.tex.erbに手を入れて\printindexを読み込むようにする必要があります。

このへん、公式のドキュメントがほとんどないので辛いのですが、がんばろう。

メタ情報

ドキュメントに埋め込みたいメタ情報(タイトル、著者名など)は、YAMLファイルに記述しておいて、それをreview-pdfmakerの実行時に指定します。 このYAMLには、標準で用意されているキー・値のペア以外にも、好きなキーと好きな値のペアを記述してよいようです。 たとえば奥付に初刷の情報だけでなく最新刷の情報も出力したい場合には、

date:    平成27年6月25日 # これは標準で用意されているキーと値
...(中略)
latestd: 平成27年7月1日  # これらは標準にはない
latestp: 第1版第2刷

のようなキーと値のペアをYAMLに書いておいて、これらをlayouts/layout.tex.erbで使えばよいでしょう。

レイアウト

二倍長ダッシュのような記号が必要な場合、デフォルトではサポートされていないので、やはりreview-ext.rbに独自マークアップとして定義するしかなさそうです。 ただし、少なくともバージョン1.5.0にはインラインの要素を入れ子にできないという問題があるため、この方法だと他のマークアップの中で二倍長ダッシュを使うことはできません。 次期バージョンでは入れ子のインライン要素に対応するらしいので期待しましょう。

一般に、レイアウトに対する特別な要求はLaTeXやCSSの側で解決することになるはずです。 裏を返せば、Re:VIEWで簡単に本が作れるとはいっても、見た目をよりよくしようと思ったらLaTeXやCSSをがんばるしかないという話です。

デフォルトで生成されるLaTeXソースの問題

LaTeXのhyperrefパッケージをincludeしている場所が、ユーザの独自スタイルファイルがincludeされる場所より前にあるので、自分のスタイルファイルで定義した\chapterがうまく動作しない、といった可能性があります。 また、デフォルトでgeometryパッケージが使われています。 いずれもlayouts/layout.tex.erbを編集することで回避できます。

オーバーライドできないマークアップ

ほとんどの定義済みマークアップはreview-ext.rbでオーバーライドできるのですが、たとえば章見出しのための行頭「=」は再定義ができません。 そのため、章扉と目次や柱とで見出しを変更したい場合(つまり\chapter[foo]{bar}したい場合)、上記のような通常の拡張方法が使えません。 LATEXBuilderのheadlineメソッドを全面的に修正するくらいしか方法が思いつきませんでした。

Re:VIEWは商業出版のデファクトになるか

というわけでRe:VIEWで商業出版は、中の人が中にいる特別なプロダクションさんでなくても、ソースを見ながらLaTeXをがんばれば割と可能です。 とはいえ、「じゃあおまえこれからはRe:VIEWで売り物の本を毎回作るつもり?」と言われたら、たぶんそんなことはないです。

そもそも、書籍っていうのはわりと「一点もの」な性格の商品なので、「その本で独自に必要とされるセマンティクスのための構文と表現を考える」という作業は商業出版だとどうしてもくっついてくるものだと思っています(異論がある人はどこかでビールでも)。 で、その作業がRe:VIEWでやりやすいかといったら特別そういうわけではないし、そういうのはむしろXMLのお家芸だったりします。かといって山括弧を手書きしないと原稿が書けないような執筆環境はありえないし、痛し痒しですね。え、LaTeX?

手に入れた原稿(翻訳なら原書)のソース形式を最大限に生かす方向で今後もがんばります。

2015/04/01

昔のTeX環境をDockerのコンテナ化する

大きく進化した日本語TeX環境

新しいLinuxマシンで、とりあえず日本語TeXを使えるようにするまでの時間は、ここ数年で信じられないほど短くなりました。それもこれも、TeX Liveが2010で日本語に完全対応してくれたおかげです。

いまのように「TeX Liveをインストールするだけ」となる以前、Linuxで日本語TeX環境を整備するのは、ほとんど腫物に障るようなものでした。 ディストリビューションの各種パッケージから必要なものを適切な順番にインストール、フォントの実体ファイルへのシンボリックリンクをTEXMF以下に作成、mktexlsrを実行、otfパッケージを手動でインストール、mktexlsrを実行、dvipdfmxの設定ファイル群を編集、mktexlsrを実行。 なんとかインストールを終えてplatexを実行し、dvipdfmxにかけると、なぜかPDFのしおりが文字化けしてしまい、よくよく調べてみると上流で日本語EUC用のCMapファイルが勝手に消されている! あのころのdvipdfmxはいろいろとひどかったのですが、日本語でPDFを作るときの現実的な選択肢がほかにはなかったのです。

ところが2000年代後半になると、日本語TeX環境が思い出したように進化を再開します。具体的には、e拡張やUTF-8に対応したエンジンが登場してきました。 dvipdfmの亜種のような扱いを受けながら鬼子となっていたdvipdfmxも、XeTeXで見直されたおかげか、まっとうなDVIウェアとして主要パッケージでネイティブ対応されるようになりました。 おかげで不可解なバッドノウハウの数々がずいぶん不必要になったはずです。

過去の環境で作ったドキュメントが負債に

しかし前述したように、いったんうまく動くようになった日本語TeX環境に手を入れるのは、とくに業務で使っているとなかなか勇気がいることでした。 必然的に、更新をさぼります。その結果、古い環境で作られたドキュメントがどんどんたまっていきます。 さすがに、e拡張なしではtikzが満足に使えなかったり、UTF-8でない原稿をバージョン管理するのはつらかったりで、いまでは現代的な日本語TeX環境に移行したのですが、そうなると今度は過去のドキュメントが負債としてのしかかってきます。 過去のTeX環境で作ったドキュメントを当時と同じ見た目に再現しなければいけない場合、どうしても当時のマシン環境が必要です。 過去の環境を仮想マシンとしてそのまま残して凌いできたものの、ディスクイメージだけで100G近くあるので、管理コストがバカになりません。 作業としても、ドキュメントを編集するだけなのにOSをまるごとブートするというのは、どう考えても面倒くさい。

過去の環境をDockerコンテナ化

そこで、過去のマシンと同じ環境をDockerのコンテナとして作成することにしました。 古いドキュメントの編集が必要なときには、この古い日本語TeX環境を閉じ込めたコンテナ内でPDFを作るようにすればよかろう、というわけです。

いろいろなドキュメントに応じて必要となるパッケージはDockerfileを使ってそのつどインストールすることにすれば、コンテナ自体は最小の構成にしておけます。 コンテナ化したいのはあくまでもTeX環境だけなので、仮想マシンと違って実体フォントをインストールする必要がないっていうのも利点です。

Debian Lennyをベースとした日本語TeX環境コンテナ化の手順

Dockerのマニュアルによれば、ルートファイルシステムのtarアーカイブに対して docker import を実行すれば、コンテナ(の基になるイメージ)が生成できるとのことです。

自分が必要とする Debian Lenny のルートファイルシステムを、ふつうのディレクトリ(以下の例では ./lenny4debootstrap/)に取ってくるには、以下のように debootstrap コマンドを使います。ちなみに、この作業をしているのは jessie/sid 上です。

$ sudo debootstrap lenny ./lenny4debootstrap http://archive.debian.org/debian/

取ってきたルートファイルシステムを tar で固めて、docker import します。

$ sudo tar -C lenny4debootstrap -c . | sudo docker import - lenny

これで、lennyという名前のDockerイメージができました。 このイメージを docker run すれば、Dockerコンテナができて、その中で好きなことができます。 とりあえず、お約束のバージョン確認。

$ sudo docker run lenny cat /etc/debian_version
5.0.10

上記の cat /etc/debian_version の部分に /bin/bash とかを指定すれば、コンテナ内で好きなシェルが立ち上がります。 しかし仮想コンソールがない状態で起動してしまうので、これだけだとコンテナ内で起動してるシェルからコマンドを入力できません。 仮想コンソールを有効にするには、docker run-t オプションを付けます。

さらに、これだけではコンテナ内で実行したコマンドの結果が標準入力にリダイレクトされず、コンテナ内のシェルから対話的なことが何もできません。 これを有効にするためには -i オプションが必要です。

というわけで、コンテナ内でシェルを実行してコマンドを実行するには、こんなふうにします。

$ sudo docker run -i -t lenny /bin/bash
e606e97b3187:/# ls
bin  boot  dev  etc  home  lib  media  mnt  opt  proc  root  sbin  selinux  srv  sys  tmp  usr  var
e606e97b3187:/# exit
$ 

コンテナ内のシェルのプロンプト e606e97b3187:/# に表示されている12桁の16進数は、コンテナのIDです。 以下のコマンドで最近実行したコンテナのIDが表示できますが、確かに上記と同じ文字列になっているのが分かります。

$ sudo docker ps -l
ONTAINER ID   IMAGE  COMMAND      CREATED        STATUS        PORTS  NAMES
e606e97b3187  lenny  "/bin/bash"  2 minutes ago  Up 2 minutes         romantic_poincare

さて、これでコンテナ内のシェルから apt-get install ptex-base とかできれば話は簡単なんですが、archive.debian.org から取ってきた Lenny のルートファイルシステムには apt が入っていません。 /etc/apt/source.listこそありますが、無効なアドレスが入っています。 そこで、まずは apt が使えるようにがんばってください。 たぶん以下を個別にDebianのアーカイブから取ってきて、dpkg -i で入れればよいはずです。

apt_0.7.20.2+lenny2_i386.deb
coreutils_6.10-6_i386.deb
debian-archive-keyring_2010.08.28~lenny1_all.deb
gcc-4.3-base_4.3.2-1.1_i386.deb
gnupg_1.4.9-3+lenny1_i386.deb
gpgv_1.4.9-3+lenny1_i386.deb
libacl1_2.2.47-2_i386.deb
libattr1_2.4.43-2_i386.deb
libbz2-1.0_1.0.5-1+lenny1_i386.deb
libc-bin_2.11.3-4_i386.deb
libc6_2.11.3-4_i386.deb
libc6_2.7-18lenny7_i386.deb
libgcc1_4.3.2-1.1_i386.deb
liblocale-gettext-perl_1.05-4_i386.deb
libncurses5_5.7+20081213-1_i386.deb
libreadline5_5.2-3.1_i386.deb
libselinux1_2.0.65-5_i386.deb
libstdc++6_4.3.2-1.1_i386.deb
libusb-0.1-4_0.1.12-13_i386.deb
lzma_4.43-14_i386.deb
readline-common_5.2-3.1_all.deb
zlib1g_1.2.3.3.dfsg-12_i386.deb

もちろんコンテナ内には wget もないので、ホストOSで取ってきた .deb をルートファイルシステムに配置して docker import するか、以下のようにdocker run-v オプションを付けて .deb のあるディレクトリをマウントします。

$ sudo docker run -t -i -v /home/k16/temp/debs:/root/temp lenny /bin/bash
1be08b199276:/# cd root/temp
1be08b199276:/# dpkg -i ...

source.listはこれ。

1be08b199276:/# cat /etc/apt/sources.list
deb http://archive.debian.org/debian/ lenny main contrib non-free

無事に apt が入ったら、必要な日本語TeX環境を入れましょう。 当時の情報としては、このへんのリンクが参考になると思います。

2015/01/01

2015年賀状

年賀状、なんとか書いた。

%!
<< /PageSize [285 420] >> setpagedevice

/setrandcolor {% def
  /m exch def
  /r1 {m 10 7.8 exp mul rand div} def
  /r2 {m 10 7.3 exp mul rand div} def
  /r3 {m 10 7.2 exp mul rand div} def
  r1 r2 r3 setrgbcolor
} def

/randdirection {rand 8 mod 3 div} def

/f {% def
  /i exch def
  /Legrand findfont
  i 10 add scalefont setfont
  randdirection 105 add rotate
  -100 randdirection 200 mul moveto
  1 1 10 { (2015 ) false charpath pop} for
  gsave
  i 5 div setrandcolor fill
  grestore
  1 1 0.9 setrgbcolor stroke
} def

1 1 100 {% for
  /n exch def
  1.3 setlinewidth
  -100 100 translate
  0 0 moveto
  100 rotate
  20 2 70 {f} for
  showpage 
} for

ごらんのとおりの手抜きコードですが、文字の配置もランダムなので、都合300ページ分をfor分で生成して、見た目がいいのを20枚くらい選ぶという方法をとりました。 おかげで結果はわりとかっこいい。

2014/12/24

TeXの組版で1行ごとに色を変える

テキストからなるドキュメントのページというのは、行の集まりだと考えられます。 では、ページの行ごとに装飾を施すようなことは可能でしょうか? たとえば、本文を行ごとに色分けするようなことは可能でしょうか?

Webページでは、CSSを使って、表の各行の背景色をストライプにするような効果がよく使われています。 しかし、本文を行ごとに色分けするのは、CSSだけではかなり難しそうです。 ブラウザで本文の1行になるコンテンツをどう決めているのか知りませんが、それを制御しようと思ったら、ブラウザの描画処理に介入する方法が必要に思えます。

この事情は (La)TeX でも変わりません。 1行ごとに色を変えるといった処理を実現するには、行とページを組み立てる TeX の仕組みに介入する手立てが必要です。 TeXでは、その手立てが「出力ルーチン(アウトプットルーチン)」という形で提供されています。

ここでは、TeX & LaTeX Advent Calendar 2014 第24日のネタとして、行ストライプ問題を使って出力ルーチンで遊んでみます (第23日は tkz-fct パッケージがアレだった件、明日最終日はZRさんです)。

出力ルーチンとは

ものすごく端折って言うと、TeXは入力ソースを読み込んだら最適な改行位置を計算して各行を作ります。 その各行が溜まってきたら、そこから最適な改ページ位置を計算して1ページを作ります。 各行が溜まったものは「メイン垂直リスト」、そこからTeXが計算して作った1ページは「\box255」と呼ばれます。

しかし、\box255 がそのまま DVI ファイルや PDF ファイルの 1ページにはなるわけではありません。 \box255 を調理して DVI ファイルや PDF ファイルの 1ページにするのが「出力ルーチン」の仕事です。 ページノンブルを振ったり、柱を作ったりする仕事も、実は出力ルーチンで行われています。

この出力ルーチンにおける処理の内容は、ユーザが好きなように定義できます。 その定義では、\box255 をそのまま律儀に使う必要もありません。 たとえば、出力するページに残したい行だけを取り出して残りはメイン垂直リストに戻すことも可能です(改めて \box255 が組み立てられるので、戻した行は次ページ以降の材料として使われる)。 残したい行だけを取り出すときには、\vsplit というプリミティブが使えます。 「\vsplit ボックス to 高さ」のように実行すれば、指定したボックスから指定した高さぶんの行を取り出してきたボックスが手に入ります。

本文をクリスマスっぽいストライプにする

ここまでくれば、本文の行をストライプにする方法が見えてきましたね。 \box255 から \vsplit で1行ずつ取り出して交互に色を付け、それを集めたボックスを作り、そのボックスを出力ページとして吐き出せばよさそうです。

\documentclass[12pt]{article}

\usepackage{lipsum}
\usepackage[usenames,dvipsnames]{xcolor}

\fboxsep=0pt
\newcount\RGF
\RGF=0
\def\XmasStripe#1{
  \ifnum\RGF=0
    \colorbox{red}{\color{ForestGreen}#1}
    \global\RGF=1
  \else
    \colorbox{ForestGreen}{\color{Red}#1}
    \global\RGF=0
  \fi}

\output={ \loop \setbox1=\vsplit255 to\baselineskip \setbox0=\vbox{\copy0\XmasStripe{\copy1}\vskip-\dp1} \ifdim\ht255>0pt \repeat \shipout\box0}
\begin{document} \color{ForestGreen} % 最初の行のため。colorパッケージがおかしい? \lipsum[1-10] \end{document}
\output というのが、ストライプ柄のために定義した出力ルーチンです。 \box255 から \box1 へと1行ずつ取り出して交互に色を付け(\XmasStripe)、それらを次々に連結していった \box0 を作り(各行を連結するときにボックスの深さをつぶすために \vskip-\dp1 している)、最後にその \box0 をページとして吐き出しています。 ページとして吐き出すためのプリミティブは \shipout です。

実行結果はこんな感じ。もちろんドキュメントオプションでフォントサイズを変えても行ごとに色付けされます。スクリーンショットも貼っておきます。

注意

ここに載せたのはおもちゃのプログラムなので、ノンブル付けといった他の処理はすべて無効になってしまいます。 「Underfull/Overfull \vbox」もてんこ盛りです。

解説のほうも、いかにも出力ルーチンが簡単なものっぽい書き方をしてますが、正直なところ、書いている本人もそれほどちゃんとは理解していません。 なにせ、TeX が \box255 としてページを組み立てる処理と非同期に深く連動している処理です。 少なくとも TeX ブックの第14章、第15章を完全に理解している必要があります。 なので、本来はなるべくいじらないほうがいいでしょう。

参考文献

David Salomon "Output Routines: Examples and Techniques. Part I: Introduction and Examples."

2014/12/08

「版管理+自動組版」イベントの雑感

2014年12月6日、「版管理+自動組版」と題した勉強会というかイベントいうか集まりを開きました。 「同じようなことをバラバラにやってる人たちの横のつながりのきっかけが欲しいな」という程度の軽い気持ちで声を上げてみたら、予想以上に興味を持ってくれる人が膨らんで、様々な背景の方から発表に手を上げていただき、当日も会場から次々と質問が飛び交うという、実に活発で刺激的ですごく楽しい集まりになりました。ありがとうございました!

発表内容や概要は、公開されている各スライドや、武藤さんによる素晴らしいまとめを見ていただくとして、ここには個人的な感想文を晒しておこうと思います。参加してないと文脈が分かりづらい内容なのはご了承ください。

発表では、自分のゆるい話のあと、 @amedama こと宮川さんに Grifletという書籍のビルドシステムを紹介していただきました。 出版に継続的インテグレーションを適用するというのは、自分たちでも割と前から取り組んでいたのですが、この間ずっと未解決になっていた課題として、自動組版の環境をプロジェクトごとに固定化したりチーム間で共有したりしたいという要望がありました。 VM を使うとこまでは過去の本の重刷対応なんかでやっているのですが、Dockerのような仮想コンテナが使えることには気づけてませんでした。 それに気づいたのが、実は宮川さんの PyCon 2014 のスライドで、まさかその話をこうして直接聞ける機会がくるとは想像もしていませんでした。 今回の宮川さんの発表では、これを商品として提供するサービスの可能性にまで突っ込まれていて、商用フォント会社とうまい具合にライセンス契約ができれば同人誌の制作をしたいような人にとっても現実的な価格で再販できるのではとか、商業出版をやっている身としてもサービスを享受するという方向で夢が広がる話が伺えました。

商業出版という観点では、清水川さんによるかなり具体的な書籍制作フローの事例紹介がありました。 清水川さんは、執筆者としてドキュメント制作フローを語ったと思うのですが、それは自分たち出版社の人間から見てもなんら特別なものではなく、本作りのフローで必要なことは執筆者にとっても編集者にとっても共通する部分が多いという至極当たり前の事実を追認しました(ただ、スプレッドシートでSIer風にコメントを管理するのはつらいかもw)。

もう一つ追認したのは、上流でうまく回っているソースの版管理と最終的な本との間にギャップというかブラックボックスがあると、改訂版などへの再利用性は極端に低下するという事実です。 最後の最後まで版管理っていうのは、技術的なだけでなく政治的に難しい面もあるので、せめて、内容の編集までは出版社側の人間も reST ソースで完全に終わらせて、あとはレイアウト的な問題しか絶対に直さない、くらいの割り切りが必要かもしれません(レイアウト制作時に見つかった致命的な内容の問題が見つかったら必ずソースにも反映するようにする、といった抜け道は用意しておくとして)。

一方で、再利用性っていうのが「版管理+自動組版」をやりたい人にとって大前提の金科玉条になってもいけないと思いました。 そもそも何をどの程度に再利用可能にしたいのかは最終成果物によって大きく変わるはずで、必然的に、版管理する対象とか粒度、さらには制作システムのフローもまちまちにならざるを得ないでしょう。 で、そういう「共通化しにくさ」っていうのの具体例が、 taison さんの発表に出てきた 3つの事例かもなあと勝手に解釈していました。 taison さんの発表は、「どれも似たようなことをしているのに担保したいことが違って標準化できてない」という話をはじめ、あるある感で胸が痛くいっぱいになりました。

ところで、 taison さんのシステムで XML アプリケーションを固定していないのは、自分の経験としては正解だと感じてます。 DTD や Schema を用意するということは、梯子の下の表現レイヤを限定するということです。 もし、表現レイヤは決め打ちでいいというなら、わざわざ山かっこなんか使わず、人間にやさしい(⊃入力しやすい)マークアップを用意したほうがハッピーでしょう。 しかし、 XML という仕組みそのものには、文法的な一貫性を提供しつつ、ユーザが都合に合わせてマークアップを拡張できるという特徴があります。 表現レイヤを制限せず、なおかつ文法的に破たんしてないマークアップを提供したかったら、整形式であることだけを要求した XML を使うというのは割と理に適っているはずです。

マークアップを拡張することについては、小宮さんからも、拡張によるマークアップの方言化の是非という視点での発表がありました。 たとえば Sphinx でも、ベースとなるマークアップの reST を機能的に拡張するための API があって、それはすごく強力(なにぜPythonのフル機能がマークアップとして利用できるようになる!)なんだけど、それらの拡張が使える環境と使えない環境が生まれてしまう、さてどうしよう、という話だったと思います。 自分の知ってる TeX 界隈も、CTAN というオンラインのライブラリのおかげでマクロやパッケージの管理では比較的楽ができてますが、そもそもエンジンや PDF 生成機能がユーザから透過的とは言えない現状があります。 実際、 宮川さんの発表でも、LaTeX で Noto Sans を使いたかったけど TeX Live のエッジ(にしか入ってない dvipdfmx ですね)が必要で、システム全体を更新するわけにもいかないから、必要な Debian パッケージを入れた Docker コンテナを使ったという話がありました。 そんな風に環境ごとシステムの中の人が管理するという手はあるとはいえ、どうしたってユーザの利便性とか表現レイヤの自由度は下がるわけで、痛し痒しな気もします。

ひょっとすると、表現レイヤの自由度をあまり捨てずにマークアップの拡張による方言化を吸収できるかもしれない、そんな自動組版の最終兵器が、村上さんのプレゼンで紹介された CSS 組版なのかもしれません。 そこまで期待していいのかっていう内省もないではないんですが、技術的には夢の最終兵器としての可能性は間違いなく持ってるし、末端のユーザが実用できる日も遠くはない気がしています(実際、アンテナハウスの実装をはじめ、ちゃんと動いているものはあるわけで)。 むしろ心配なのは、 Web の世界では直接必要とされていない技術なので、ブラウザというプラットフォームで継続的に仕様と実装の開発が進むかどうかです。 TeX ユーザの集い2014 でも川端さんによるルビの標準化の話がありましたが、あれもお金がネックになって次の一手が出ないようだし、Web という巨大産業はどうやらそういう世界のようです。 そういう意味で、必要なのは銀の弾丸よりも金の弾丸なのでしょう……。 自動組版界隈、あんまりお金なさそうだし、どんな形で自分たちが利用できるようになるのかを含めて CSS 組版を盛り上げていくのに協力できればなと感じました。

最後の発表では、ここまで自動組版っぽい話題が多かったなかで、「同一性とは何か」まで考えさせられる版管理系のネタ を力武さんにぶつけていただきました。 図表の差分とれないのつらい、みたいな感想しか持ってなかったので、そもそも図表みたいなものの差分を取りたいのかという問題提起に付いてくだけで精一杯でしたが、 「差分を取るだけでなく、差分に意味を与えて差分をメンテナンスしてくのが編集という営みだろう(意訳)」という話が個人的には刺さりました。 git rebase -i に相当することができない版管理ツールを使うのはやめようと思いました(小並感)。

図表の差分の話もさることながら、 MS Word の原稿をどう比較するかという話への会場からの食いつきがよかったのが意外でした。 あんまり実体をしらないので、表面的な差分をとるだけならツールもけっこうあるし難しくない気がしてたんですが、そうでもないんですね……。 正直なところ、Word に限らず、閉じた世界でならものすごい利便性を提供するツールって、そこに身を投げれば版管理+自動組版が完全に解決するような錯覚に陥ることがあります。 図表の版管理にしても、閉じた世界で便利な解決策を提供しているツールがありそうなものなので、この辺りは寡聞にして知らない系の話というだけかも。

会の終了後は、主催者が参加できないことから公式の懇親会は企画しなかったのですが、一部の野良懇親会で濃い話が続いたりもしたようで、横のつながりの一助としても多少は機能できたっぽくてよかったです。 こういう特殊な軸で人が集まるのはとても面白いということがわかったので、同じ形になるかどうかはわかりませんが、また何かできればと思っています。

2014/12/02

LaTeX で git のメタ情報を使うパッケージ

2014年現在、「自動組版のためのPDF生成器である」と豪語できるツールは、どうやらまだまだ (La)TeX だけという状況っぽいです(異論は認める宗教戦争前夜)。 しかし、自動組版に使えると豪語するからには、 git のメタデータくらいは気軽に出力できないと困ります。にもかかわらず、どうも CATN にはこれといった便利パッケージが見当たらない†1。その愚痴を TeX & LaTeX Advent Calendar 2014 の2日目の記事としてぶつけます。(1日は ZR さん、明日3日は doraTeX さんです。大物に挟まれてつらい)

ところで、今週末の12/6(土)は、自動組版とバージョン管理の可能性を模索しようという「版管理+自動組版」という集まりがあります。 ものすごく楽しみです。 閑話休題。

さっそくですが、 git のメタ情報を (La)TeX のドキュメント中で利用するためのパッケージとしては、 gitinfo2vc といったものがあるようです。 いずれも、たとえば自分のドキュメントに git のコミットハッシュの文字列を含めたかったら、\gitHash(gitinfo2) とか \GITHash(vc)といった引数なしのコマンドを自分のドキュメントの中で指定して使う仕組みです。分かりやすいですね。

しかし、ここで厄介なのが、これらのパッケージのインストールと設定です。 いずれも TeX Live 2014 に入っているので、プリアンブルで \usepackage するだけで使えると実にうれしいのですが、残念なことにそんな安直な使い方をさせてくれません。事前に外部のスクリプトを自分で設定する必要があります。

vc パッケージの場合は、毎回ドキュメントをコンパイルする前に vc-git.awk というスクリプトを実行し、vc.tex というメタ情報が入ったファイルを生成して、このファイルをドキュメントから \include するという仕組みになっています。 なので、このスクリプトを手動で実行したり、 Makefile に記述しておいたり、 \write18 を使って vc-git.awk をドキュメントのコンパイル時に実行したりする必要があります。公式のドキュメントで説明されているのは \write18 を使う方法です。

gitinfo2 のほうは、 git に特化しているだけあって少しだけ先進的で、 git のフックスクリプトの機能を利用する仕組みになっています。 具体的には、

  • 特定のファイルに git log HEAD を出力するだけのコマンドシェルスクリプトを、ユーザが自分の .git/hooks ディレクトリに設置する
  • その特定のファイルをドキュメント中で \input で読み込んでおく
という具合です。 でもこれだと、GitHub をポーリングして CI を回している環境ではちょっと使いにくい(コミットフックで出力される特定のファイルをバージョン管理化におけばいいのですが、なんかいやだ)。

仕方がないので、自分ではこれらのパッケージを使っていません。 代わりに、 git のコミットハッシュを \write18 で取得するだけという、超低機能な自前コマンドを使っています。 これをプリアンブルに仕込んでおけば、 git の短縮版コミットハッシュの文字列が \gitRevision という引数なしのコマンドで得られます。

\immediate\write18{git show HEAD --pretty="\@percentchar h" -s > revision.tmp}
\def\gitRevision{\input{revision.tmp}}

さらに、みようみまねで buildinfo.sty という LaTeX2e 用のパッケージにしてみました。

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{buildinfo}[2014/12/06 provides git hash as a command]
\RequirePackage{etoolbox}
\RequirePackage{kvoptions}
\SetupKeyvalOptions{family=buildinfo, prefix=buildinfo@}
\DeclareBoolOption{long}
\ProcessKeyvalOptions*
\immediate\write18{date +\@percentchar c  > build.tmp}
\ifbool{buildinfo@long}
  {\immediate\write18{git show HEAD --pretty="\@percentchar H" -s > revision.tmp}}
  {\immediate\write18{git show HEAD --pretty="\@percentchar h" -s > revision.tmp}}
\newcommand{\buildDate}{\input{build.tmp}}
\newcommand{\gitRevision}{\input{revision.tmp}}

\usepackage{buildinfo} すれば、 短縮版のコミットハッシュ文字列に展開される \gitRevision コマンド(\usepackage[long]{buildinfo} とすれば40文字になる)と、 コマンド実行時の日時の文字列に展開される \buildDate コマンドが使えるようになります。


†1 思い返せば、Subversionを使っていたころにも、 svninfo というパッケージでファイル単位でしかメタ情報を扱えないことに苦慮していたことがありました。(いまや完全に git に移行したので、この問題は個人的には原理的になくなりましたが。)

2014/11/10

TeXユーザの集い2014でしたTUG2014の話

プレゼン資料だけだとあまりに情報量がなさそうなので、発表の準備のときに用意していた原稿も下の方に張り付けておきます。未編集です。



自己紹介
======
こんにちは、鹿野です。ふだんは神田の技術系出版社で書籍の企画をしたり編集をしたりしています。
むかしは半分趣味でTeXマクロを書いて遊んだりもしていましが、最近はもっぱら仕事上のおつきあいという感じです。
その仕事では、バージョン管理している原稿から印刷所に入稿するPDFを自動組版するのに、pLaTeXを使っています。

今日は、TUGのアニュアル・ミーティングという、この「TeXユーザの集い」のワールドワイド版みたいなものに参加してきた話をしたいと思います。
今年の集いは、ライトニングトークまで含めて、ものすごく濃厚な内容になっていますが、私の発表は技術的な内容は薄い、文字通りの体験記なので、気楽に聞いていただければ幸いです。

TUGについて
======
まず、そもそもTUGって何、という話から入ろうと思います。
TeXのユーザー会は、実は世界のいろいろな地方ごとにあって、その北米版が「ユーザーに「s」がつくほうのTeX Users Group」で、その略称がTUGです。
ちなみに、日本はこのオフィシャルなTeXのユーザー会がないんですよねー
今回の「集い」で事前に日本のTeXユーザーの組織化に関するアンケートがあったと思うんですが、このTeXユーザーグループに名を連ねようという布石なのかもですね。
いや、知らないんですが。

で、北米版のTeXのユーザー会であるTUGが、全世界のTeXユーザーグループでもあるという形になっています
ので、TUGの会員には、北米在住でなくても、年会費を払えば地球のだれでもなれます。わたしも一応TUGの会員に「個人で」なっています。年会費は$105です。
この年会費は、みなさんご存知のCTANの運用にも使われているらしいので、仕事とかでTeXを使っているので還元したい方は会員になってみるとよいかもしれません。

TUGboat
======
TUGの会員になると、TUGboatという雑誌が送られてきます。年に3回です。
これの編集と発行もTUGのお仕事です。
まあ、1年たつとすべての記事がオンラインで誰でも読めるようになるので、TUGboatを読みたいだけならば、会員になったりしなくても大丈夫です。

TUG年次総会
======
で、ここからだんだん本題になるんですが、TUGのもっとも大きな役割としてあるのが、世界中のTeXユーザーの交流の場となる、年に一回のイベントの主催です。
去年は、この中で参加した方も多いと思うのですが、東京で開催されました。通算、第34回だったんですが、日本では初めての開催だったということです。
150人くらいの参加者だったそうで、大成功だったようです。
私も、去年ちょこっとかかわらせていただいて、それがすごく楽しかったので、今年もぜひ参加したいと思って参加したのが、アメリカのポートランドで開催された第35回のTUGであるTUG 2014になります。

ポートランドについて
======
ポートランド、あんまり日本人にはなじみがない気もするので、ちょっとだけふれておきたいと思います。
ポートランドは、オレゴン州の北西にあって、オレゴン州でいちばん大きい都市です。
で、私もぜんぜん知らなかったんですが、TUGの本部がある場所なんだそうです。そんなわけで、過去に何回か、ポートランドでTUGが開催されてるみたいですね。

これも知らなかったのですが、ポートランドはバラの街としてしられているらしいです。
あと、自転車の環境がすごく整備されていて、みんな路面電車に自転車をもちこんだりしてるんですね。
街の真ん中にすごく大きな川、ウィラメット川が流れていて、写真にあるような鉄橋をはじめ何本も橋がかかってるんですが、それらにも自転車用の道が整備されていて、びゅんびゅん行きかってました。
自転車って、盗難とかコワイので、治安がよい場所じゃないとあんまり流行らないわけですが、実際、ポートランドはアメリカでも最も治安がいい街のひとつなんだそうです。
なので、まあ日本で夜に出歩くほど気楽というわけじゃないですが、夜になって飲みに繰り出しても、そんなに恐ろしくない町でした。
しかも地ビールの醸造所が何カ所もあるんですね。直営のバーとかもいっぱいあったり、これはもう夜は飲みに行くしかないだろう、という感じで、

ビール
======
しかも、ちょうどTUGの前日まで地ビール祭が開催されてたらしくて、私は間に合わなかったんですが、
前入りしてた黒木さん、去年のTUG2013の実行会長ですが、その黒木さんは、この地ビール祭であびるほどビールを飲んでたらしいです。
私のほうは、発表にも申し込んでいたので、飛行機の中とかで必死に発表の練習をしてたわけですが、その間にすっかりポートランド観光してたと。
この写真も、そんな黒木さんが私が到着する前に見つけてくれていたスーパーのビール売り場の様子です。
この一角だけでもこれだけの銘柄の地ビールが並んでいて、それでちゃんと経営が成り立ってるわけですね。
こう、アメリカっていうと、大量消費・車社会・治安も悪い、みたいな印象もあったのですが、ポートランドに限って言えば、すごく成熟した素晴らしい町でした。

会議の場所
======
そんなポートランドのダウンタウンの片隅に、マークスペンサーという小さいけれどいい感じのホテルがあって、そこの地下が今年のTUGの会場でした。
この写真の正面が下に続く階段になっていて、その奥の会議室が会場です。

ホテルなので、ほとんどの参加者は、私や黒木さんも含めてそこに滞在もしてたみたいです。
だから、本当に朝から晩まで、会議中もそれ以外の時間も顔を合わせるわけですね。

あと、このマークスペンサーホテルのよいところとして、すぐ近くに世界最大のチェーンじゃない書店があります。
TeXのユーザーの集まりなので、本とか大好きっこばかりが集まってるわけだから、みんな空いた時間にこのパウエルズという本屋さんに遊びにいくわけです。
とにかくすごい大きい本屋なのですが、誘い合わせていったわけでもないのに、ばったりほかの参加者にあったりもしました。

Powell's
======
この写真はパウエルズの店内で撮ったもので、まあ、宣伝です。
弊社で作ってる「マンガでわかる統計学」とかの英訳版がこんなふうに面出しされていて、かなりうれしかったです。
こっちはTeXの本のコーナーで、世界最大でもこれしかなかったので、ちょっとさびしい感じですね。

プレゼンの話(概要)
======
TUGの会議そのものは、一言でいってしまうと、プレゼン大会です。
3日間にわたって、35分ずつ、一日10本くらいのプレゼンがあって、大部分の参加者がすべてを聞いていたと思います。
実際、参加者の半分以上がプレゼンもするという構成です。

プレゼンの内容は、ものすごく自由で、TeXに関係するツールの話もあれば、パッケージの紹介もあれば、TeXでこんなことしてみましたという事例の話もあります。
いろんなツールやパッケージの開発者もいるので、こういうこと考えてよとか、そういう話もありました。
全部のプレゼンについて一つずつ説明していくのは時間的にも能力的にも無理なので、詳細はTUGのWebや、最初に紹介したジャーナルのTUGboatでチェックしてみてください。
プレゼンターが直接書いた記事があるものもあるし、TUG 2014全体の要約記事なんかもあります。
もし気になったのがあったら、聞いてもらえれば、ひょっとしたら「こんな話だったよ」と言えるかもしれません。

なので、いくつか個人的に気になったプレゼンをピックアップしてみたいと思います。

Astonishing
======
まずはなんといっても、JSBoxです。
これ、名前から何なのかまったく想像できないんですが、TeXのCによる再実装です。
WEB2Cのアウトプットを書き換えたとか、そんなちゃちなものじゃなくて、ゼロからこのダグ先生がCで書き直して、トリップテストも機能的にはパスさせてしまったというやつです。
ダグ先生の会社は、数学チックで再帰的な図案のデザインとかMacのコンサルとかやってるらしくて、
なんでCなんだよ、っていうのが個人的な感想ですが、それはまあおいといて、すごいですね。
内部的には21ビットのUnicodeで、それ向けにオリジナルTeXのアルゴリズムやデータ構造を全部再実装したらしいです。エンコーディングにはUTF-8を採用と言ってました。
OpenTypeフォントがなんでも使えるといってるので、そのまま日本語も使えるといいよねーという感じなんですが、TeXのcatcodeを勝手に拡張しちゃっていて、
catcode 16を名前空間のセパレータ用として予約しちゃっているんですね。なのでptex 向けのマクロやスタイルは全滅かもしれません。
「今度のTeX Liveにいれよう」みたいになってたので、そのうち使えるようになったら試してみたいですね。

もうひとつ会場を沸かしてたのは、カベーさんの発表です。
GUIでパラメータが設定できるようになっていて、そこの数値をスライダーとかで動かすだけでLaTeXのページ版面とか簡単に設定してしまうのをデモされてました。
いろいろなパッケージを内部で階層的に管理している部分がポイントらしくて、原理的には、なるほどねーという感じなんですが、実際デモを見るとすげーっていう感じでした。

Interesting
======
個人的に興味をもって聞いてたのは、TeXと、印刷用じゃない出力との関係についてのプレゼンでした。

日本だと割とすぐにEPUBとかに走っちゃう印象があるんですが

たとえばPDFのリフロー対応とか、
これ、たとえばdvipdfmxで作ったpdfでもAcrobatでタグ付きPDFとかに変換すると、Adobeリーダーでもちゃんとリフローが機能するPDFになったりするんですが、
pdftexが生成するpdfではスペースの出力がまずくて、全部の単語がくっついちゃってたらしいんですね。それを解消しました、みたいな発表があったり、

まあ、やっぱりほとんどAdobeのリーダー専用なんですが、PDFのアノテーションとかレイヤとかをTeXからもっと使おうぜとか、

あとは、LaTeXの原稿からWebブラウザで「読める」出力を得る方法を模索している話とかもありました。
たとえは、この写真のビルさんは、統計の先生なんですが、XMLと対応できるLaTeXの部分集合みたいなのを定義して、それをここ何年か開発しているとのことなのですが、
その中で数式をMathMLのサブセットとCSSでここまでブラウザ上で再現しました!という発表をされていたり、
これはまた別の人なんですが、アメリカ・インスティチュート・マスマティクスのジャーナルのLaTeX原稿をHTMLに変換した実例をデモする発表をする人がいたり、
これも単に変換するのではなくて、参考文献とか、クリックすると単なるリンク先に飛ぶのではなくちゃんとJavaScriptのアクションで本文の直後に詳細な情報を表示するようにしないとだめとか、そういう話が面白かったです。

あと、TeXとはまったく関係ない話もぽつぽつあって、
数学の教科書用のXMLアプリケーション、XML用語の「アプリケーション」ですね、これを使ってSAGEにも紙にも対応した教科書を作ってる話とか
Plottyっていうグラフ作成のWebアプリがあるのですが、それの中の人のプレゼンとか、
あと、この写真のおじさん、Wikiを発明したウォード・カニンガムです、この人がゲストスピーカーで、新しいWikiを作っていますという話をしたり、
面白かったのは、みんな、「TeXに関係は?」みたいな質問をされるんですよ。その答えが、どれも、MathJaxで数式を表示してます、でした。
たぶん、数式をWebブラウザとかで表示したい場合は、個人的にはビルさんのアプローチとかのほうが好きなんですが、もうMathJaxになるんだろうなあという思いを強くしました

プレゼン外
======
TUGそのものがプレゼン大会だっていうのは、さっき言ったとおりなんですが、
プレゼンだけなら、わざわざ太平洋を越えていかなくても、あとでスライドとか動画を見るのでもいいわけですよね。
というわけで、最後にプレゼン以外の話です。

去年のTUG 2013でもプレゼン外の雑談が有益だってって、寺田さんがブログに書いてらっしゃいましたが、
実際、TUG 2014もそうで、しかも朝から晩まで一緒の空間にいるので、合宿みたいなノリになってるわけですね。
昼休みや休憩はもとより、朝からホテルのラウンジでコーヒーを飲みながら雑談が始まるわけです。
毎年TUGに参加している人たちって、プレゼンを名目に旧交を深めて観光旅行してるだけなんじゃないかと。
とくにこのパブニートさんは、去年のTUGで仲良くなって、今年もすごく仲良くしてくれて、
ほとんどはTeXに関係ない話だったりもするわけですが、こういう雑談の時間がすごく有意義でした。
ちなみに、このプレゼンで使っている写真は、ほとんどは彼によるものです。使っていい?って聞いたら快諾してくれました。

夜も夜で、ドイツからきているフランク・ミッテルバッハさん、LaTeX2eの開発者で、LaTeXコンパニオンの著者です、このすごい人が、なんか飲みに誘ってくれるわけですね。
で、こんなふうにレストランでメニューを見ながら、これ何やってるのかというと、みんなでメニューの組版にケチをつけてるんですね。

こっちは懇親会の写真なんですが、こっちの二人はインドから来ているTeXニシャンで、この人は黒木さんです。
プレゼントに当選したときの様子です。隣のクリス・ローリーは、LaTeXコンパニオンの第2版の共著者の一人で、この懇親会の直前にビールをおごってくれました。
懇親会の後も、このクリスと、フランク、それから、こっちの奥にうつっているウィル・ロバートソン、fontspecとかの開発者です、それに黒木さんと私とでビールを飲みに行きました。
いま、こうやって話してても、なんて贅沢な時間だったんだろうと、なんか自分なんかがほんと図々しかったのではないかと恐縮に感じてしまいます。

というわけで、いろんなプレゼンを聞いてきた話よりも、こっちのほうが今日、メインに伝えたいことかもしれません。