どこでも使える\verbとlstlistingができた(LaTeX 確認シリーズ #4)
はじめに
皆様お久しぶりです。KKTeXです。久しくXやQiitaでの投稿をサボっておりました。
今回話題とするKKluaverbの開発やgckanbunの拡張に集中していたのと、学業が少々忙しかったため、ログインする気力が湧きませんでした。
Lua言語を真面目に扱うのがこのパッケージの開発で初めてでありましたので、先生兼同僚兼秘書であるGeminiと格闘する毎日でしたが、何かと新鮮で面白かったです。ちなみに、デバッグは今まで作ってきたどのパッケージよりも大変でした。さすがTeX界のパンドラの箱、\verb様といったところでしょうか。
GOAL
この記事の主人公たるKKluaverbパッケージは、ZRさんのbxrawstrパッケージのエンコード方式を参考に、
「どこでも使える \verb と lstlisting 」を構成する
ということにありました。
完成形は(2月末までにCTANに入れる予定ですが)https://github.com/KKTeX/KKluaverbから入手可能です。
このパッケージを使用すれば以下のような出力が可能となります。
使用方法
使用方法はリポジトリにあるkkluaverb-doc.pdfをご参照いただければ詳述してありますが、ここでは簡単に解説します。
\KKverbコマンド
概要
このコマンドは、既存の\verbコマンドのそれと全く同様です。ただし、\verbより優れている点として、
- 他のコマンドの引数内で使用可能
- 目次・索引にもそのまま入る
- 長い引数を取ったとしても、そのまま改行してくれる
- フォントや色の設定が自由
- Color Preset(後述)機能を使うことで、特定のキーワードやデリミタ内部のテキストだけを自由に色分けすることができる
などが存在します。これらの機能はすべてLuaによる拡張の賜物であるといえ、TeX言語のみでの実装は至難、もしくは原理的に解決不能なレベルのものと言えるでしょう。
コード
使い方としては\verbのように
\KKverb|\def\TEST{Test Text.}|
とするのみです。
ちなみに、このコード内で意図的に改行ないし空行を入れたとしても、それらは完全に無視されます。すなわち
\KKverb|\def\TEST{Test Text.}|
\KKverb|\def\TE
ST{Test Text.}|
\KKverb|\def\TE
ST{Test Text.}|
はすべて同一の出力を得る書き方であり、コンパイルすると
以上の画像のような出力となります1。
オプション
細かいオプションの説明は、リポジトリにあるkkluaverb-doc.pdfをご参照ください。
\KKcodeS/E擬似環境
概要
この(擬似)環境は、lstlistingを場所を問わず使えるように拡張するために作成されたものとなっています。なぜ「擬似」をつけているのかと申し上げますと、TeXにおける"environment"と類似の挙動を、裏でLuaを使用しつつ作成したものであるからです。
コード
この擬似環境は
-
\KKcodeS,\KKcodeEで挟まれた行番号が出力されないもの -
\KKcodeS+,\KKcodeEで挟まれた行番号が出力されるもの
の2種類が用意されています。
\KKcodeS
コード部分
\KKcodeE
のようにして使います。\KKcodeS, \KKcodeEで挟まれており、尚且つこれらの開始点と同じ行に書かれたコードに関しては完全に無視されます。
無視されない\KKcodeS 無視される
コード部分
無視される\KKcodeE 無視されない
といった具合です。
この環境におけるコード部分では、改行・空行・スペースの全てがソースコードそのままに再現されます。従って、余計なインデントを入れてしまった場合、想定外の出力が得られるということに注意してくささい。
出力例を示しておきます。たとえば、Luaのコードを行番号なしで出す場合、
\KKcodeS
-- Alnum Checker
local function is_alnum(char)
if not char then return false end
return char:match("[A-Za-z0-9_]") ~= nil
end
\KKcodeE
のように打ち込みます。
また、\KKcodeSから\KKcodeS+に変更するだけで行番が表示されるようになり、
以上の出力を得ます2。
プリセット作成
概要
さて、本パッケージの強みの1つとして、
ユーザー自身が任意の個数の言語プリセットを作成でき、かつ簡単に切り替えられる
というものがあります。
コード
この設定をする際には、Luaのコードを直接書きに行くことでパッケージの提供するmappingシステムに色やキーワードの情報を渡します。
構文は以下のようになっています。
\begin{luacode*}
KKLuaVerb.presets["<name-of-style>"] = {
map = {
<color1> = { "<token1>", "<token2>",... },
<color2> = { "<token1>", "<token2>",... },
...
},
options = {
word_boundary = true or false,
comment_char = "<comment-token>",
comment_color = "<comment-color>",
escape_char = "<escape-token>",
delimiters = {
{ start = '<starter>', stop = '<ender>', color = "<patial-color>" },
}
}
}
\end{luacode*}
大きく分けて
-
map:キーワードと色を指定する部分 -
options:各種設定
の設定項目があり、optionsの方では -
word_boundary:keywordが別のトークン内で検出された時に色を変えない(true)と変える(false)の指定 -
comment_char:コメントアウトの開始トークンの指定 -
comment_color:コメントの色 -
escape_char:エスケープを開始するトークンの指定 -
delimiters:特定のトークンに挟まれた部分全域を特定の色に変更(その内部のkeywordがあっても無効化できる)する指定
が可能です。
そして、作成したmapは、
\KKvUsePreset{プリセット名}
で呼び出します。プリセットは名前さえ別のものにしておけば幾つでも作成が可能です。同じ文書内で別のプリセットに変更したい場合にもこのコマンドを使用します。
このプリセット登録はプリアンブルで行ってもよいですが、長くなる場合には別のstyファイルを用意してその内部で行うことを推奨します。
使用例
たとえば、TeXのスタイルを作るなら
\begin{luacode*}
KKLuaVerb.presets["TeXStyle"] = {
map = {
DarkCyan = { "{", "}" },
OrangeRed = { "[", "]" },
DeepPink = { "(", ")" },
DarkGoldenrod = { "&", "$", "^", "_"},
CornflowerBlue = {
"\\documentclass", "\\usepackage", "\\begin", "\\end",
"\\section", "\\subsection", "\\chapter",
"\\makeatletter", "\\makeatother", "\\ExplSyntaxOn", "\\ExplSyntaxOff"
},
MediumPurple = {
"\\def", "\\edef", "\\gdef", "\\xdef",
"\\newcommand", "\\renewcommand", "\\providecommand",
"\\let", "\\setcopy", "\\long", "\\global"
},
Magenta = {
"\\if", "\\else", "\\fi", "\\ifx", "\\ifdefined",
"\\ifnum", "\\ifdim", "\\loop", "\\repeat", "\\noexpand"
},
IndianRed = {
"\\KKlvStart*", "\\KKlvEnd*"
}
},
options = {
word_boundary = true,
comment_char = "%",
comment_color = "ForestGreen",
escape_char = "\\",
delimiters = {
{ start = '$', stop = '$', color = "SpringGreen3" },
}
}
}
\end{luacode*}
のようになるでしょう。
Luaなら
\begin{luacode*}
KKLuaVerb.presets["LuaStyle"] = {
map = {
Magenta = {
"if", "then", "else", "elseif", "end",
"for", "while", "repeat", "until", "in",
"do", "break", "return", "function"
},
ProcessBlue = { "local", "true", "false", "nil" },
DarkGoldenrod = {
"print", "require", "type", "tostring", "tonumber",
"table", "string", "math", "io", "os", "debug", "coroutine",
"self"
},
DarkCyan = { "{", "}", "[", "]", "(", ")", "=", "+", "-", "*", "/", "#", "..", "==" }
},
options = {
word_boundary = true,
comment_char = "--",
comment_color = "Cerulean",
escape_char = "%",
delimiters = {
{ start = '"', stop = '"', color = "SkyBlue1" },
}
}
}
\end{luacode*}
のようになるでしょうか。
文字置換
概要
\KKverbの引数や\KKcodeS/E擬似環境内部のテキストに、あらかじめ指定したテキスト置換をかけることも可能です。
コード
たとえば、"!"を"<EXCLAMATION>"へ、"?"を"<QUESTION>"に一括置換したい場合、
\KKvSetMap{!}{<EXCLAMATION>}
\KKvSetMap{?}{〈QUESTION〉}
と書きます。すると、
\KKverb|Wait, you really change them!?|
の出力は
となります。
スペースを視覚化するためにもこの機能を使用することができますが、この場合だけ少し注意が必要です。
置換をセットする場合には
\KKvSetMap{ }{␣}
で問題ありません。しかしながら、リセットする際には
\KKvSpaceForce
という専用のリセッターを使用する必要があります。
これは、本パッケージがインデントや半角スペースをTeXが自動で不可視化してしまわないようにする加工をデフォルトで施しており、それが置換指定によって一度無効化されてしまうことに起因しています。詳しくは実装解説記事に譲りますがこの点についてだけはご留意ください。
たとえば
\KKvSetMap{ }{␣}
\KKverb| Look! All spaces are visualized!! |
\KKvSpaceForce
\KKverb| Oh, spaces are no longer visualized. |
のようにして使用します。
出力は画像のようになります。
終わりに
いかがでしたでしょうか。この記事においては、技術的なことは一切書かず、使用方法のみを紹介する記事とさせていただきました。
自分のTeXに関する記事は今のところ全てLaTeX確認シリーズ3と題しているわけですが、どう見ても「確認」と言えるほど基礎的な内容ではありません。こんなこと知らなくても、TeXでプリントやレポートは書けます。むしろ「実戦講座4」とかの方がしっくりくるように思います。今更変えるかは悩ましいですが。
次の記事では、内部実装の仕組みを解説する内容で書いていこうと思っております。最後までお読みいただきありがとうございました。
-
本画像では後述するプリセット機能を適用した状態でのコンパイルです。何も設定していない場合には着色されないことに注意してください。 ↩
-
本画像でも後述するプリセット機能を適用した状態でのコンパイルです。何も設定していない場合には着色されないことに注意してください。 ↩
-
確認シリーズとは、鉄緑会で高2以上の学年で使用される網羅教材のこと。高3生の多くにとってはバイブル的存在とされ、通年で最も使い込まれる教材の1つ。 ↩
-
実戦講座とは、鉄緑会における数学および英語の講座のうち、高2向けのものを指す。さも当然かの如く東大の過去問を例題に入れてくるため、シンプルに大変。しかしこれを超えないと冬の校内模試(クリ模試)で酷い目に遭うため、実質的にやるorやめるという状況になる。 ↩






