When you want to present program source code beautifully — with line numbers and syntax highlighting (keywords, comments, and strings in different colors) — the two go-to packages are listings and minted. The first needs no external tools and runs anywhere; the second calls the external Pygments engine for far more accurate highlighting. If you only need code reproduced exactly as typed, the plainer verbatim family is enough.
Two approaches
There are two routes to typesetting source code, built on different ideas. listings is implemented purely in LaTeX macros and needs no extra software whatsoever; write \usepackage{listings} and it just works — on Overleaf, or in a locked-down computer-lab setup you cannot configure. minted, by contrast, hands the work to Pygments, a serious Python lexer, and pulls the result back into LaTeX. Because Pygments genuinely parses hundreds of languages, its highlighting is far more accurate than what listings can manage.
That difference is exactly the basis for choosing between them: reach for listings when you want simplicity and portability, and for minted when you want highlighting quality. Because minted launches an external program, it needs the special permission called shell escape (covered below) and may not run in restricted environments. And if you only want code reproduced verbatim — no colors, no line numbers — verbatim or fancyvrb are lighter weight; see “Verbatim” for those.
| listings | minted | |
|---|---|---|
ハイライト方式 / Highlighting | Keyword-list based (simple) | Pygments lexer (high accuracy) |
外部依存 / Dependencies | None (pure LaTeX) | Needs Python + Pygments |
シェルエスケープ / Shell escape | Not needed | Generally required (with exceptions on recent TeX Live) |
対応言語 / Languages | Major languages built in | 500+ covered by Pygments |
listings basics
Load \usepackage{listings} first. Wrap a block of code in the **lstlisting environment; pull in a whole external file with \lstinputlisting; and drop a short snippet into running text with \lstinline. Rather than repeating options at every call site, the standard practice is to collect language and appearance settings once in the preamble with \lstset{...}**.
\usepackage{listings}
\usepackage{xcolor}
\lstset{
language=Python, % 言語 / language
basicstyle=\ttfamily\small, % 本文の書体 / base font
keywordstyle=\color{blue}\bfseries,
commentstyle=\color{teal}\itshape,
stringstyle=\color{red!60!black},
numbers=left, % 行番号を左に / line numbers on the left
numberstyle=\tiny\color{gray},
frame=single, % 枠線 / a single-line frame
breaklines=true, % 長い行を折り返す / wrap long lines
showstringspaces=false, % 文字列中の空白を記号化しない
tabsize=2,
}
\begin{lstlisting}[caption={階乗を計算する}, label=lst:fact]
def factorial(n):
# 再帰で階乗を求める
if n <= 1:
return 1
return n * factorial(n - 1)
\end{lstlisting}The main \lstset keys are these. basicstyle sets the overall font (\ttfamily\small is the usual choice); keywordstyle, commentstyle, and stringstyle style keywords, comments, and strings. numbers=left puts line numbers down the left margin, and numberstyle formats them. frame=single draws a border, breaklines=true wraps long lines, and giving caption= and label= turns the block into a numbered “listing” — like a figure or table — that you can \ref.
Individual blocks can override options inside [ ], e.g. \begin{lstlisting}[language=C, numbers=none]. For an external file you can even slice out a line range: \lstinputlisting[language=Python, firstline=37, lastline=45]{sample.py}. To embed code in text, pick a delimiter the same way \verb does — \lstinline|while (i < n)|.
Limits of listings (UTF-8 and Japanese)
Highlighting in listings is an approximation driven by a per-language list of keywords and simple rules — it is not as clever as a real lexer. Context-sensitive coloring (where the same word is a type name in one place and a variable in another) is hard for it, and the rough edges show more on complex languages. This is a limitation of the approach itself.
A second practical pitfall is multibyte characters. listings does not assume UTF-8 by default, so Japanese comments and the like inside code can come out garbled or misaligned. There are two remedies. If you type code directly into the body, you teach it the characters one by one with **literate=**, as in \lstset{... literate={あ}{{あ}}1 ...} — impractical once there are many. When you instead include an external file, the easy fix is to load the **listingsutf8** package in place of listings (it works only with \lstinputlisting).
minted basics (Pygments)
Loading \usepackage{minted} lets you write code blocks in the **minted environment. The big difference from listings is that you pass the language name as the first argument**: \begin{minted}{python}. There is also a single-line shortcut **\mint, an inline command \mintinline, and \inputminted** for external files.
\usepackage{minted}
% ドキュメント全体の配色テーマ / a color theme for the whole document
\usemintedstyle{monokai}
\begin{minted}[linenos, bgcolor=black!90, fontsize=\small]{python}
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
\end{minted}
% 単一行 / a single line
\mint{python}|print("Hello!")|
% 本文中に埋め込む / inline in running text
\mintinline{python}{print("Hello!")}
% 外部ファイルを取り込む / include an external file
\inputminted[linenos]{python}{sample.py}Options go right after the environment name in [ ], in **key=value form. Common ones: linenos for line numbers; style=** to pick a Pygments color theme (monokai, etc. — the gallery is at pygments.org/styles); **bgcolor= for a background color; and fontsize=**. To apply one theme document-wide use \usemintedstyle{monokai}; to set defaults more broadly use \setminted{style=monokai, linenos}. For a language Pygments does not support, or to switch highlighting off deliberately, set the language to text.
Code for \mint and \mintinline is delimited just like \verb: a pair of matching delimiters (any punctuation, e.g. |...|) or curly braces {...}. Note that \mint is not for inline use — it is merely a way to avoid writing the environment when there is only one line of code. To blend code into running text, always use \mintinline.
Shell escape (the catch with minted)
Because minted launches an external Python program, you must compile with shell escape enabled — the permission that lets LaTeX run external commands. With pdfLaTeX, pass the -shell-escape option.
pdflatex -shell-escape document.texIt also requires Python 3.8+ and Pygments underneath. That said, things improved with minted version 3 — a complete rewrite released from 2025 onward. When installed through a TeX package manager (tlmgr install minted, etc.), the whole Python side including Pygments now ships inside the TeX tree as a dedicated **latexminted** executable, so there is no separate Pygments install. And latexminted is designed for restricted shell escape: **on TeX Live 2024 and later it is registered as a trusted executable, so you can compile without -shell-escape at all**.
Even so, on TeX Live before 2024 and on MiKTeX you still need -shell-escape (-enable-write18 on MiKTeX) as before. Since shell escape can run arbitrary external commands, do not use it on documents from untrusted sources. Conversely, it is fine in a pre-configured environment like Overleaf, or when working locally on your own code (Overleaf supports minted out of the box). This “external dependency plus shell escape” is the chief trade-off against the more portable listings.
Which to choose
- You want zero setup and the assurance it runs anywhere → listings. On Overleaf or a locked-down box,
\usepackageis all it takes. - Highlighting accuracy and language coverage come first → minted. Pygments-based coloring is in a different league.
- You cannot install external tools / cannot use shell escape → listings, no contest.
- You only need code reproduced verbatim, no coloring →
verbatimorfancyvrbwill do (see “Verbatim”). - You want to write an algorithm as pseudocode → the dedicated
algorithm2e/algpseudocode(see “Algorithms”).