【2025/09/17 追記】 そもそも Jupyter Notebook → PDF 変換方法の比較表は以下を参照ください (このページの TeX 経由方式はノートブック上で HTML をレンダリングしてる場合には不向きです)。
Jupyter Notebook → PDF 変換方法の比較表 + Playwright 経由変換例
前回、Jupyter Notebook を PDF にきれいに変換する記事を書きました (以下)。
が、手元で上記の PDF からコードをコピーするとインデントの空白がコピーされない (完全にインデントがなくなる) ことに気付きました。これは不便だと思います。
なお、印刷プレビュー経由方式 PDF については、手元では空白が1つになり (4つになってほしい)、こちらもコピペしてすぐ実行できる状態ではありませんでした。
なので、さしあたり以下の対処法を考えました。
考えた対処法
-
LaTeX テンプレートを修正し、コード内の空白を空白記号 ␣ として PDF に出力する。
- PDF 上のコードをコピーする時は、ノートブック等にペーストしてからすべての空白記号を空白に置換する。
- 「Jupyter Lab の置換コマンドはどこ?」となった私のような方は、以下の Stack Overflow に貼られている GIF 画像を参照してください。
How to Find & Replace in Jupyter Lab - Stack Overflow
- 「Jupyter Lab の置換コマンドはどこ?」となった私のような方は、以下の Stack Overflow に貼られている GIF 画像を参照してください。
- PDF 上のコードをコピーする時は、ノートブック等にペーストしてからすべての空白記号を空白に置換する。
コピペする時に置換の手間がかかってしまいますが、置換でインデントが復元できるならまだよいと思います (?)。よりよい対処法があればご教示いただけますと幸いです。
なお、IPython シェルに、各セルのコード内の空白記号を常に空白に置換する処理を登録することもできます (後述)。ただ、空白記号のままだとシンタクスハイライトが効きません。
以下に、テンプレート修正箇所を示します (テンプレートの場所は前回記事を参照)。
空白記号を出力するためのテンプレート修正
style_jupyter.tex.j2
の以下の箇所の \begin{Verbatim}
のオプション引数に ,showspaces
を書き足します。これでコードセル内の空白が明示的に空白記号として PDF 出力されます。
%==============================================================================
% Support Macros
%==============================================================================
% Name: draw_cell
% Purpose: Renders an output/input prompt
((*- if draw_cell is not defined -*)) % Required to allow overriding.
((* macro draw_cell(text, cell, prompt, prompt_color, extra_space) -*))
((*- if prompt == 'In' -*))
((*- set style = "breakable, size=fbox, boxrule=1pt, pad at break*=1mm,colback=cellbackground, colframe=cellborder"-*))
((*- else -*))((*- set style = "breakable, size=fbox, boxrule=.5pt, pad at break*=1mm, opacityfill=0"-*))((*- endif -*))
\begin{tcolorbox}[((( style )))]
(((- draw_prompt(cell, prompt, prompt_color, extra_space) )))
\begin{Verbatim}[commandchars=\\\{\},showspaces] % 空白記号を表示する
((( text )))
\end{Verbatim}
\end{tcolorbox}
((*- endmacro *))
((*- endif -*))
ただ、上記で設定した空白記号は周辺のフォントと同じ色で出力され、若干主張が激しいので、文字色を薄くすると PDF がみやすいと思います (好みに応じて)。
\renewcommand{\FancyVerbSpace}{\textcolor{gray!50}{\textvisiblespace}} % 空白記号を薄く
((* endblock header *))
これらの編集をすると、出力される PDF は下図のようになります。このコードをコピーすると空白記号は空白記号としてコピーされるので、適宜空白に置換します。
【おまけ】Jupyter Notebook 上で空白記号のままでコードを実行する方法
ノートブック冒頭で、IPython シェルに、「コードクリーンアップ後にコード各行の空白記号を空白に置換」を登録しておけば、空白記号のままで実行できます (下図)。シンタクスハイライトは一部効かないし見た目がきれいではないですが、手動で置換する手間はないです。
ip = get_ipython()
ip.input_transformers_cleanup.append(lambda lines: [line.replace('\u2423', ' ') for line in lines])