diff --git a/src/lib/tabwriter/tabwriter.go b/src/lib/tabwriter/tabwriter.go index 2615186e7a..ec6fadad1f 100644 --- a/src/lib/tabwriter/tabwriter.go +++ b/src/lib/tabwriter/tabwriter.go @@ -138,11 +138,6 @@ func (b *Writer) Line(i int) *array.IntArray { } -func (b *Writer) LastLine() *array.IntArray { - return b.lines.At(b.lines.Len() - 1).(*array.IntArray); -} - - // debugging support func (b *Writer) Dump() { pos := 0; @@ -235,7 +230,17 @@ func (b *Writer) WriteLines(pos0 int, line0, line1 int) (pos int, err *os.Error) pos += w; } } - err = b.Write0(Newline); + + if i+1 == b.lines.Len() { + // last buffered line - we don't have a newline, so just write + // any outstanding buffered data + err = b.Write0(b.buf.a[pos : pos + b.width]); + pos += b.width; + b.width = 0; + } else { + // not the last line - write newline + err = b.Write0(Newline); + } if err != nil { goto exit; } @@ -246,18 +251,6 @@ exit: } -// TODO use utflen for correct formatting -func utflen(buf *[]byte) int { - n := 0; - for i := 0; i < len(buf); i++ { - if buf[i]&0xC0 != 0x80 { - n++ - } - } - return n -} - - func (b *Writer) Format(pos0 int, line0, line1 int) (pos int, err *os.Error) { pos = pos0; column := b.widths.Len(); @@ -336,22 +329,21 @@ func (b *Writer) Append(buf *[]byte) { i0 = i + 1; // exclude ch from (next) cell // terminate cell - b.LastLine().Push(b.width); + last := b.Line(b.lines.Len() - 1); + last.Push(b.width); b.width = 0; if ch == '\n' { - if b.LastLine().Len() == 1 { - // The last line has only one cell which does not have an - // impact on the formatting of the following lines (the + b.AddLine(); + if last.Len() == 1 { + // The previous line has only one cell which does not have + // an impact on the formatting of the following lines (the // last cell per line is ignored by Format), thus we can // flush the Writer contents. err = b.Flush(); if err != nil { return i0, err; } - } else { - // We can't flush yet - just add a new line. - b.AddLine(); } } } diff --git a/src/lib/tabwriter/tabwriter_test.go b/src/lib/tabwriter/tabwriter_test.go index 980cc73369..03b0409c90 100644 --- a/src/lib/tabwriter/tabwriter_test.go +++ b/src/lib/tabwriter/tabwriter_test.go @@ -49,7 +49,18 @@ func Check(t *testing.T, tabwidth, padding int, padchar byte, align_left bool, s var w tabwriter.Writer; w.Init(&b, tabwidth, padding, padchar, align_left); - io.WriteString(&w, src); + written, err := io.WriteString(&w, src); + if err != nil { + t.Errorf("--- src:\n%s\n--- write error: %v\n", src, err); + } + if written != len(src) { + t.Errorf("--- src:\n%s\n--- written = %d, len(src) = %d\n", src, written, len(src)); + } + + err = w.Flush(); + if err != nil { + t.Errorf("--- src:\n%s\n--- flush error: %v\n", src, err); + } res := b.String(); if res != expected { @@ -58,11 +69,95 @@ func Check(t *testing.T, tabwidth, padding int, padchar byte, align_left bool, s } -export func Test1(t *testing.T) { +export func Test(t *testing.T) { + Check( + t, 8, 1, '.', true, + "", + "" + ); + + Check( + t, 8, 1, '.', true, + "\n\n\n", + "\n\n\n" + ); + + Check( + t, 8, 1, '.', true, + "a\nb\nc", + "a\nb\nc" + ); + + Check( + t, 8, 1, '.', true, + "\t", // '\t' terminates an empty cell on last line - nothing to print + "" + ); + + Check( + t, 8, 1, '.', false, + "\t", // '\t' terminates an empty cell on last line - nothing to print + "" + ); + + Check( + t, 8, 1, '.', true, + "*\t*", + "**" + ); + + Check( + t, 8, 1, '.', true, + "*\t*\n", + "*.......*\n" + ); + + Check( + t, 8, 1, '.', true, + "*\t*\t", + "*.......*" + ); + + Check( + t, 8, 1, '.', false, + "*\t*\t", + ".......**" + ); + + Check( + t, 8, 1, '.', true, + "\t\n", + "........\n" + ); + + Check( + t, 8, 1, '.', true, + "a) foo", + "a) foo" + ); + Check( t, 8, 1, ' ', true, - "\n", - "\n" + "b) foo\tbar", // "bar" is not in any cell - not formatted, just flushed + "b) foobar" + ); + + Check( + t, 8, 1, '.', true, + "c) foo\tbar\t", + "c) foo..bar" + ); + + Check( + t, 8, 1, '.', true, + "d) foo\tbar\n", + "d) foo..bar\n" + ); + + Check( + t, 8, 1, '.', true, + "e) foo\tbar\t\n", + "e) foo..bar.....\n" ); Check( @@ -74,66 +169,66 @@ export func Test1(t *testing.T) { Check( t, 0, 0, '.', true, "1\t2\t3\t4\n" - "11\t222\t3333\t44444\n\n", + "11\t222\t3333\t44444\n", "1.2..3...4\n" - "11222333344444\n\n" + "11222333344444\n" ); Check( t, 5, 0, '.', true, - "1\t2\t3\t4\n\n", - "1....2....3....4\n\n" + "1\t2\t3\t4\n", + "1....2....3....4\n" ); Check( t, 5, 0, '.', true, - "1\t2\t3\t4\t\n\n", - "1....2....3....4....\n\n" + "1\t2\t3\t4\t\n", + "1....2....3....4....\n" ); Check( t, 8, 1, ' ', true, "a\tb\tc\n" "aa\tbbb\tcccc\tddddd\n" - "aaa\tbbbb\n\n", + "aaa\tbbbb\n", "a b c\n" "aa bbb cccc ddddd\n" - "aaa bbbb\n\n" + "aaa bbbb\n" ); Check( t, 8, 1, ' ', false, "a\tb\tc\t\n" "aa\tbbb\tcccc\tddddd\t\n" - "aaa\tbbbb\t\n\n", + "aaa\tbbbb\t\n", " a b c\n" " aa bbb cccc ddddd\n" - " aaa bbbb\n\n" + " aaa bbbb\n" ); Check( t, 2, 0, ' ', true, "a\tb\tc\n" "aa\tbbb\tcccc\n" - "aaa\tbbbb\n\n", + "aaa\tbbbb\n", "a b c\n" "aa bbbcccc\n" - "aaabbbb\n\n" + "aaabbbb\n" ); Check( t, 8, 1, '_', true, "a\tb\tc\n" "aa\tbbb\tcccc\n" - "aaa\tbbbb\n\n", + "aaa\tbbbb\n", "a_______b_______c\n" "aa______bbb_____cccc\n" - "aaa_____bbbb\n\n" + "aaa_____bbbb\n" ); Check( @@ -144,7 +239,7 @@ export func Test1(t *testing.T) { "\t\t\t88888888\n" "\n" "666666\t666666\t666666\t4444\n" - "1\t1\t999999999\t0000000000\n\n", + "1\t1\t999999999\t0000000000\n", "4444------333-22--1---333\n" "999999999-22\n" @@ -152,7 +247,7 @@ export func Test1(t *testing.T) { "------------------88888888\n" "\n" "666666-666666-666666----4444\n" - "1------1------999999999-0000000000\n\n" + "1------1------999999999-0000000000\n" ); Check( @@ -163,7 +258,7 @@ export func Test1(t *testing.T) { "\t\t\t88888888\n" "\n" "666666\t666666\t666666\t4444\n" - "1\t1\t999999999\t0000000000\n\n", + "1\t1\t999999999\t0000000000\n", "4444........333...22...1...333\n" "999999999...22\n" @@ -171,7 +266,7 @@ export func Test1(t *testing.T) { "....................88888888\n" "\n" "666666...666666...666666......4444\n" - "1........1........999999999...0000000000\n\n" + "1........1........999999999...0000000000\n" ); Check( @@ -182,7 +277,7 @@ export func Test1(t *testing.T) { "\t\t\t88888888\n" "\n" "666666\t666666\t666666\t4444\n" - "1\t1\t999999999\t0000000000\n\n", + "1\t1\t999999999\t0000000000\n", "4444\t\t333\t22\t1\t333\n" "999999999\t22\n" @@ -190,23 +285,23 @@ export func Test1(t *testing.T) { "\t\t\t\t88888888\n" "\n" "666666\t666666\t666666\t\t4444\n" - "1\t1\t999999999\t0000000000\n\n" + "1\t1\t999999999\t0000000000\n" ); Check( - t, 4, 2, ' ', false, + t, 0, 2, ' ', false, ".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" ".0\t0.0\t332.0\t8908.0\t\n" ".0\t-.3\t456.4\t22.1\t\n" - ".0\t1.2\t44.4\t-13.3\t\n\n", + ".0\t1.2\t44.4\t-13.3\t\t", " .0 .3 2.4 -5.1\n" " 23.0 12345678.9 2.4 -989.4\n" " 5.1 12.0 2.4 -7.0\n" " .0 0.0 332.0 8908.0\n" " .0 -.3 456.4 22.1\n" - " .0 1.2 44.4 -13.3\n\n" + " .0 1.2 44.4 -13.3" ); }