Skip to content

Instantly share code, notes, and snippets.

@pasberth
Created October 8, 2013 17:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pasberth/6888325 to your computer and use it in GitHub Desktop.
Save pasberth/6888325 to your computer and use it in GitHub Desktop.
Sphinx と Pygments を使って独自のハイライティングをする

Sphinx と Pygments を使って独自のハイライティングをする

Sphinx はドキュメントを作成するツールで, Pygments は Sphinx 内部で使われているシンタックスハイライタです.

Pygments を使用して独自のハイライティングをする方法は, チュートリアルあるいはソースコードを読むのがいちばん手っ取り 早いでしょう. http://pygments.org/docs/lexerdevelopment/ とか, https://bitbucket.org/birkenfeld/pygments-main/src/0442d3cf660124048efde3c0d72ff79ea0355040/pygments/lexers?at=default などを読めば,レクサをつくってシンタックスハイライタをつくる方法が 完全に理解できます.たとえば, foo というキーワードを強調表示したければ, 次のようなクラスをつくります.次の例の場合,このファイル自身を実行すると 標準入力から適当に入力を読み取って,すべての foo を強調表示します.

from pygments import highlight
from pygments.formatters import Terminal256Formatter
from pygments.lexer import RegexLexer
from pygments.token import Keyword

class HogeLexer(RegexLexer):
    name = 'Hoge'
    aliases = ['hoge']
    filenames = ['*.hoge']

    tokens = {
        'root': [
            (r'foo', Keyword),
        ]
    }

if __name__ == '__main__':
    import sys
    code = sys.stdin.read()
    sys.stdout.write(highlight(code, HogeLexer(), Terminal256Formatter()))

たとえば, def のように,前のキーワードによって強調の仕方を変えたい場合, bygroups という関数があります.次の例の場合,このファイル自身を実行すると 標準入力から適当に読み取って,すべての foo を,それが def に続く場合は def を強調してなおかつ foo を青い字で表示し,def に続かない場合は緑の字で 強調表示します.

from pygments import highlight
from pygments.formatters import Terminal256Formatter
from pygments.lexer import RegexLexer, bygroups
from pygments.token import Keyword, Name, Whitespace

class HogeLexer(RegexLexer):
    name = 'Hoge'
    aliases = ['hoge']
    filenames = ['*.hoge']

    tokens = {
        'root': [
            (r'(def)(\s+)(foo)', bygroups(Keyword, Whitespace, Name.Function)),
            (r'foo', Keyword),
        ]
    }

if __name__ == '__main__':
    import sys
    code = sys.stdin.read()
    sys.stdout.write(highlight(code, HogeLexer(), Terminal256Formatter()))

さて, Pygments によって色をつける方法はわかったとして, ところで, Sphinx は内部で Pygments を使用しているのですが, 独自に定義した Pygments の レクサを Sphinx に使わせる方法がわかりません. Pygments のチュートリアルには,ソースコードを編集せよ.と書かれていますが, せっかくですから conf.py で追加したい所です. ソースコードを追ってみると,使用できる言語は どうやら https://bitbucket.org/birkenfeld/pygments-main/src/0442d3cf660124048efde3c0d72ff79ea0355040/pygments/lexers/_mapping.py?at=default で管理されているようです.Sphinx のディレクティブの実装も追えば,じっさいこの値が使用されている事がわかります. そういうわけで,ちょっと違法かもしれませんが, conf.py に次のように書く事で 目標を達成できます.ただし,次の例の場合,パスの通った場所にある hoge.py で HogeLexer が定義されている必要があります

import pygments.lexers._mapping
pygments.lexers._mapping.LEXERS['HogeLexer'] = ('hoge', 'Hoge', ('hoge',), ('*.hoge',), ('text/x-hoge',))

こうして,

.. sourcecode:: hoge

   foo
   def foo

などとすれば,実際にこのコードがハイライトされることがわかります.

ところで, sphinx の pygments_style には,いろいろな値が設定できます. sphinx とか, emacs もあります. でも,できれば css で拡張したい所です.まあ,それは,書き出される HTML は Pygments のものなので, Pygments のドキュメントを読めばわかることです.ただ, Sphinx で CSS を使用するには, テーマをつくる必要があります.そういうわけで, http://sphinx-users.jp/cookbook/makingwebsite/index.html などを参考に, CSS をつくります.

おわり.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment