RDとは何か

RDとはRuby版のPODです。つまりRubyスクリプトファイルの中に埋め込む事を意図して 定義されたドキュメントフォーマットです。

RDは主にplain textをさまざまなフォーマットに変換するplain2というプログラム の影響を受けています。そのため、RDはplain textに似ており、シンプルですっきり した文法なので読みやすく書きやすいでしょう。

RubyインタプリタはRDをどのように扱うか

Rubyのインタプリタは単純に"=begin"で始まる行から"=end"で始まる 行までを無視します。ですから、スクリプトファイル中に埋め込む事ができるのは RDだけではありません。何でも=begin=endの間に書く事ができるの です。RDは選択肢の一つにすぎませんが、Ruby標準のドキュメントフォーマットと されています。*1

RDの基本的な概念と文法

Element, Block, Inline

これからの説明では"Element"という用語*2をテキストに文章構造を与えるための 構成要素という意味で用います。さらに、"Block"という用語を比較的 大きくグローバルな構造を表すElementに、"Inline"という用語を比較的小さ くローカルな、テキストに付加的な修飾を与えるElementに対して用います。

段落や見出し、リストなどがBlockです。RDではBlockを表すのに インデントや特殊文字を用います。Blockを入れ子にすることで複雑な 構造も表現できます。そして、Blockの表現は自然とplain textに見え ます。詳しくはBlockを見てください。

強調やコードや参照などがInlineです。((? ... ?))のようなカッコと 特殊文字の組合せがInlineの表現に使われます。ほとんどのInlineが互いに 入れ子にできます。詳しくはInlineを見てください。

Block

基本文法

Blockは行指向の文法にしたがいます。つまり、同じ行にある文字はすべて同じ Blockに属しています。インデントはBlockの入れ子レベルとタイプを表して います。行の先頭の文字はBlockのタイプに関係します。

概念と用語
Baseline
Baselineはインデントの基準です。ある行のインデントととBaselineの相対的 な深さはその行の属するBlockのタイプに影響します。
Head Char
Head Charは空白文字を除いた行の先頭の文字です。
STRINGLINE
STRINGLINEは普通の文字で構成された行です。STRINGLINEは"*", "(num)", ":", "=", "+"といった文字を Head Charとしては含みません。しかし、インデントされた行なら"=" や"+"をHead Charとすることができます。
WHITELINE
WHITELINEは空白文字だけの行です。
Comment
/^#/にマッチする行はコメントとみなされます。
Baselineの決定と影響

トップレベルではBaselineは行の左端です。リスト内ではBaselineはListItem の最初のBlockによって決定します。例えば、

Example: "|" はBaselineを表しています。
  |この行はトップレベルのTextBlockの行だとします。
  |<- したがって、Baselineは左端です。
    *|List内では (1)
     |<- このようにBaselineは(1)の行で決定されます。
    *    |同じListでもListItem毎にBaselineが決定されます。
         |<- したがって、1番目のListItemとは違うここにBaselineがあります。

|この行はトップレベルのTextBlockの行だとします。 |<- したがって、Baselineは左端です。

  • |List内では (1) |<- このようにBaselineは(1)の行で決定されます。
  • |同じListでもListItem毎にBaselineが決定されます。 |<- したがって、1番目のListItemとは違うここにBaselineがあります。

Blockが別のBlockに入れ子になっている時には内部のBlockのBaselineは外側の BlockのBaselineよりも深くなります。

Baselineとインデントの相対的な位置関係がBlockのタイプに影響します。 Baselineと同じ深さにインデントされたSTRINGLINETextBlock に属す行となります。一方Baselineより深くインデントされたSTRINGLINEVerbatimの行です。

Blockのタイプ

Headline

Headlineは"="か"+"をHead Charとする行で構成されます。 Headlineは1行以上にはなりません。Headlineはトップレベルだけに置く事が できます。

Example:
|<- トップレベルのBaseline
= Headline 1.
=== Headline 1.1.1.
+ Headline 1.1.1.1.1.

Headline 1.

Headline 1.1.1.

Headline 1.1.1.1.1.

Headlineの先頭の特殊文字はHeadlineのレベルを表しています。次の図で 最初のマークは最も大きなレベルのもので、最後のマークがもっとも小さな レベルのものです。

Fig: Headline Marks
=
==
===
====
+
++

マークに続くテキストはHeadlineのタイトルです。これは同時に Referenceのラベルとして使われます。

