...

パッケージ tabwriter

import "text/tabwriter"
概要
目次

概要 ▾

tabwriter パッケージは,タブ区切りカラムを整列したテキストに変換する書き込みフィルタ (tabwriter.Writer) を実装します。

このパッケージは, http://nickgravgaard.com/elastictabstops/index.html に記載されている Elastic Tabstops アルゴリズムを使用しています。

text/tabwriter パッケージはフリーズしており,新しい機能を受け付けていません。

例 (Elastic)

コード:

// 各行の 2 番目のセルに表示されるにもかかわらず, b と d がどのように異なる列に属しているかを取得します。
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, '.', tabwriter.AlignRight|tabwriter.Debug)
fmt.Fprintln(w, "a\tb\tc")
fmt.Fprintln(w, "aa\tbb\tcc")
fmt.Fprintln(w, "aaa\t") // 末尾のタブ
fmt.Fprintln(w, "aaaa\tdddd\teeee")
w.Flush()

出力:

....a|..b|c
...aa|.bb|cc
..aaa|
.aaaa|.dddd|eeee

例 (TrailingTab)

コード:

// 3 行目には末尾のタブがないので,最後のセルは位置合わせされた列の一部ではありません。
const padding = 3
w := tabwriter.NewWriter(os.Stdout, 0, 0, padding, '-', tabwriter.AlignRight|tabwriter.Debug)
fmt.Fprintln(w, "a\tb\taligned\t")
fmt.Fprintln(w, "aa\tbb\taligned\t")
fmt.Fprintln(w, "aaa\tbbb\tunaligned") // 末尾タブなし
fmt.Fprintln(w, "aaaa\tbbbb\taligned\t")
w.Flush()

出力:

------a|------b|---aligned|
-----aa|-----bb|---aligned|
----aaa|----bbb|unaligned
---aaaa|---bbbb|---aligned|

定数

フォーマットはこれらのフラグで制御できます。

const (
    // HTML タグを無視し,エンティティ ("&" で始まり ";" で終わる) を 1 つの文字 (width = 1) として扱います。
    FilterHTML uint = 1 << iota

    // エスケープされたテキストセグメントのエスケープ文字を,テキストを変更せずにそのまま通過させるのではなく取り除きます。
    StripEscape

    // セルの内容を強制的に右揃えにします。
    // デフォルトは左揃えです。
    AlignRight

    // 空の列を最初の入力に存在しない場合と同様に処理します。
    DiscardEmptyColumns

    // padchar とは関係なく,常にインデント列にタブを使用してください (つまり,左側の先頭の空のセルのパディング) 。
    TabIndent

    // 列の間に垂直バー ('|') を表示します (フォーマット後) 。
    // 破棄された列は,幅 0 の列 ("||") として表示されます。
    Debug
)

テキストセグメントをエスケープするには,エスケープ文字で囲みます。 たとえば,この文字列内のタブ " 無視するタブ :\xff\t\xff" はセルを終了させず,書式設定のために幅 1 の単一文字を構成します。

有効な UTF-8 シーケンスに表示できないため,値 0xff が選択されました。

const Escape = '\xff'

type Writer

Writer は,入力内のタブ区切り列の周囲にパディングを挿入して出力内で整列させるフィルタです。

Writer は,着信バイトを,水平 ('\t') または垂直 ('\v') のタブ,改行 ('\n') または改ページ ('\f') で終了するセルで構成される UTF-8 エンコードテキストとして扱います。 改行も改ページも改行として機能します。

連続した行のタブ終了セルは列を構成します。 Writer は,列内のすべてのセルを同じ幅にするために必要に応じてパディングを挿入し,列を効果的に整列させます。 タブ幅を指定しなければならないタブを除いて,すべての文字が同じ幅を持つと仮定します。 列セルはタブ区切りではなくタブ区切りである必要があります。 行末のタブで終端されていない末尾テキストはセルを形成しますが,そのセルは整列列の一部ではありません。 例えば,この例では (| は水平タブを表します):

aaaa|bbb|d
aa  |b  |dd
a   |
aa  |cccc|eee

