34.1. "formatter" --- 汎用の出力書式化機構
******************************************

このモジュールでは、二つのインタフェース定義を提供しており、それらの各
インタフェースについて複数の実装を提供しています。 *formatter* インタ
フェースは "htmllib" モジュールの "HTMLParser" クラスで使われており、
*writer*  インタフェースは formatter インタフェースを使う上で必要です
。

formatter オブジェクトはある抽象化された書式イベントの流れを writer オ
ブジェクト上の特定の出力イベントに変換します。formatter はいくつかのス
タック構造を管理することで、writer  オブジェクトの様々な属性を変更した
り復元したりできるようにしています; このため、writer は相対的な変更や
"元に戻す" 操作を処理できなくてもかまいません。writer の特定のプロパテ
ィのうち、formatter オブジェクトを介して制御できるのは、水平方向の字揃
え、フォント、そして左マージンの字下げです。任意の、非排他的なスタイル
設定を writer に提供するためのメカニズムも提供されています。さらに、段
落分割のように、可逆でない書式化イベントの機能を提供するインタフェース
もあります。

writer オブジェクトはデバイスインタフェースをカプセル化します。ファイ
ル形式のような抽象デバイスも物理デバイス同様にサポートされています。こ
こで提供されている実装内容はすべて抽象デバイス上で動作します。デバイス
インタフェースは formatter オブジェクトが管理しているプロパティを設定
し、データを出力端に書き込めるようにします。


34.1.1. formatter インタフェース
================================

formatter を作成するためのインタフェースは、インスタンス化しようとする
個々の formatter クラスに依存します。以下で解説するのは、インスタンス
化された全ての formatter がサポートしなければならないインタフェースで
す。

モジュールレベルではデータ要素を一つ定義しています:

formatter.AS_IS

   後に述べる "push_font()" メソッドでフォント指定をする時に使える値で
   す。また、その他の "push_property()" メソッドの新しい値として使うこ
   とができます。"AS_IS" の値をスタックに置くと、どのプロパティが変更
   されたかの追跡を行わずに、対応する "pop_property()" メソッドが呼び
   出されるようになります。

formatter インスタンスオブジェクトには以下の属性が定義されています:

formatter.writer

   formatter とやり取りを行う writer インスタンスです。

formatter.end_paragraph(blanklines)

   開かれている段落があれば閉じ、次の段落との間に少なくとも
   *blanklines* が挿入されるようにします。

formatter.add_line_break()

   強制改行挿入します。既に強制改行がある場合は挿入しません。論理的な
   段落は中断しません。

formatter.add_hor_rule(*args, **kw)

   出力に水平罫線を挿入します。現在の段落に何らかのデータがある場合、
   強制改行が挿入されますが、論理的な段落は中断しません。引数とキーワ
   ードは writer の "send_line_break()" メソッドに渡されます。

formatter.add_flowing_data(data)

   空白を折りたたんで書式化しなければならないデータを提供します。空白
   の折りたたみでは、直前や直後の "add_flowing_data()" 呼び出しに入っ
   ている空白も考慮されます。このメソッドに渡されたデータは出力デバイ
   スで行末の折り返し (word-wrap) されるものと想定されています。出力デ
   バイスでの要求やフォント情報に応じて、writer オブジェクトでも何らか
   の行末折り返しが行われなければならないので注意してください。

formatter.add_literal_data(data)

   変更を加えずに writer に渡さなければならないデータを提供します。改
   行およびタブを含む空白を *data* の値にしても問題ありません。

formatter.add_label_data(format, counter)

   現在の左マージン位置の左側に配置されるラベルを挿入します。このラベ
   ルは箇条書き、数字つき箇条書きの書式を構築する際に使われます。
   *format* の値が文字列の場合、整数の値 *counter* の書式指定として解
   釈されます。 *format* の値が文字列の場合、整数の値をとる *counter*
   の書式化指定として解釈されます。書式化された文字列はラベルの値にな
   ります; *format* が文字列でない場合、ラベルの値として直接使われます
   。ラベルの値は writer の "send_label_data()" メソッドの唯一の引数と
   して渡されます。非文字列のラベル値をどう解釈するかは関連付けられた
   writer に依存します。

   書式化指定は文字列からなり、counter の値と合わせてラベルの値を算出
   するために使われます。書式文字列の各文字はラベル値にコピーされます
   。このときいくつかの文字は counter 値を変換を指すものとして認識され
   ます。特に、文字 "'1'" はアラビア数字の counter 値を表し、"'A'" と
   "'a'" はそれぞれ大文字および小文字のアルファベットによる counter 値
   を表し、"'I'" と "'i'" はそれぞれ大文字および小文字のローマ数字によ
   る counter 値を表します。アルファベットおよびローマ字数字への変換の
   際には、counter の値はゼロ以上である必要があるので注意してください
   。

