そのまま出力(verbatim 系)

LaTeX で積分記号を出すより、バックスラッシュ 1 文字を出すほうが難しい——これは冗談ではありません。打った文字をそのまま印字する verbatim\verbverbatim 環境)は、LaTeX が自分の文法を一時的に停止させないと成立しない、システム唯一の場所だからです。この構造から、一見理不尽に見える規則がすべて導かれます。\verb が改行をまたげないのも、\end {verbatim} と空白を入れると組版が止まるのも、\section{...}\footnote{...} の中で使うと verbatim とは無関係なエラーが出るのも、原因は一つです。このページでは verbatim 環境と \verb、空白を可視化する星付き形、ファイル全体を読み込む \verbatiminput\VerbatimInput、コマンドを一部だけ生かす alltt、行番号と枠を付ける fancyvrb、そして地の文でバックスラッシュやアンダースコアを打つ方法までを扱います。

verbatim 環境が実際に切っているもの

\begin{verbatim}\end{verbatim} のあいだに書いたものは、改行も空白も含めて打った通りに、タイプライタ体で印字されます。追加パッケージは要りません。仕組みは「エスケープ」ではなく 降格 です。LaTeX は環境に入るときに \{}$&#^_%~ のカテゴリコードを一斉に「ただの文字」へ書き換えます。カテゴリコードとは、TeX が入力を読みながら 1 文字ずつに貼っていく役割ラベルのことで、その文字がコマンドを始めるのか、グループを開くのか、単なるインクなのかを決めています。verbatim の中でバックスラッシュが命令を始めないのは、命令を無視しているからではなく、その瞬間バックスラッシュがバックスラッシュという名前のただの記号になっている からです。

latex
\begin{verbatim}
for i in range(3):
    print("100% & $5 \n")   # none of this is interpreted
\end{verbatim}

これを実装するのは、書き手にとっても骨が折れます。その苦労は LaTeX 自身のソースに刻まれています。LaTeX の本体を定義する latex.ltx の中で、verbatim の終わりを探すマクロは、エスケープ文字を |、グループの開閉を [] に切り替えた状態で定義されています。定義の内側では \{} の 3 文字がどうしても「ただの印字される文字」でなければならず、そのままでは自分自身を書き表せないからです。verbatim を定義するあいだだけ、LaTeX のソースは LaTeX で書かれることをやめます。この 2 行は TeX Live 2024 同梱の latex.ltx でそのまま読めます。

この「終わりを探す」やり方から、二つの実務的な規則が出てきます。第一に、環境の中に文字列 \end{verbatim} をそのまま書くことはできません。LaTeX はそれを見つけた瞬間に環境の終わりだと判断します。第二に、\end{verbatim} のあいだに空白を入れてはいけません。終端はマクロの引数の区切りとして文字単位で照合されるため、\end {verbatim} は終端として認識されず、TeX はファイルの末尾まで読み進めて Runaway argument? に続けて ! File ended while scanning use of \@xverbatim. で停止します。原稿を整形するツールがこの空白を入れてしまう事故は珍しくありません。なお空白の個数を見せたいときは星付きの verbatim* 環境を使うと、空白が ␣ として印字されます。

\verb の区切り文字の選び方と、改行をまたげない理由

行の途中に短い逐語を差し込むには \verb を使います。\verb の直後に区切り文字を 1 つ置き、そのまま出したい文字列を書き、同じ文字でもう一度閉じる——\verb|\textbf{x}| のように書きます。区切り文字は 中身に現れない文字 ならほぼ何でも構いません。| が中身に含まれるなら \verb!...!\verb+...+\verb/.../ に替えます。ただし 2 つだけ選べない文字があります。英字は使えません——\verbx と続けて書くと TeX はそれを別のコマンド名として読んでしまうからです。そして * も使えません——\verb* は空白を ␣ で印字する星付き形として予約されているためです。

latex
The macro \verb|\textbf{...}| sets bold text;
a pipe in the content needs another delimiter, as in \verb!a|b!.

Count the gaps: \verb*|a  b| prints the spaces as visible marks.

もう一つ、\verb には強い制限があります。閉じの区切り文字は同じ行になければなりません。 見つからないまま行末に達すると、! LaTeX Error: \verb ended by end of line. で止まります。実際の原因はたいてい閉じ忘れですが、意外に多いのがエディタの自動折り返しや整形で長い行が分割されてしまうケースです。長い文字列を扱うなら \verb ではなくブロック側の環境に移すのが安全です。なお、URL のように ~#%_ を含みがちな文字列だけが目的なら、url または hyperref パッケージの \url{...} のほうが向いています。逐語であることに加えて、適切な位置で行を折り返してくれるからです。

地の文でバックスラッシュやアンダースコアを打つ

