マクロツイーター

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

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

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

PythonTeX というのは、端的にいうと、「LaTeX 文書中で Ruby のプログラムを実行する機能」を提供するパッケージである。すなわち「PerlTeXRuby 版」に相当する。なので、「ちょっと複雑な LaTeX 命令を実装したいが、TeXexpl3LuaPerlLISP 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=utf8pdflatex で置き換える。他のエンジンの場合も同じ。))以下のような出力が得られる。

補足事項。

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

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

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

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