[2012-06-05編集]記事の内容を書き直した。(参照)
(前回の続き)
verbatim な入力を LaTeX 上で気軽に扱えると、色々なことに応用できる。
verbatim な出力
例えば、verbatim な入力ができると、verbatim な出力ができる。
\documentclass{article} \usepackage{fontspec} % Unicode フォントに切替 \usepackage{bxluavienv,luacode} \begin{luacode*} function verb_output(str) local lines = str:explode("\n") -- 「\r+」「\n+」でなく「\n」 -- 入力文字列を行ごとに分割した上で -- 各行を「\mbox{}\\」区切りで出力する for k = 1, #lines do tex.sprint(-2, lines[k]) -- 第 1 引数に「-2」 if k < #lines then tex.sprint("\\mbox{}\\\\") end end end \end{luacode*} \DeclareVerbInputEnvironment{simpleverbatim}{% \par\noindent \directlua{verb_output(\VIEString{#1})}\par % \VIEString に注意 } \begin{document} \begin{simpleverbatim} #1 discount & service $5.99 {79% off!} \end{simpleverbatim} \end{document}
ここでのポイントは、tex.sprint()
の第 1 引数に「−2」を渡していること。前回、tex.sprint()
で書き出す時に「普通に」(= 現在のカテゴリコードで)トークンが行われると述べたが、「−2」を指定すると、書き出す時も verbatim なままになる。*1
また、Lua 関数に入力文字列を渡す時に、(luacode の)\luastring(N)
でなく \SPEString
を使っている。これは、「先頭が CR(^^M
)だったら除去する」「それ以外の CR を LF(^^J
)に置換する」という変換を行った文字列*2を表す。これを使うと、受け取る Lua 関数ではそれを「普通の複数行テキスト」のように取り扱えて便利である。
※注意: この simpleverbatim 環境は確かに「書いたままの Unicode 文字列」を現在のフォントで出力するのであるが、それが正しく出力されるかは、フォントのエンコーディングに依存する。当然 Unicode フォントならば大丈夫であり、また ASCII 文字に限れば T1 エンコーディングでもよいしまた(等幅 OT1 の)cmtt フォントでもよい。しかし OT1 の cmr フォントでは一部の文字が化ける。この文書では fontspec を読み込んでいるので Unicode フォントが使われている。*3
luacode 環境を自分で作る
中身の文字列が得られているので、それを \directlua
に放り込むだけである。
\documentclass{article} \usepackage{bxluavienv} % luacode 要らないよ % luacode* 環境を自前で作る \DeclareVerbInputEnvironment{myluacode}{% \directlua{#1}}% これでおしまい! % それを使ってみる \begin{myluacode} function do_format(f, v) -- lua-style comment tex.sprint(string.format("%"..f, tonumber(v))) end \end{myluacode} % おっと、\luastringN も必要でした... \newcommand*{\luastringN}[1]{"\luatexluaescapestring{\detokenize{#1}}"} %%<*> \format{XXX}{N} : printf 書式 %XXX で数値 N を出力 \newcommand*{\format}[2]{\directlua{do_format(\luastringN{#1},\luastringN{#2})}} \begin{document} The answer is \format{04X}{66}. \end{document}
普通の LaTeX 環境を普通の命令のように定義する
bxluavienv パッケージには \ParseAsLaTeX
という命令が用意されていて、verbatim に取得した文字列をこの命令に渡すことでもう一度トークン化して(普通の LaTeX のソースとして)実行することができる。これを利用すると、環境をあたかも命令であるかのように定義できて、しかも定義された環境は当然 \verb
を含めるという利点が得られる。
\documentclass{article} % 色を定義する \usepackage{color} \definecolor{mred}{rgb}{0.85,0,0} \definecolor{lpink}{rgb}{1,0.85,0.85} \usepackage{bxluavienv} %%<*> specialbox 環境: 中身を色つきの箱で囲って出力する % \ParseAsLaTeX{#1} は要するに環境の中身を普通に解釈して得られるトークン列。 \DeclareVerbInputEnvironment{specialbox}{% \fcolorbox{mred}{lpink}{\Large\textcolor{mred}{\ParseAsLaTeX{#1}}}} \begin{document} % 用例。意地悪く \verb 入り。 \begin{specialbox} I $\heartsuit$ Lua\TeX! \verb|(^_^;| \end{specialbox} \end{document}
ちなみに、この機能を提供する既存のパッケージとして、environ パッケージ(Will Robertson 氏作製)がある。