文字を 1 つ 2 つ出したいだけなら、verbatim を持ち出す必要はありません。バックスラッシュは \textbackslash、アンダースコアは \_ で出ます。ここで最も多い事故が \\ はバックスラッシュではなく改行コマンドである ことです。\\ と書いてもバックスラッシュは印字されず、その場で行が折り返されます。数式モードの $\backslash$ でも見た目は出せますが、字形が数式フォントのものになるので、地の文では \textbackslash が正解です。アンダースコアを裸で書くと ! Missing $ inserted. になります——TeX にとって _ は下付き文字の指示だからで、file\_name のようにエスケープすれば解決します。

書き方出力注意
\textbackslash\\\ は改行命令。バックスラッシュは出ない
\__裸の _! Missing $ inserted. になる
\% \& \# \$% & # $いずれも前に \ を付けるだけでよい
\{ \}{ }グループ記号を文字として出す
\textasciitilde~裸の ~ は改行しない空白になる
\textasciicircum^裸の ^ は上付き文字の指示になる

なぜ \verb は \section や \footnote の中で失敗するのか

\verbverbatim 環境も、他のコマンドの引数の中には書けません。理由は禁止規則ではなく、単純な時間の前後関係です。\verb は自分の引数を読む直前にカテゴリコードを切り替えます。ところが \section{...} の中身は、\section が呼ばれた その時点で、通常のカテゴリコードのままトークン列に変換され終わっています\verb の出番が来るころには、\foo はすでに「印字すべき 4 文字」ではなく「\foo というコマンド」になっているのです。verbatim は文字を読み直せない——これが本質です。

厄介なのは、この失敗が verbatim の名前を一切出さないエラーになることです。\section{The \verb|\foo| command}! Undefined control sequence. で止まります——\foo が本当のコマンドとして解釈され、そんなものは定義されていないからです。中身に特殊文字が一つもない \mbox{\verb|abc|} なら ! LaTeX Error: \verb illegal in argument. という、めずらしく親切なメッセージが出ます。ブロック環境の場合はさらに読みにくく、\footnote{\begin{verbatim} ... \end{verbatim}}Runaway argument? に続いて ! Paragraph ended before \@xverbatim was complete.\parbox{5cm}{...} の中なら ! Argument of \@xverbatim has an extra }.\caption{...} の中なら ! Argument of \@caption has an extra }. になります。どれも「verbatim を引数に入れた」という一つの原因の別の顔です。

一方で、表のセルは引数ではありませんtabular の各セルは行と列の区切りを見ながら読まれるので、p{4cm} の列も含めて \verb はそのまま動きます。同じ表の中でも \multicolumn{2}{c}{...} の第 3 引数は本物の引数なので、そこでは失敗します。「表の中では使えない」と覚えるのではなく、波括弧で囲まれた引数かどうか で判断するのが正確です。

回避策は三つあります。一つめは cprotect パッケージ(Bruno Le Floch、v1.0e)。守りたいコマンドの前に \cprotect を付けるだけで、\cprotect\section{The \verb|\foo| command} が通ります。環境の \begin を守る \cprotEnv も付属します。二つめは fancyvrb の \SaveVerb / \UseVerb。先に逐語テキストに名前を付けて保存し、引数の中ではその名前を呼ぶだけにする二段構えです。三つめは脚注専用で、fancyvrb の \VerbatimFootnotes をプリアンブルで宣言しておくと \footnote の中で逐語が使えるようになります。なお、fancyvrb の \Verb に替えても解決しません——同じタイミングの問題を抱えているからです。そして最後の手段として、\texttt{\textbackslash foo} と手で綴ってしまうのが、見出し 1 つのためならいちばん短い道です。

latex
% Fails: \foo was already a command token before \verb could act
% \section{The \verb|\foo| command}   -> Undefined control sequence

% Workaround 1 -- cprotect
\usepackage{cprotect}
\cprotect\section{The \verb|\foo| command}

% Workaround 2 -- save it first, use it later
\usepackage{fancyvrb}
\SaveVerb{cmd}|\foo|
\section{The \UseVerb{cmd} command}

% Workaround 3 -- verbatim inside footnotes
\VerbatimFootnotes

ファイルを丸ごと読み込む \verbatiminput と \VerbatimInput

プリアンブルに \usepackage{verbatim} を書き、本文で \verbatiminput{hello.py} とすれば、その外部ファイルの全行が逐語で組まれます。原稿にコピーする方式と違い、元ファイルを直せば PDF も自動で追従するので、コードと文書を二重に管理せずに済みます。動く実物を載せられるという意味では、これが最も安全なコード掲載方法です。

