はじめに
よろしくね、私の味方! nikkieです。
Sphinxでシンタックスハイライトしたコードを表示する1際、コードが別のファイルにあるときは literalinclude
ディレクティブを使っています。
このディレクティブ、ドキュメントを読んだところ知らなかったオプションを知り、もっと便利に使えそうでした。
バックアップとして現時点の理解をアウトプットします。
目次
- はじめに
- 目次
- Sphinxのliteralincludeディレクティブ
- literalincludeディレクティブとcode-blockディレクティブで共通のオプション
- コードの一部だけをinclude(code-blockディレクティブにはないオプション)
- 終わりに
Sphinxのliteralinclude
ディレクティブ
https://www.sphinx-doc.org/ja/master/usage/restructuredtext/directives.html#directive-literalinclude
.. literalinclude:: example.py
のようにして、example.py
にあるコードをドキュメントに含められます。
Sphinxプロジェクトで書いているreSTとは別のファイルにあるソースコードを、コピペすることなくliteralinclude
でドキュメントに含められるので、私には大変重宝しています。
例えばsphinx-revealjs
で発表資料を作るとき、サンプルコード群はリポジトリルートでディレクトリを分けてliteralinclude
しています2。
reSTの中の、例えばcode-block
ディレクティブのコードはフォーマットが難しいですが、サンプルコードをreSTから切り離すとフォーマットしやすくなります。
ドキュメントでは、以下のような使用例(オプション指定例)が示されています。
.. literalinclude:: example.rb :language: ruby :emphasize-lines: 12,15-18 :linenos:
オプションはたくさんあり、オススメのものを以下に述べていきます。
literalinclude
ディレクティブとcode-block
ディレクティブで共通のオプション
行番号表示
linenos
linenos
はフラグで、指定すると行番号が表示されます。
lineno-start
lineno-start
は整数と一緒に指定します。
行番号は指定した整数から始まります。
language
でシンタックスハイライト指定
シンタックスハイライトに使うPygmentsのlexerのshortnameを指定します。
いろいろ見た中では、以下が参照しやすいように思われます。
強調したい行を指定 emphasize-lines
コードのうち強調したい行の行番号を指定します。
:emphasize-lines: 12,15-18
のように、カンマ区切り、また範囲はハイフンで表せます。
lineno-start
を指定したり、後述する一部だけ含めたりしても、含めるコードの1行目を強調するなら:emphasize-lines: 1
です。
ドキュメントに含める部分を一番上から1,2,...行目と数えるようです。
その他(未検証含む)
caption
指定したキャプションを付けられます。
code-block
ディレクトリとの差分は、:caption:
とだけ指定した場合、literalinclude
ディレクティブに指定したファイル名がキャプションとして使われる3ようです。
name
(素振り材料)
implicit target nameを指定し、ref
ロールなどでコードを参照できるようです。
コードの一部だけをinclude(code-block
ディレクティブにはないオプション)
クラス・関数・メソッド単位 pyobject
もしPythonモジュールの場合には、 pyobject オプションを使用してクラス、関数、メソッドの単位でインクルードすることもできます:
.. literalinclude:: example.py :pyobject: awesome_function
literalinclude
に指定したファイルがPythonモジュールのとき限定ですが、クラス・関数・メソッド単位で一部だけ含められます!
pyobject
オプションはカンマ区切りをサポートしていないので、複数のクラス・関数・メソッドを含めたいときは、literalinclude
ディレクティブを複数指定して使っています。
Pythonモジュールをフォーマットしても、pyobject
オプションなら含める箇所がズレる(後述)ようなこともありません
行数指定 lines
lines オプションを使って行番号を正確に指定することでも部分的なインクルードを行えます:
.. literalinclude:: example.py :lines: 1,3,5-10,20-
1行目、3行目、5〜10行目、20行目以降が含められます。
行番号を表示したとき、1行目、3行目、5〜10行目の部分の行番号は飛び飛びにはならず、1〜7と連番になります。
lines
オプションはPythonモジュール以外を部分的に含める際に重宝します。
ですが、含めるファイルをフォーマットして空行が入った/除かれた場合にズレてしまうので、注意が必要です。
特定の文字列の後から/前までを含められる
今回ドキュメントを読んで一番の驚きはこちら。
注釈の例ですが、以下のPythonモジュールについて
if __name__ == "__main__": # [initialize] app.start(":8000") # [initialize]
:start-after: [initialize]
・:end-before: [initialize]
と指定すると、コメントの間の行が含められます!
:start-after: pattern
:patternの行の次から:start-at: pattern
:patternの行から(patternの行を含む):end-before: pattern
:patternの行の前まで:end-at: pattern
:patternの行まで(patternの行を含む)
linesオプションの指定と違って、フォーマットが変わってもincludeされる部分は影響を受けなさそうで、結構使いやすそうな印象です。
これは使っていきたい!
その他(未検証含む)
素振り材料も含めて記載します。
差分表示 diff
.. literalinclude:: example.py :diff: example.py.orig
unified diff formatで差分が表示されます。
前後にコード行を追加 prepend
,append
(素振り材料)
lineno-match
ファイルの一部を表示するように指定した場合、ファイルの行番号をそのまま表示するように指定することもできます。その場合は、 lineno-match オプションを設定して下さい。
(上の素振りで試しましたが)ファイルの行番号がそのまま表示されました。
以下のただし書きも納得です。
ただし、このオプションは選択された行が切れ目なくつながっている場合でのみ有効です。
終わりに
存在を知ってから積極的に利用しているliteralinclude
ディレクティブ、ドキュメントにあたったことで知識の整理と新たな発見がありました。
start-after
やend-before
が特にヤバいです!
今まで使っていて感じていた、かゆいところにきれいに手が届きそう!
reSTにソースコードをコピペせずDRYを保って扱えるliteralinclude
ディレクティブはオススメです。
たくさんのオプションによって非常に柔軟に使えることが分かりました。
- 先日、全部で4つあるとアウトプットしました。↩
-
例 https://github.com/ftnext/2022_slides
source
にreSTを置き、samplecodeにPythonモジュールを置いています↩ - In addition, it supports the caption option; however, this can be provided with no argument to use the filename as the caption. (「追加のオプション」の直後のパラグラフより)↩