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 で実装してみた。
% 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 で少々複雑な処理をする場合には、