ところで、verbatim という名前のパッケージが標準の verbatim 環境と別に存在するのは、\verbatiminput を足すためではありません。Rainer Schöpf による このパッケージ(LaTeX の Tools バンドル所収)の説明書は、動機をはっきり書いています。組み込みの環境は \end{verbatim} までの全文を 1 個のマクロ引数として読み終えるまで、1 行も出力できない——だから長いリストは TeX のメモリを溢れさせる可能性がある、というのです。パッケージ版は verbatim を 1 行ずつ 読んで出力する実装に置き換え(説明書はこの手を AMS-TeX の \comment マクロから借りたと述べています)、その結果として「ファイルを 1 行ずつ読める」ようになり、\verbatiminput はいわばその副産物として生まれました。副作用も一つあります。\end{verbatim}同じ行に続けて書いた文字 は、組み込み版では印字されますが、パッケージ版では黙って捨てられます。挙動の違いは意図的なもので、説明書に明記されています。

document.tex
\usepackage{verbatim}
% ...
\verbatiminput{hello.py}

\begin{comment}
This paragraph is skipped entirely -- not printed, not typeset.
\end{comment}

同じパッケージは、\begin{comment} から \end{comment} までを丸ごと読み飛ばす comment 環境 も追加します。これは逐語出力ではなく「出力しない」ための道具で、草稿の一部を一時的に外しておくのに便利です。ファイル読み込みをもう一段細かく制御したいなら、次節の fancyvrb にある \VerbatimInput[オプション]{ファイル名} を使います。\verbatiminput と違って枠や行番号を渡せるほか、firstline=10, lastline=25 のように ファイルの一部だけ を切り出せるので、長いソースの該当箇所だけを見せたいときに効きます。

コマンドを一部だけ生かす alltt

コード例の 一部だけ を太字にしたり色を付けたりしたいとき、通常の verbatim では手が出せません。命令が全部止まっているからです。そこで LaTeX 標準配布に含まれる alltt パッケージalltt 環境が効きます。allttverbatim とほぼ同じく等幅で打った通りに組みますが、バックスラッシュ \ と波括弧 { } の 3 文字だけは通常の意味を保ちます。つまり見た目は逐語のまま、内部で LaTeX のコマンドを走らせられます。

latex
\usepackage{alltt}
% ...
\begin{alltt}
def \textbf{greet}(name):
    return "Hi, " + name   \textit{# a comment}
\end{alltt}

この例では関数名 greet が太字、コメント部分が斜体になり、それ以外は打った通りに残ります。引き換えに払う代償は明快で、\{} の 3 文字を 文字として 出したいときは \textbackslash\{\} と綴らなければなりません(verbatim 環境ならそのまま出ます)。つまり alltt は、逐語性を 3 文字ぶん手放して装飾する権利を買っている、という取引です。手で軽く飾りたいなら alltt、一文字も動かしたくないなら verbatim、と割り切って使い分けます。

行番号と枠を付ける fancyvrb の Verbatim 環境

行番号も枠も、組み込みの verbatim には付けられません。それを引き受けるのが fancyvrb パッケージ で、中心は 大文字 V で始まる Verbatim 環境——小文字の verbatim とは別物です。オプションは \begin{Verbatim}[numbers=left, frame=single] のように環境ごとに渡すか、プリアンブルで \fvset{numbers=left, ...} と書いて文書全体の既定値にします。fancyvrb は 1992 年に PSTricks の作者でもある Timothy Van Zandt が書き起こし、2000 年以降は Herbert Voß が保守しています(TeX Live 2024 同梱版は v4.5c)。30 年ぶんの実用機能が積み上がっているのはそのためです。

オプション主な値働き
numbersnone / left / right行番号の位置。既定は nonenumbersep で本文との間隔を調整
framenone / single / lines / leftline / topline / bottomline枠の種類。既定は none。太さは framerule、余白は framesep
fontsize\small\footnotesize などフォントサイズ。既定は本文と同じ
showspacestrue / false空白を可視文字で表示。showtabs はタブ、tabsize は幅
firstline / lastline整数\VerbatimInput でファイルの一部だけを切り出す
commandchars\\\{\}エスケープ文字とグループ開始・終了の 3 文字を指定し、逐語の中で命令を有効化
latex
\usepackage{fancyvrb}
\fvset{fontsize=\small}          % document-wide default
% ...
\begin{Verbatim}[numbers=left, frame=single]
def greet(name):
    return "Hello, " + name
\end{Verbatim}

% only lines 10-25 of an external file, framed
\VerbatimInput[firstline=10, lastline=25, frame=lines]{server.py}

commandchars=\\\{\} を指定すると、逐語の中でも \{} がエスケープ文字とグループ区切りとして働き、alltt と同じ要領で命令を埋め込めるようになります。同じオプション一式を毎回書きたくなければ、\DefineVerbatimEnvironment{Code}{Verbatim}{numbers=left, frame=single} のように 自前の環境を定義 してしまうのが定石です。以後は \begin{Code} と書くだけで済みます。ここまでの道具はすべて「打った通りに出す」ためのもので、キーワードの色分け——つまり 構文ハイライト は行いません。色付きで整形されたソースを載せたいなら、TeX のマクロだけで着色する listings か、Python の Pygments に任せる minted が担当です。関連ページの「ソースコード掲載」で両者を比較しています。