マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

せっかくだから PythonTeX でナベアツを実装した

TUG 2013 で PythonTeX についての発表があって少し話題になっているようた。

PythonTeX というのは、端的にいうと、「LaTeX 文書中で Ruby のプログラムを実行する機能」を提供するパッケージである。すなわち「PerlTeX の Ruby 版」に相当する。なので、「ちょっと複雑な LaTeX 命令を実装したいが、TeX や expl3 や Lua や Perl や LISP on TeX じゃなくて Ruby を使いたい!」という人は是非とも試すべきであろう。

パッケージ自体は最近の TeX Live 2013 であれば既にインストールされている。ただし、LuaTeX のような「言語処理系を組み込んだ TeX エンジン」ではなく、PerlTeX のように「TeX と言語処理系が連携する」形で動作するので、別途 Ruby のインタプリタがインストールされている必要がある。あと、どうやら Python *1も必要らしい。

というわけで、早速 \NabeAzz 命令を Ruby で実装してみた。

[test-ruby.tex]
% pLaTeX 文書; 文字コードは一応UTF-8
\documentclass[a4paper]{jsarticle}
\usepackage[usefamily=ruby]{pythontex}
\usepackage{type1cm}
\newcommand*{\textFunny}[1]{%
  {\usefont{OT1}{cmfr}{m}{it}\LARGE #1}%
}
\newcommand{\NabeAzz}[1]{%
  \rubyc{nabeazz(#1)}%
}
\begin{rubycode}
def nabeazz(n)
    1.upto(n).each do |i|
        puts((i % 3 == 0 || i.to_s =~ /3/) ? "\\textFunny{#{i}}" : i)
    end
end
\end{rubycode}
\begin{document}
3の倍数と3が付く数字のときだけFunnyになります。
\begin{quote}
  \NabeAzz{40}
\end{quote}
\end{document}

LuaTeX のようなエンジン拡張ではないので、TeX エンジンは好きなものが選べる。なのでここでは敢えて pLaTeX を使った。プレアンブルにおいて

\usepackage[usefamily=ruby]{pythontex}

を実行してパッケージを読み込むと、Ruby を使用するための以下の機能が提供される。

  • \rubyc{} : Ruby のコードを実行する。実行中に標準出力に出力した文字列は TeX 側への入力となる。例えば、\rubyc{puts(40%3)} は 1 と書いたのと同等になる。((LuaTeX の tex.print() と同様の動作となる。ただし「実際に」実行が起こる順序は LuaTeX の場合とは異なるし、恐らくは論理的にも等価ではないはず。))ソースコード中の LaTeX の特殊文字は verbatim に扱われるのが本来の動作だが、標準の \verb 系の命令と同様、他の命令の引数の中では verbatim 性が失われる。(だから、上の例の \NabeAzz の定義では #1 がちゃんと命令引数の意味になる。((かなり微妙な動作であるが、マニュアルにおいて同様の例が挙げられているので、これが正式な仕様と考えていいだろう。なお、\verb と同様の \rubyc|40%3| のような書き方もできる。引数を { } に入れた場合は当然 { } について均衡である必要がある。)))
  • \ruby{} : この場合、ソースコードは単一の(Ruby の)式でなければならず、その式の値(の文字列化)が TeX 側への入力となる。例えば、\ruby{40%3} は 1 と同等になる。引数の verbatim 性は \rubyc 命令と同じ。
  • \begin{rubycode}\end{rubycode} : \rubyc の環境版。環境の内容は(引数内でない限り)verbatim に扱われる。

文書のコンパイルの手順は以下の通りである。((もちろん pTeX エンジンの既定の入力漢字コードが UTF-8 である場合は -kanji=utf8 は不要。))

platex -kanji=utf8 test-ruby
pythontex test-ruby
platex -kanji=utf8 test-ruby

これで test-ruby.dvi が得られる。DVI 文書から PostScript や PDF への変換は通常の文書の場合と変わらない。((もし欧文の pdflatex 用の文書である場合は、手順の platex -kanji=utf8 を pdflatex で置き換える。他のエンジンの場合も同じ。))以下のような出力が得られる。

補足事項。

  • パッケージの既定では、文書の文字コードは UTF-8 であることが想定されている。
  • LaTeX の特殊文字の問題があるので、複雑な Ruby コードは関数(やクラス)にして rubycode 環境の中に置き、「LaTeX コードと混在する箇所」では \rubyc ã‚„ \ruby 命令を使う、という形が書きやすいであろう。
  • 実は Ruby 実行の命令・環境は(プレアンブルでなく)文書本体中でも使用可能である。しかし私は本体中にプログラム言語(TeX だろうが expl3 だろうが Ruby だろうが)を書くのを激しく嫌っているので、上掲の例では「LaTeX 命令を Ruby で実装する」という形をとった。

というわけで、これからの時代は、LaTeX で少々複雑な処理をする場合には、

TeX ではなくて Ruby (とか)を使おうではないか!

*1:Python はスクリプト言語の一種であるらしい。多分、プログラムを書くのに使われるのだろう。