import "tabwriter"

tabwriterパッケージは、タブによって指定されるカラムを整形されたテキストに変換するための、書き込みフィルタ(tabwriter.Writer)を実装しています。

このパッケージでは、http://nickgravgaard.com/elastictabstops/index.htmlに記述されているElastic Tabstops algorithmを使用しています。

パッケージファイル

tabwriter.go

定数

これらのフラグで書式を制御できます。

const (
    // htmlタグを無効にして、エンティティ('&'で始まり、';'で終わる)を
    // 一文字(幅 = 1)として扱う。
    FilterHTML uint = 1 << iota

    // テキストのエスケープされた部分をそのまま処理せずに、
    // 囲んでいるエスケープ文字を取り除きます。
    StripEscape

    // セルの内容を右寄せ。
    // デフォルトは左寄せ。
    AlignRight

    // 最初の空のカラムを、存在しなかったように扱う
    DiscardEmptyColumns

    // カラムのインデント(左側の空のセルのパディング)に常にタブを使用する。
    // padcharは無視される。
    TabIndent

    // カラム間に垂直線('|')を出力する。(フォーマット後)
    // 破棄されたカラムはゼロ幅のカラム("||")として出力される。
    Debug
)

テキストの一部分をエスケープするときは、エスケープ文字で囲みます。たとえば、「このタブを無視: \xff\t\xff」とすると、この文字列内のタブコードはセルの終了とはみなされず、出力の際に一文字分の幅を持つ文字として計算されます。

この0xffという値を使っているのは、正しいUTF-8シーケンス内で、この値が現れることがないためです。

const Escape = '\xff'

Writer型

Writerは、入力内のタブで区切られたカラムの前後にパディングを挿入し、整形したテキストを出力するフィルターです。

Writerは入力バイトを、タブ(水平または垂直)または改行(LFまたはFF)文字で終了するセルから成るUTF-8エンコードされたテキストとして処理します。カラムは隣接する行のセルによって構成されます。Writerはカラム内のすべてのセルに同じ幅を持たせるために必要に応じてパッドを挿入し、カラムを縦一列に整列します。tabwidthで幅が指定されるタブを除き、他のすべての文字は同じ幅を持つとみなされます。セルはタブで区切られるのではなく、タブで終わることに注意してください。行の終わりにタブ以外のテキストがあっても、カラムセルは形成しません。

Writerは、すべてのUnicodeコードポイントが同じ幅を持つと仮定しています。これは特定のフォントにおいては正しくはありません。

DiscardEmptyColumnsがセットされているときは、垂直(ソフト)タブによって終了された空のカラムは破棄されます。ただし、水平(ハード)タブによって終了されるカラムは、このフラグの影響を受けません。

WriterがHTMLをフィルターするよう設定したときは、HTMLタグは幅0、エンティティは幅1であるとみなされます。

テキストの一部分をエスケープ文字で囲むことによってエスケープ可能です。tabwriterは、テキスト内のエスケープされた部分をそのまま処理します。すなわち、エスケープされたテキスト内のタブや改行が解釈されることはありません。StripEscapeフラグがセットされているときは、出力からエスケープ文字が取り除かれます。セットされていなければ、エスケープ文字もそのまま出力されます。フォーマット化を考慮し、エスケープされたテキストの幅は、常にエスケープ文字を除外して算出されます。

フォームフィード文字(‘\f’)は、改行文字のように振舞いますが、現在の行のすべてのカラムを終了させる働き(Flushの呼び出しと同じ)をします。そして次の行のセルから、また新しいカラムが始まります。HTMLタグ内、またはエスケープされた箇所以外のフォームフィード文字は、改行として出力されます。

ある行の適切な間隔は、その先の行のセルを調べないと判断できないので、Writerは入力を内部的にバッファリングする必要があります。そのため呼び出し側はWriteの呼び出しを終えたときに、Flushを呼び出さなければなりません。

type Writer struct {
    // contains unexported fields
}

NewWriter関数

func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer

NewWriterは、新しいtabwriter.Writerをアロケートし、初期化します。このパラメータはInit関数と同じです。

(*Writer) Flush関数

func (b *Writer) Flush() (err os.Error)

Flushは、Writer内でバッファリングされたデータを確実に出力するため、最後のWrite呼び出しの後に必ず呼び出さなくてはなりません。最後に不完全なエスケープ文字列があっても、フォーマットの際には完全なエスケープであるとみなされます。

(*Writer) Init関数

func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer

Writerは、Initを呼び出して初期化する必要があります。最初のパラメータ(output)には、フィルターの出力先を指定します。その他のパラメータでフォーマットを制御します。

minwidth	パディングを含めた最小のセル幅
tabwidth	タブ文字の幅(スペースの数と等しい)
padding		幅を計算する前にセルに加えるパディング
padchar		パディングに使用するASCII文字
		padchar == '\t'のとき、Writerは'\t'のフォーマット出力時の幅が
		tabwidthと同じであるとみなし、かつalign_leftとは関係なくセルは
		左寄せになります。
		(正しく表示できるよう、tabwidthの値は結果を表示させるビューワの
		タブ幅と合わせてください)
flags		フォーマット制御

タブで区切られたカラムをタブ幅8でフォーマットする例です。

b.Init(w, 8, 1, 8, '\t', 0);

スペースで区切られたカラムを、カラム間を最小4つのスペースでフォーマットする例です。

b.Init(w, 0, 4, 8, ' ', 0);

(*Writer) Write関数

func (b *Writer) Write(buf []byte) (n int, err os.Error)

Writeは、bufをライターbに書き込みます。ラッピングしている出力ストリームへの書き込み中に発生したエラーのうち、返されるのはひとつだけです。