はじめに
TeXで複数のプログラミング言語のコードを記述するとき、そのまま記述するとLstlisting
やLstinline
の各言語の書式設定が混ざってしまう不具合があります。
そこでどのようにすれば複数のプログラミング言語のそれぞれの設定で記述できるかを説明します。
そのまま記述すると?
まず、そのまま記述してみるとどのようなことが起きるか見てみます。
例としてHaskellとPythonのコードを記述する場合を考えます。
分かりやすさのために、Haskellコードの文字を黒、背景を白に、Pythonコードは反転して文字を白、背景を黒に設定します。
\usepackage{listings}
\usepackage{color}
\lstset{
language = Haskell,
basicstyle = {\color{black}},
backgroundcolor = {\color{white}}
}
\lstset{
language = Python,
basicstyle = {\color{white}},
backgroundcolor = {\color{black}}
}
そこで、以下のように両方のコードを記述してみます。
\begin{lstlisting}[language = Haskell, caption = Haskell]
main :: IO ()
main = putStrLn "Hello world"
\end{lstlisting}
\begin{lstlisting}[language = Python, caption = Python]
print("Hello World")
\end{lstlisting}
ここで設定通りPythonだけ文字色が反転して欲しいのですが、結果は以下のように両方反転したものになります。
これはおそらく、オプションlanguage
を指定しても最後に設定したlseset
の内容が反映されてしまうこと、すなわち変数が上書きされてしまうのが原因だと思われます。
そこで、各言語設定をそれぞれ適用して、Pythonだけ反転するようにするには以下のようにします。
言語設定
最後に設定したlstset
の内容が反映されるなら、コードを記載する直前にlstset
を設定してしまうという方法を取ります。
そこで、各lstset
を呼び出すマクロをそれぞれ定義します。
\newcommand\lstsetHaskell{
\lstset{
language = Haskell,
basicstyle = {\color{black}},
backgroundcolor = {\color{white}}
}
}
\newcommand\lstsetPython{
\lstset{
language = Python,
basicstyle = {\color{white}},
backgroundcolor = {\color{black}}
}
}
上に設定したlstset
を呼び出すコマンドをそれぞれ\lstsetHaskell
と\lstsetPython
という名前で定義します。
そして、それを各言語のコードを記述する直前に挿入するだけです。
このとき、lstlisting
のlanguage
オプションを入れる必要はないです。
\lstsetHaskell
\begin{lstlisting}[caption = Haskell]
main :: IO ()
main = putStrLn "Hello world"
\end{lstlisting}
\lstsetPython
\begin{lstlisting}[caption = Python]
print("Hello World")
\end{lstlisting}
すると以下のように各言語設定が反映されます。
しかしながら毎回\lstsetHaskell
や\lstlsetPython
と入れるのは面倒なので、次のようなマクロを組みます。
使いやすいようにマクロを組む
個人的に以下のようなマクロを作っています。
lstlisting
\begin{lstlisting}
と\end{lstlisting}
の代わりに\begin{haskellCode}
と\end{haskelCode}
で囲んで記述できるようにします。
ユーザ定義環境は通常\newenvironment
を使って定義しますが、この中に\begin{lstlisting}
と\end{lstlisting}
を入れると定義自体はできますがコードの記述が通りません。
そこで、代わりに専用コマンド\lstnewenvironment
を使います。
コメントで指摘していただいた@mod_poppo様、ありがとうございます。
\lstnewenvironment{haskellCode}[#1][]{\lstsetHaskell\lstset{#1}}{}
\lstnewenvironment{pythonCode}[#1][]{\lstsetPython\lstset{#1}}{}
ここで任意の引数を1つ取っていて、それによってlstset
を上書きして変更したりcaption
等をつけることが可能です。
\begin{haskellCode}[caption = Haskell]
main :: IO ()
main = putStrLn "Hello world"
\end{haskellCode}
\begin{pythonCode}[caption = Python]
print("Hello World")
\end{pythonCode}
lstinline
\lstinline
でも同様にマクロを定義できます。
\newcommand\inHaskell{\lstsetHaskell\lstinline}
\newcommand\inPython{\lstsetPython\lstlinline}
\lstinline
の時にこれの代わりにそれぞれ\inHaskell
と\inPython
と記述することでそれぞれの設定で記述できるようにしています。
"Hello World"を出力するには, Haskellでは\inHaskell{putSrtLn "Hello World"}, Pythonでは\inPython{print("Hello World")}と記述します.
まとめ
TeXで複数のプログラミング言語のコードを記述する際に、それぞれの設定を反映させながら記述する方法を記載しました。