HeadlineのタイトルにはReferenceとFootnoteを除くInlineを使う事が できます。

Include

Includeは"<<<"をHead Charとし、その後ろにインクルードする ファイルの名前が続く行からなります。RD形式のファイルと出力するフォーマッ トで書かれたファイルのどちらでもIncludeによってインクルードできます。

RD形式のファイルをインクルードする時にはインクルードされるファイルの名 前は"foo.rd"の様に".rd"もしくは".rb"というサフィックスでなくてはなりま せん。そして、"<<<"の後にはサフィックスを含めたファイルの完全な 名前を書きます。例えば、次の様にです。

<<< foo.rd

出力するフォーマットのファイルをインクルードするには、インクルードされる ファイルはその出力フォーマットに固有のサフィックスを持たないといけません。 例えば、HTMLのファイルをインクルードするには".html"というサフィックスを、 Texinfo形式のファイルをインクルードするには".texi"というサフィックスを つけます。そして、"<<<"の後ろにはサフィックスを除いたファイルの 名前を書きます。例えば、

<<< foo

と書くわけです。

この場合、RDフォーマッタはHTMLを出力する時には"foo.html"をインクルード し、Texinfo形式で出力する時には"foo.texi"をインクルードします。出力フォー マットのIncludeを用いる時には複数の(しかもなるべく多くの)形式のインク ルードファイルを用意すべきです。

TextBlock

TextBlockは複数のSTRINGLINEから構成されます。それらの行はBaseline と同じインデントでないといけません。Baselineより深いSTRINGLINEVerbatimの行とみなされます。

TextBlockはInlineを内部に含む事ができます。

Example:
|
これはTextBlockです。
TextBlockの2行目の行です。
  この行はTextBlockでなくVerbatimです。
* そしてこの行はListの行です。(正確にはListItemの中のTextBlockの行でも
  あるのですが)

この例は次のようにフォーマットされます。

これはTextBlockです。 TextBlockの2行目の行です。

この行はTextBlockでなくVerbatimです。
  • そしてこの行はListの行です。(正確にはListItemの中のTextBlockの行でも あるのですが)
Verbatim

Rubyスクリプトを引用するのにVerbatimを用いる事ができます。Verbatimは Baselineより深いインデントを持つSTRINGLINEで構成されます。 Verbatimは"*"や"(1)"や":"といった特殊文字をHead Charとして持つ行も含む事ができますが、それらは最初の行には置く事 ができません。最初の行にあるときにはListと見なされます。Verbatim は最初の行より浅いインデントの行も含みません。VerbatimはWHITELINE を含める事ができます。

InlineはVerbatim内では使えません。

Example:
 これはVerbatimです。
   最初の行より深いインデントを持っても、同じVerbatimの行になります。
 * この行はListに見えますが、Verbatimです。
しかしこの行は最初の行よりも浅くインデントされているので、別のVerbatim
の行になります。

この例が次のようにフォーマットされます。

これはVerbatimです。
  最初の行より深いインデントを持っても、同じVerbatimの行になります。
* この行はListに見えますが、Verbatimです。
しかしこの行は最初の行よりも浅くインデントされているので、別のVerbatim
の行になります。
List

Listは特殊なBlockです。Listは複数のListItemから構成され、ListItem は複数のBlockから構成されます。したがって、ListはBlockを内部に含む事が できます。含む事のできるBlockにはList自身も含みます。*3

ListItemはWHITELINEを含む事ができますが、TextBlockは 持てません。そのため、WHITELINEを間にはさむ事によって複数のTextBlock をListItem内部に置く事ができます。

Listには"ItemList"、"EnumList"、"DescList", "MethodListの4種類があります。

ItemList

ItemListは単純な番号付されないListです。ItemListItemは"*"という Head Charの行で始まります。ItemListItemの最初のBlockは必ず TextBlockになります。

Example:
* 親Listの最初のItem
    * 子Listの最初のItem
    * 子Listの2番目のItem
  親ListのItemに含まれるTextBlock

下のようにフォーマットされます。

  • 親Listの最初のItem

    • 子Listの最初のItem
    • 子Listの2番目のItem

    親ListのItemに含まれるTextBlock

EnumList

EnumListは番号付されたListです。EnumListItemは"num"(num は整数)というHead Charの行ではじまります。他の点ではEnumListは ItemListと同じです。

Example:
(1) 親Listの最初のItem
      * 子ListとなるItemList
