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と同じ深さにインデントされたSTRINGLINEはTextBlock に属す行となります。一方Baselineより深くインデントされたSTRINGLINE はVerbatimの行です。
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より深いSTRINGLINEは Verbatimの行とみなされます。
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) 番号は無視されます。
次のようにフォーマットされます。
- 親Listの最初のItem
- 子ListとなるItemList
- 親Listの2番目のItem
- 番号は無視されます。
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も含む事ができます * ...
次のようにフォーマットされます。
MethodList
MethodListはメソッドの説明のための特殊なタイプのDescListです。 ほとんどの点でMethodListはDescListと同様ですが、Labelの規則 は違っています。RDフォーマッタはMethodListのTermパートがなんらかの Rubyのあるクラスのメソッドや定数やCの関数プロトタイプといったような プログラムのコードであると知っています。そのため、MethodListは メソッドの引数のように見える部分を除いた上でLabelとなります。詳細は LabelとReferenceを見てください。
MethodListItemはDescListと同様にTermパートとDescription
パートを持ちます。Termパートは"---
"というHead Char
の行でなり、DescriptionパートはTextBlockやVerbatim
、Listを含む事ができます。しかし、逆に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はTextBlockやHeadline、DescListの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のタイトルとDescList やMethodListのTermパートだけがLabelとなります。したがって、各々の Headlineには違うタイトルをつけてあげなくてはなりません。この問題の きちんとした解決策はまだ見付かっていません。
どのようにLabelがつけられるか
HeadlineのタイトルとDescListやMethodListのTermパートが Labelとして使われます。しかし、Inlineが含まれるために、それらが そのままLabelとして使われる、というほど単純ではありません。
第一に、MethodListはLabel付けにおいてはやや特殊です。MethodList のTermパートはInlineを含みませんが、その代わりRDではMethodList のTermパートはメソッドリファレンスやそれに類似の物とみなされますので、次の ようなルールでラベルが付けられます。
- "
(
"や"{
"の前にあるテキストだけがラベルと見なされる。*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 に用いるカッコを取り除くためのルールがあります。
どんなInline修飾もLabelには影響しません。したがって、
= ((*Headline*))
と = Headline は共に"Headline"とLabelが決まります。
しかし、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>))
表示用のテキストが無い場合には代わりにLabelにInlineを使えます。
((<((*Label*))>))
Label
Footnotes
*1もし他のドキュメントフォーマットに興味があるなら、例えば
rubyapi2
<URL:http://www.ueda.info.waseda.ac.jp/~igarashi/ruby/xml.html#rubyapi2>
などを見るといいでしょう。これはRuby/Gtkのような大規模ライブラリのドキュメン
ト向けに作られています。
*2訳注: RDの文法用語についてはあ
えて日本語訳をあてませんでした。
*3Headline
やIncludeはList内部に持てません。
*4 Varについての詳しい説明はtexinfo.texiの該当部分にあります。
*5Footnote
*6
"(...)
"の内部のテキストはメソッドの引数だと見なされ、
"{...}
"の内部のテキストはメソッドのブロックと見なされるのです。
*7
"Label"というLabelのついたElementが無いのでおそらくReferenceの様には
見えないでしょう。