formatter.flush_softspace()

   以前の "add_flowing_data()" 呼び出しでバッファされている出力待ちの
   空白を、関連付けられている writer オブジェクトに送信します。このメ
   ソッドは writer オブジェクトに対するあらゆる直接操作の前に呼び出さ
   なければなりません。

formatter.push_alignment(align)

   新たな字揃え (alignment) 設定を字揃えスタックの上にプッシュします。
   変更を行いたくない場合には "AS_IS" にすることができます。字揃え設定
   値が以前の設定から変更された場合、writer の  "new_alignment()" メソ
   ッドが *align* の値と共に呼び出されます。

formatter.pop_alignment()

   以前の字揃え設定を復元します。

formatter.push_font((size, italic, bold, teletype))

   writer オブジェクトのフォントプロパティのうち、一部または全てを変更
   します。 "AS_IS" に設定されていないプロパティは引数で渡された値に設
   定され、その他の値は現在の設定を維持します。writer の "new_font()"
   メソッドは完全に設定解決されたフォント指定で呼び出されます。

formatter.pop_font()

   以前のフォント設定を復元します。

formatter.push_margin(margin)

   左マージンのインデント数を一つ増やし、論理タグ *margin* を新たなイ
   ンデントに関連付けます。マージンレベルの初期値は "0" です。変更され
   た論理タグの値は真値とならなければなりません;  "AS_IS" 以外の偽の値
   はマージンの変更としては不適切です。

formatter.pop_margin()

   以前のマージン設定を復元します。

formatter.push_style(*styles)

   任意のスタイル指定をスタックにプッシュします。全てのスタイルはスタ
   イルスタックに順番にプッシュされます。 "AS_IS" 値を含み、スタック全
   体を表すタプルは writer の "new_styles()" メソッドに渡されます。

formatter.pop_style([n=1])

   "push_style()" に渡された最新 *n* 個のスタイル指定をポップします。
   "AS_IS" 値を含み、変更されたスタックを表すタプルは writer の
   "new_styles()" メソッドに渡されます。

formatter.set_spacing(spacing)

   writer の割り付けスタイル (spacing style) を設定します。

formatter.assert_line_data([flag=1])

   現在の段落にデータが予期せず追加されたことを formatter に知らせます
   。このメソッドは writer を直接操作した際に使わなければなりません。
   writer 操作の結果、出力の末尾が強制改行となった場合、オプションの
   *flag* 引数を偽に設定することができます。


34.1.2. formatter 実装
======================

このモジュールでは、formatter オブジェクトに関して二つの実装を提供して
います。ほとんどのアプリケーションではこれらのクラスを変更したりサブク
ラス化することなく使うことができます。

class formatter.NullFormatter([writer])

   何も行わない formatter です。 *writer* を省略すると、 "NullWriter"
   インスタンスが生成されます。 "NullFormatter" インスタンスは、writer
   のメソッドを全く呼び出しません。writer へのインタフェースを実装する
   場合にはこのクラスのインタフェースを継承する必要がありますが、実装
   を継承する必要は全くありません。

class formatter.AbstractFormatter(writer)

   標準の formatter です。この formatter 実装は広範な writer で適用で
   きることが実証されており、ほとんどの状況で直接使うことができます。
   高機能の WWW ブラウザを実装するために使われたこともあります。


34.1.3. writer インタフェース
=============================

writer を作成するためのインタフェースは、インスタンス化しようとする個
々の writer クラスに依存します。以下で解説するのは、インスタンス化され
た全ての writer がサポートしなければならないインタフェースです。ほとん
どのアプリケーションでは "AbstractFormatter" クラスを formatter として
使うことができますが、通常 writer はアプリケーション側で与えなければな
らないので注意してください。

writer.flush()

   バッファに蓄積されている出力データやデバイス制御イベントをフラッシ
   ュします。