(2) 親Listの2番目のItem
(10) 番号は無視されます。

次のようにフォーマットされます。

  1. 親Listの最初のItem
    • 子ListとなるItemList
  2. 親Listの2番目のItem
  3. 番号は無視されます。
DescList

DescListは用語説明のためのListです。DescListItemは2つの部分からなります。 1つはTermパートでもう1つはDescriptionパートです。TermパートはReference のLabelとして使われます。

Termパートは":"というHead Charの行からなります。Termパートの 行はインデントできることを除くとTermパートはHeadlineと同様です。

DescriptionパートはTermパートの次の行からはじまります。Descriptionパート のBaselineはTermパートの(Head Charを除いた)テキスト部分と 同じかより深くないといけません。例えば次の例は間違っています。

Example:
:   |Term
  |Description.

Descriptionぱーとは複数のBlockを含む事ができます。Listを 最初のBlockとすることもできます。TermパートはInlineを含む事が できますが、ReferenceとFootnoteは例外です。

Example:
:Term
   Descriptionの最初の行
   2番目の行
:Term2
   * Listも含む事ができます
   * ...

次のようにフォーマットされます。

Term
Descriptionの最初の行 2番目の行
Term2
  • Listも含む事ができます
  • ...
MethodList

MethodListはメソッドの説明のための特殊なタイプのDescListです。 ほとんどの点でMethodListはDescListと同様ですが、Labelの規則 は違っています。RDフォーマッタはMethodListのTermパートがなんらかの Rubyのあるクラスのメソッドや定数やCの関数プロトタイプといったような プログラムのコードであると知っています。そのため、MethodListは メソッドの引数のように見える部分を除いた上でLabelとなります。詳細は LabelとReferenceを見てください。

MethodListItemはDescListと同様にTermパートとDescription パートを持ちます。Termパートは"---"というHead Char の行でなり、DescriptionパートはTextBlockVerbatimListを含む事ができます。しかし、逆にMethodListをList の中に置くべきではありません。RDは将来的にはこれを禁止するかも しれません。

Example:
--- Array#each {|i| ... } # => Labelは"Array#each"
      各項目に対してブロックを評価する。
--- Array#index(val) # => Labelは"Array#index"
      ((|val|))と同じ値である最初の項目を返す。同じ項目が無いときには
      (({nil}))を返す。

この例が次のようにフォーマットされます。

Array#each {|i| ... }
各項目に対してブロックを評価する。
Array#index(val)
valと同じ値である最初の項目を返す。同じ項目が無いときには nilを返す。

フォーマッタのいくつかはMethodListのTermパートに書かれているのはRuby のメソッドや定数などであると仮定しています。そういったフォーマッタでは MethodListのTermパートをインテリジェントに扱う事ができますが、そのため には特定の慣習にしたがってRDを書く必要があります。

標準的なRubyクラスリファレンスのための慣習として次のようなものが提案さ れています。

インスタンスメソッド

クラスClassのインスタンスメソッドmethod

Class#method(its params  ...) { parameter block }
クラスメソッド(クラスの特異メソッド)

クラスClassのクラスメソッドmethod

Class.method(its params ...) { parameter block }
クラス定数

クラスClassの定数Const

Class::Const
関数メソッド

関数func

function#func(its params ...) { parameter block }

Rubyはいくつかの特殊な文字(e.g. [], []=, +, -, <<, ...)はメソッドの名前 (識別子)として使います。この時、Rubyインタプリタはこれらのメソッドの パースを普通のメソッドとは違ったやりかた(演算子メソッド)で行います。 しかし、この慣習ではこれらの演算子メソッドも同じように書きます。

Example:
  --- Array#[](key)
        ((|key|))に対応する値を返す。
  --- Array#[]=(key, value)
        ((|key|))の場所に((|value|))を格納する。
  --- Array#+(other)
        2つの(({Array}))を結合してそれを返します。

Inline

InlineはTextBlockHeadlineDescListのTermパートの 中で使う事ができます。カッコを使ったマークアップがInlineに使われます。 Inline同士は互いに入れ子にできます。

次のInlineの一覧では左側に書式を、右側にフォーマット後の様子を表示 しています。

((*Em*)) => Em
強調
(({while gets...})) => while gets...
プログラムのコード
((|var|)) => var
メタ変数*4
((%ruby -v%)) => ruby -v
キーボード
((:Term:))

=> Term

インデクスやキーワードとなる用語の指定

((<Identity or URL>))

