M12i.

学術書・マンガ・アニメ・映画の消費活動とプログラミングについて

Sphinxの拡張機能"sphinx-csharp"に機能を追加

Sphinx拡張機能"sphinx-csharp"に機能を追加したときのメモ。

やりたかったこと

pipを通じてインストールできるSphinx拡張機能"sphinx-csharp"に機能を追加したい。より具体的に言うと、この拡張機能が提供してくれるC#言語用のドメイン(ディレクティブとロールのセット*1)を拡張して、以下の3つをできるようにしたい:

  • メソッドのパラメータに修飾子(ref, out, params)を指定
  • メソッドの修飾子を複数指定
  • クラスのメンバーとしてインデクサーを記述(ディレクティブは.. indexer:: ...、ロールは:idxr:`...`

やったこと

#1. PyPIで調べる

PyPIサイトの"sphinx-csharp"のパッケージ・ページ(ここ)を参照。プロジェクトがGitHub上のリポジトリホスティングされれいることを確認。

f:id:m12i:20170103214529p:plain

#2. GitHubでForkする

まずはこのページに記載されているGitHub上のリポジトリここ)からプロジェクトをFork。私個人のリポジトリとしてPushできるようにしました(Fork先はここ)。

#3. ローカルにクローンを作成

Forkしたリポジトリを元にしてローカルにクローンを作成しました:

$ git clone https://github.com/mizukyf/sphinx-csharp.git

#4. Pythonコードを加筆修正

プロジェクトを構成するPythonスクリプト・ファイルをAtomテキスト・エディタでオープンして、色々変更を行いました。変更内容を知りたい場合は前述のFork後のリポジトリのCommit内容を確認してみてください(コミット一覧)。

#5. Sphinxプロジェクトで動作確認

Pythonコードの修正後、そもそもの動機の根源となっていたSphinxプロジェクト(もちろんC#で実装されたライブラリのAPIリファレンスを執筆しているプロジェクト)の設定ファイルconf.pyを修正:

import os
import sys
sys.path.append(os.path.abspath('/path/to/sphinx-csharp'))

クローンした"sphinx-csharp"が置かれているディレクトリをモジュール検索パスに追加します。生々しいですが、私的な用途なのと当面は動作確認も兼ねて使うことになるのでまあいいでしょう。

上記設定をした上でSphinxプロジェクトのreStructuredTextに追加したマークアップ(ディレクティブとロール)を利用したコードを記述。そしてビルドを行いました。

ふむ、まあまあかな?

構文サンプル

拡張されたメソッドおよびインデクサーのためのマークアップのサンプルを掲載しておきます。リポジトリにもコミットされている"/test/index.rst"を大幅に端折ったものです:

.. default-domain:: csharp

.. namespace:: MyNamespace

.. class:: MyClass

   This is a class with methods and properties.

   Here are some references to it's methods and properties:

       * :meth:`MyClass.MyMethod`
       * :meth:`MyMethod`
       * :prop:`MyClass.MyProperty`
       * :prop:`MyProperty`

   (・・・中略・・・)

   .. method:: int MyMethodHasParamModifiers(ref int arg0, params int[] arg1)

      A method with a parameter modifier.

   .. method:: public static MyMethodHasMultiModifiers()

      A method with multiple method modifiers.

   .. property:: string MyProperty { get; set; }

      A read/write property.

      (・・・中略・・・)

   .. indexer:: string this[int i] { get; set; }

   .. indexer:: string this[int i] { get; }

   .. indexer:: virtual string this[int i] { get; set; }

   .. indexer:: string this[int i, MyClass j] { get; set; }

      (・・・中略・・・)

Indexer ref :idxr:`MyClass.this[]`

*1:SphinxにはAPIを構成するクラスやそのメンバーをディレクティブ(Directive)でマークアップして、同じreStructuredTextファイルや別のファイルの中の対応するロール(Role)でマークアップした箇所から参照できるようにする機能があります。これらのディレクティブとロールはドメイン(Domain)という一種の名前空間を持っており、Python言語やGo言語などそれぞれのプログラミング言語ごとにその名を関したドメイン拡張機能(Extension)として配布されています。