writer.new_alignment(align)

   字揃えのスタイルを設定します。*align* の値は任意のオブジェクトを取
   りえますが、慣習的な値は文字列または "None" で、"None" は writer の
   "好む" 字揃えを使うことを表します。慣習的な *align* の値は "'left'"
   、"'center'"、"'right'"、および "'justify'" です。

writer.new_font(font)

   フォントスタイルを設定します。*font* は、デバイスの標準のフォントが
   使われることを示す "None" か、"(size, italic, bold, teletype)" の形
   式をとるタプルになります。size はフォントサイズを示す文字列になりま
   す; 特定の文字列やその解釈はアプリケーション側で定義します。
   *italic*、*bold*、および *teletype* といった値はブール値で、それら
   の属性を使うかどうかを指定します。

writer.new_margin(margin, level)

   マージンレベルを整数値 *level* に設定し、論理タグ (logical tag) を
   *margin* に設定します。論理タグの解釈は writer の判断に任されます;
   論理タグの値に対する唯一の制限は *level* が非ゼロの値の際に偽であっ
   てはならないということです。

writer.new_spacing(spacing)

   割り付けスタイル (spacing style) を *spacing* に設定します。

writer.new_styles(styles)

   追加のスタイルを設定します。 *styles* の値は任意の値からなるタプル
   です; "AS_IS" 値は無視されます。 *styles* タプルはアプリケーション
   や writer の実装上の都合により、集合としても、スタックとしても解釈
   され得ます。

writer.send_line_break()

   現在の行を改行します。

writer.send_paragraph(blankline)

   少なくとも *blankline* 空行分の間隔か、空行そのもので段落を分割しま
   す。 *blankline* の値は整数になります。 writer の実装では、改行を行
   う必要がある場合、このメソッドの呼び出しに先立って
   "send_line_break()" の呼び出しを受ける必要あります; このメソッドに
   は段落の最後の行を閉じる機能は含まれておらず、段落間に垂直スペース
   を空ける役割しかありません。

writer.send_hor_rule(*args, **kw)

   水平罫線を出力デバイスに表示します。このメソッドへの引数は全てアプ
   リケーションおよび writer 特有のものなので、注意して解釈する必要が
   あります。このメソッドの実装では、すでに改行が "send_line_break()"
   によってなされているものと仮定しています。

writer.send_flowing_data(data)

   行端が折り返され、必要に応じて再割り付け解析を行った (re-flowed)
   文字データを出力します。このメソッドを連続して呼び出す上では、
   writer は複数の空白文字は単一のスペース文字に縮約されていると仮定す
   ることがあります。

writer.send_literal_data(data)

   すでに表示用に書式化された文字データを出力します。これは通常、改行
   文字で表された改行を保存し、新たに改行を持ち込まないことを意味しま
   す。 "send_formatted_data()" インタフェースと違って、データには改行
   やタブ文字が埋め込まれていてもかまいません。

writer.send_label_data(data)

   可能ならば、*data* を現在の左マージンの左側に設定します。*data* の
   値には制限がありません; 文字列でない値の扱い方はアプリケーションや
   writer に完全に依存します。このメソッドは行の先頭でのみ呼び出されま
   す。


34.1.4. writer 実装
===================

このモジュールでは、3 種類の writer オブジェクトインタフェース実装を提
供しています。ほとんどのアプリケーションでは、 "NullWriter" から新しい
writer クラスを派生する必要があるでしょう。

class formatter.NullWriter

   インタフェース定義だけを提供する writer クラスです; どのメソッドも
   何ら処理を行いません。このクラスは、メソッド実装をまったく継承する
   必要のない writer 全ての基底クラスになります。

class formatter.AbstractWriter

   この writer は formatter をデバッグするのに利用できますが、それ以外
   に利用できるほどのものではありません。各メソッドを呼び出すと、メソ
   ッド名と引数を標準出力に印字して呼び出されたことを示します。

class formatter.DumbWriter(file=None, maxcol=72)

   単純な writer クラスで *file* に渡されたファイルオブジェクトか
   *file* が "None" の場合には標準出力に出力を書き込みます。出力は
   *maxcol* で指定されたカラム数で単純な行端折り返しが行われます。この
   クラスは連続した段落を再割り付けするのに適しています。