=> Indentity or URL

参照。詳しくはLabelとReferenceを見てください。

((-Footnote-))

=> *5

脚注

(('verb')) => verb
Inlineのvarbatim(フォーマット抑制)

LabelとReference

ReferenceにはLabelが必要です。RDではHeadlineのタイトルとDescListMethodListのTermパートだけがLabelとなります。したがって、各々の Headlineには違うタイトルをつけてあげなくてはなりません。この問題の きちんとした解決策はまだ見付かっていません。

どのようにLabelがつけられるか

HeadlineのタイトルとDescListMethodListのTermパートが Labelとして使われます。しかし、Inlineが含まれるために、それらが そのままLabelとして使われる、というほど単純ではありません。

第一に、MethodListはLabel付けにおいてはやや特殊です。MethodList のTermパートはInlineを含みませんが、その代わりRDではMethodList のTermパートはメソッドリファレンスやそれに類似の物とみなされますので、次の ようなルールでラベルが付けられます。

  1. "("や"{"の前にあるテキストだけがラベルと見なされる。*6

次の例を見れば、どのようにルールが適用されているかわかるでしょう。 "# =>"より右にあるのがMethodListのTermパートから抽出された Labelです。

Example:
  --- Array.new([size[, val]]) # => Array.new
  --- Array#[]=(key, val) # => Array#[]=
  --- Array#each { ... } # => Array#each
  --- void rb_define_method(VALUE class, ...) # => void rb_define_method

次に、HeadlineのタイトルやDescListのTermパートの場合には、この ような特別なルールはありませんが、Inlineを含む事があるので、Inline に用いるカッコを取り除くためのルールがあります。

  1. どんなInline修飾もLabelには影響しません。したがって、

    = ((*Headline*))
    と
      = Headline
    は共に"Headline"とLabelが決まります。
  2. しかし、Labelを抽出する際にはInlineの開始カッコの後ろと終端カッコ の前にある空白文字は取り除かれます。したがって、

    = ((* Headline  *))

    = ((*Headline*))

    も"Headline"とLabelがつけられます。

Reference

LabelのつけられたElementはReferenceによって参照できます。Referenceは ((<...>))というカッコで修飾されるInlineです。

最も簡単なReferenceの使用法は、単にLabelをそのカッコの中に書けばよいのです。

((<Label>))

これは"Label"というLabelに対する参照となります。また、フォーマッタによる 出力では"Label"というテキストが表示にも使われます。例: Label*7

URLによって示されたリソースを参照するには次のように書きます。

((<URL:http://www.ruby-lang.org/en/raa.html>))

可能ならRDフォーマッタはURLを次のようにハイパーリンクします。例: <URL:http://www.ruby-lang.org/en/raa.html>.

Labelとは違うテキストを表示に使いたい時には次のように書きます。

((<Text for display|Label>))

"Text for display"が表示用のテキストとして使われ、"Label"がLabelとして 使われます。例: Text for display

表示用のテキストはInlineを含む事ができます。しかし、Footnoteと Reference自身を含む事はできません。

Reference内では"|"や"/"は特殊文字なのでこれらを使いたい時には、それを含む 部分ごとダブルクオートで囲ってやらないといけません。これはReference内のどの 部分でも同じです。

((<"Bar | inside display text"|Label>))

Bar | inside display text

表示用のテキストはURLへのReferenceにも使う事ができます。

((<Ruby Application Archive|URL:http://www.ruby-lang.org/en/raa.html>))

Ruby Application Archive

表示用のテキストが無い場合には代わりにLabelにInlineを使えます。

((<((*Label*))>))

Label

Footnotes

*1もし他のドキュメントフォーマットに興味があるなら、例えば rubyapi2 <URL:http://www.ueda.info.waseda.ac.jp/~igarashi/ruby/xml.html#rubyapi2> などを見るといいでしょう。これはRuby/Gtkのような大規模ライブラリのドキュメン ト向けに作られています。
*2訳注: RDの文法用語についてはあ えて日本語訳をあてませんでした。
*3HeadlineIncludeはList内部に持てません。
*4 Varについての詳しい説明はtexinfo.texiの該当部分にあります。
*5Footnote
*6 "(...)"の内部のテキストはメソッドの引数だと見なされ、 "{...}"の内部のテキストはメソッドのブロックと見なされるのです。
*7 "Label"というLabelのついたElementが無いのでおそらくReferenceの様には 見えないでしょう。