b と c は別の列にあります (b 列はずっと連続しているわけではありません) 。 d と e はまったく列に入っていません (終了タブはありませんし,列が連続することもありません) 。

Writer は,すべての Unicode コードポイントが同じ幅を持つと仮定します。 一部のフォントや,文字列に結合文字が含まれている場合,これは当てはまりません。

DiscardEmptyColumns が設定されている場合,垂直 (または "ソフト") タブで完全に終了している空の列は破棄されます。 水平 (または "ハード") タブで終了している列は,このフラグの影響を受けません。

Writer が HTML をフィルタ処理するように設定されている場合は, HTML タグとエンティティがパススルーされます。 書式設定のために,タグとエンティティの幅は 0(タグ) と 1(エンティティ) と見なされます。

テキストのセグメントは,エスケープ文字で囲むことによってエスケープすることができます。 タブライターは,エスケープされたテキストセグメントを変更せずに通過させます。 特に,セグメント内のタブや改行は解釈されません。 StripEscape フラグが設定されていると,エスケープ文字は出力から取り除かれます。 そうでなければ,それらは同様に通過します。 フォーマットの目的で,エスケープ文字の幅はエスケープ文字を除いて常に計算されます。

改ページ文字は改行のように機能しますが,現在行のすべての列も終了します (実質的に Flush を呼び出します) 。 次の行のタブで終わるセルは新しい列を始めます。 HTML タグ内またはエスケープテキストセグメント内に見つからない限り,改ページ文字は改行として出力に表示されます。

1 行の適切な間隔は将来の行のセルに依存するため, Writer は内部で入力をバッファする必要があります。 Write の呼び出しが完了したら,クライアントは Flush を呼び出す必要があります。

type Writer struct {
    // エクスポートされていないフィールドがあります
}

func NewWriter

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

NewWriter は新しい tabwriter.Writer を割り当てて初期化します。 パラメータは Init 関数の場合と同じです。

func (*Writer) Flush

func (b *Writer) Flush() error

Writer にバッファされているデータが確実に出力に書き込まれるようにするために,最後の Write 呼び出しの後に Flush を呼び出す必要があります。 末尾の不完全なエスケープシーケンスは,フォーマット目的では完全と見なされます。

func (*Writer) Init

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

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

minwidth	パディングを含めた最小セル幅
tabwidth	タブ幅 (等価のスペース数)
padding		幅を計算する前にセルに加えられたパディング
padchar		パディングに使う ASCII 文字
	padchar == '\t' の場合, Writer は,'\t' のセルの幅をフォーマットされた出力のタブ幅とみなし,セルは align_left とは無関係に左寄せになります (見栄えのする結果を得るために,タブ幅は結果を表示するビューアのタブ幅に対応している必要があります)
flags		フォーマットコントロール

コード:

w := new(tabwriter.Writer)

// タブストップを 8 にして,タブ区切りの列で書式設定します。
w.Init(os.Stdout, 0, 8, 0, '\t', 0)
fmt.Fprintln(w, "a\tb\tc\td\t.")
fmt.Fprintln(w, "123\t12345\t1234567\t123456789\t.")
fmt.Fprintln(w)
w.Flush()

// 最小幅 5 のスペースで区切られた列と少なくとも 1 つの空白の余白があり,右揃えで書式設定します (幅の広い列エントリは互いに接触しません) 。
w.Init(os.Stdout, 5, 0, 1, ' ', tabwriter.AlignRight)
fmt.Fprintln(w, "a\tb\tc\td\t.")
fmt.Fprintln(w, "123\t12345\t1234567\t123456789\t.")
fmt.Fprintln(w)
w.Flush()

出力:

a	b	c	d		.
123	12345	1234567	123456789	.

    a     b       c         d.
  123 12345 1234567 123456789.

func (*Writer) Write

func (b *Writer) Write(buf []byte) (n int, err error)

Write は buf をライターに書き込みます。 返される唯一のエラーは,内部の出力ストリームへの書き込み中に発生したエラーです。