diff --git a/src/lib/tabwriter/tabwriter.go b/src/lib/tabwriter/tabwriter.go index cc20294e0f1..a2015eb2fdd 100644 --- a/src/lib/tabwriter/tabwriter.go +++ b/src/lib/tabwriter/tabwriter.go @@ -99,8 +99,7 @@ type Writer struct { cellwidth int; padding int; padbytes [8]byte; - align_left bool; - filter_html bool; + flags uint; // current state html_char byte; // terminating char of html tag/entity, or 0 ('>', ';', or 0) @@ -144,6 +143,18 @@ func (b *Writer) addLine() { } +// Formatting can be controlled with these flags. +const ( + // Ignore html tags and treat entities (starting with '&' + // and ending in ';') as single characters (width = 1). + FilterHTML = 1 << iota; + + // Force right-alignment of cell content. + // Default is left-alignment. + AlignRight; +) + + // A Writer must be initialized with a call to Init. The first parameter (output) // specifies the filter output. The remaining parameters control the formatting: // @@ -155,11 +166,9 @@ func (b *Writer) addLine() { // and cells are left-aligned independent of align_left // (for correct-looking results, cellwidth must correspond // to the tab width in the viewer displaying the result) -// align_left alignment of cell content -// filter_html ignores html tags and treats entities (starting with '&' -// and ending in ';') as single characters (width = 1) +// flags formatting control // -func (b *Writer) Init(output io.Write, cellwidth, padding int, padchar byte, align_left, filter_html bool) *Writer { +func (b *Writer) Init(output io.Write, cellwidth, padding int, padchar byte, flags uint) *Writer { if cellwidth < 0 { panic("negative cellwidth"); } @@ -172,8 +181,12 @@ func (b *Writer) Init(output io.Write, cellwidth, padding int, padchar byte, ali for i := len(b.padbytes) - 1; i >= 0; i-- { b.padbytes[i] = padchar; } - b.align_left = align_left || padchar == '\t'; // tab enforces left-alignment - b.filter_html = filter_html; + if padchar == '\t' { + // tab enforces left-alignment + t := ^AlignRight; // TODO 6g bug + flags &= uint(t); + } + b.flags = flags; b.buf.Init(1024); b.lines_size.Init(0); @@ -256,7 +269,9 @@ func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int, err *os.Error) for j := 0; j < line_size.Len(); j++ { s, w := line_size.At(j), line_width.At(j); - if b.align_left { + switch { + default: // align left + err = b.write0(b.buf.slice(pos, pos + s)); if err != nil { goto exit; @@ -269,7 +284,7 @@ func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int, err *os.Error) } } - } else { // align right + case b.flags & AlignRight != 0: // align right if j < b.widths.Len() { err = b.writePadding(w, b.widths.At(j)); @@ -433,7 +448,7 @@ func (b *Writer) Write(buf []byte) (written int, err *os.Error) { } case '<', '&': - if b.filter_html { + if b.flags & FilterHTML != 0 { b.append(buf[i0 : i]); i0 = i; b.width += unicodeLen(b.buf.slice(b.pos, b.buf.Len())); @@ -467,9 +482,9 @@ func (b *Writer) Write(buf []byte) (written int, err *os.Error) { } -// New allocates and initializes a new tabwriter.Writer. +// NewWriter allocates and initializes a new tabwriter.Writer. // The parameters are the same as for the the Init function. // -func New(writer io.Write, cellwidth, padding int, padchar byte, align_left, filter_html bool) *Writer { - return new(Writer).Init(writer, cellwidth, padding, padchar, align_left, filter_html) +func NewWriter(writer io.Write, cellwidth, padding int, padchar byte, flags uint) *Writer { + return new(Writer).Init(writer, cellwidth, padding, padchar, flags) } diff --git a/src/lib/tabwriter/tabwriter_test.go b/src/lib/tabwriter/tabwriter_test.go index d06c409f58c..5579327495f 100644 --- a/src/lib/tabwriter/tabwriter_test.go +++ b/src/lib/tabwriter/tabwriter_test.go @@ -71,12 +71,12 @@ func verify(t *testing.T, w *tabwriter.Writer, b *buffer, src, expected string) } -func check(t *testing.T, tabwidth, padding int, padchar byte, align_left, filter_html bool, src, expected string) { +func check(t *testing.T, tabwidth, padding int, padchar byte, flags uint, src, expected string) { var b buffer; b.init(1000); var w tabwriter.Writer; - w.Init(&b, tabwidth, padding, padchar, align_left, filter_html); + w.Init(&b, tabwidth, padding, padchar, flags); // write all at once b.clear(); @@ -105,109 +105,109 @@ func check(t *testing.T, tabwidth, padding int, padchar byte, align_left, filter func Test(t *testing.T) { check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "", "" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "\n\n\n", "\n\n\n" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "a\nb\nc", "a\nb\nc" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "\t", // '\t' terminates an empty cell on last line - nothing to print "" ); check( - t, 8, 1, '.', false, false, + t, 8, 1, '.', tabwriter.AlignRight, "\t", // '\t' terminates an empty cell on last line - nothing to print "" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "*\t*", "**" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "*\t*\n", "*.......*\n" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "*\t*\t", "*.......*" ); check( - t, 8, 1, '.', false, false, + t, 8, 1, '.', tabwriter.AlignRight, "*\t*\t", ".......**" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "\t\n", "........\n" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "a) foo", "a) foo" ); check( - t, 8, 1, ' ', true, false, + t, 8, 1, ' ', 0, "b) foo\tbar", // "bar" is not in any cell - not formatted, just flushed "b) foobar" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "c) foo\tbar\t", "c) foo..bar" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "d) foo\tbar\n", "d) foo..bar\n" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "e) foo\tbar\t\n", "e) foo..bar.....\n" ); check( - t, 8, 1, '.', true, true, + t, 8, 1, '.', tabwriter.FilterHTML, "e) f<o\tbar\t\n", "e) f<o..bar.....\n" ); check( - t, 8, 1, '*', true, false, + t, 8, 1, '*', 0, "Hello, world!\n", "Hello, world!\n" ); check( - t, 0, 0, '.', true, false, + t, 0, 0, '.', 0, "1\t2\t3\t4\n" "11\t222\t3333\t44444\n", @@ -216,19 +216,19 @@ func Test(t *testing.T) { ); check( - t, 5, 0, '.', true, false, + t, 5, 0, '.', 0, "1\t2\t3\t4\n", "1....2....3....4\n" ); check( - t, 5, 0, '.', true, false, + t, 5, 0, '.', 0, "1\t2\t3\t4\t\n", "1....2....3....4....\n" ); check( - t, 8, 1, '.', true, false, + t, 8, 1, '.', 0, "本\tb\tc\n" "aa\t\u672c\u672c\u672c\tcccc\tddddd\n" "aaa\tbbbb\n", @@ -239,7 +239,7 @@ func Test(t *testing.T) { ); check( - t, 8, 1, ' ', false, false, + t, 8, 1, ' ', tabwriter.AlignRight, "a\tè\tc\t\n" "aa\tèèè\tcccc\tddddd\t\n" "aaa\tèèèè\t\n", @@ -250,7 +250,7 @@ func Test(t *testing.T) { ); check( - t, 2, 0, ' ', true, false, + t, 2, 0, ' ', 0, "a\tb\tc\n" "aa\tbbb\tcccc\n" "aaa\tbbbb\n", @@ -261,7 +261,7 @@ func Test(t *testing.T) { ); check( - t, 8, 1, '_', true, false, + t, 8, 1, '_', 0, "a\tb\tc\n" "aa\tbbb\tcccc\n" "aaa\tbbbb\n", @@ -272,7 +272,7 @@ func Test(t *testing.T) { ); check( - t, 4, 1, '-', true, false, + t, 4, 1, '-', 0, "4444\t日本語\t22\t1\t333\n" "999999999\t22\n" "7\t22\n" @@ -291,7 +291,7 @@ func Test(t *testing.T) { ); check( - t, 4, 3, '.', true, false, + t, 4, 3, '.', 0, "4444\t333\t22\t1\t333\n" "999999999\t22\n" "7\t22\n" @@ -310,7 +310,7 @@ func Test(t *testing.T) { ); check( - t, 8, 1, '\t', true, true, + t, 8, 1, '\t', tabwriter.FilterHTML, "4444\t333\t22\t1\t333\n" "999999999\t22\n" "7\t22\n" @@ -329,7 +329,7 @@ func Test(t *testing.T) { ); check( - t, 0, 2, ' ', false, false, + t, 0, 2, ' ', tabwriter.AlignRight, ".0\t.3\t2.4\t-5.1\t\n" "23.0\t12345678.9\t2.4\t-989.4\t\n" "5.1\t12.0\t2.4\t-7.0\t\n"