mirror of
https://github.com/golang/go
synced 2024-09-30 14:28:33 -06:00
- interpret form feed char as newline + flush
- cleanups: - replaced internal byte buffer implementation with io.ByteBuffer (now that we have one) - removed all uses of goto statements in favor of structured code - converted tests into a table-driven test R=r DELTA=277 (48 added, 67 deleted, 162 changed) OCL=29890 CL=29901
This commit is contained in:
parent
d30f80bad2
commit
4019259411
@ -10,7 +10,6 @@
|
||||
package tabwriter
|
||||
|
||||
import (
|
||||
"bytes";
|
||||
"container/vector";
|
||||
"io";
|
||||
"os";
|
||||
@ -18,57 +17,6 @@ import (
|
||||
)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Basic byteArray support
|
||||
|
||||
type byteArray struct {
|
||||
a []byte;
|
||||
}
|
||||
|
||||
|
||||
func (b *byteArray) init(initial_size int) {
|
||||
b.a = make([]byte, initial_size)[0 : 0];
|
||||
}
|
||||
|
||||
|
||||
func (b *byteArray) len() int {
|
||||
return len(b.a);
|
||||
}
|
||||
|
||||
|
||||
func (b *byteArray) clear() {
|
||||
b.a = b.a[0 : 0];
|
||||
}
|
||||
|
||||
|
||||
func (b *byteArray) slice(i, j int) []byte {
|
||||
return b.a[i : j]; // BUG should really be &b.a[i : j]
|
||||
}
|
||||
|
||||
|
||||
func (b *byteArray) append(s []byte) {
|
||||
a := b.a;
|
||||
n := len(a);
|
||||
m := n + len(s);
|
||||
|
||||
if m > cap(a) {
|
||||
n2 := 2*n;
|
||||
if m > n2 {
|
||||
n2 = m;
|
||||
}
|
||||
b := make([]byte, n2);
|
||||
bytes.Copy(b, a);
|
||||
a = b;
|
||||
}
|
||||
|
||||
a = a[0 : m];
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
a[n + i] = s[i];
|
||||
}
|
||||
b.a = a;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Filter implementation
|
||||
|
||||
@ -88,6 +36,16 @@ func (b *byteArray) append(s []byte) {
|
||||
// this may not be true in some fonts, especially with certain
|
||||
// UTF-8 characters.
|
||||
//
|
||||
// If a Writer is configured to filter HTML, HTML tags and entities
|
||||
// are simply passed through and their widths are assumed to be zero
|
||||
// for formatting purposes.
|
||||
//
|
||||
// The form feed character ('\f') acts like a newline but it also
|
||||
// terminates all columns in the current line (effectively calling
|
||||
// Flush). Cells in the next line start new columns. Unless found
|
||||
// inside an HTML tag, form feed characters appear as newlines in
|
||||
// the output.
|
||||
//
|
||||
// The Writer must buffer input internally, because proper spacing
|
||||
// of one line may depend on the cells in future lines. Clients must
|
||||
// call Flush when done calling Write.
|
||||
@ -102,7 +60,7 @@ type Writer struct {
|
||||
|
||||
// current state
|
||||
html_char byte; // terminating char of html tag/entity, or 0 ('>', ';', or 0)
|
||||
buf byteArray; // collected text w/o tabs and newlines
|
||||
buf io.ByteBuffer; // collected text w/o tabs, newlines, or form feed chars
|
||||
size int; // size of incomplete cell in bytes
|
||||
width int; // width of incomplete cell in runes up to buf[pos] w/o ignored sections
|
||||
pos int; // buffer position up to which width of incomplete cell has been computed
|
||||
@ -114,7 +72,7 @@ type Writer struct {
|
||||
|
||||
// Internal representation (current state):
|
||||
//
|
||||
// - all text written is appended to buf; tabs and newlines are stripped away
|
||||
// - all text written is appended to buf; form feed chars, tabs and newlines are stripped away
|
||||
// - at any given time there is a (possibly empty) incomplete cell at the end
|
||||
// (the cell starts after a tab or newline)
|
||||
// - size is the number of bytes belonging to the cell so far
|
||||
@ -182,12 +140,10 @@ func (b *Writer) Init(output io.Writer, cellwidth, padding int, padchar byte, fl
|
||||
}
|
||||
if padchar == '\t' {
|
||||
// tab enforces left-alignment
|
||||
t := ^AlignRight; // TODO 6g bug
|
||||
flags &= uint(t);
|
||||
flags &^= AlignRight;
|
||||
}
|
||||
b.flags = flags;
|
||||
|
||||
b.buf.init(1024);
|
||||
b.lines_size.Init(0);
|
||||
b.lines_width.Init(0);
|
||||
b.widths.Init(0);
|
||||
@ -204,7 +160,8 @@ func (b *Writer) line(i int) (*vector.IntVector, *vector.IntVector) {
|
||||
}
|
||||
|
||||
|
||||
// debugging support
|
||||
// debugging support (keep code around)
|
||||
/*
|
||||
func (b *Writer) dump() {
|
||||
pos := 0;
|
||||
for i := 0; i < b.lines_size.Len(); i++ {
|
||||
@ -219,6 +176,7 @@ func (b *Writer) dump() {
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
func (b *Writer) write0(buf []byte) os.Error {
|
||||
@ -232,7 +190,7 @@ func (b *Writer) write0(buf []byte) os.Error {
|
||||
|
||||
var newline = []byte{'\n'}
|
||||
|
||||
func (b *Writer) writePadding(textw, cellw int) (err os.Error) {
|
||||
func (b *Writer) writePadding(textw, cellw int) os.Error {
|
||||
if b.padbytes[0] == '\t' {
|
||||
// make cell width a multiple of cellwidth
|
||||
cellw = ((cellw + b.cellwidth - 1) / b.cellwidth) * b.cellwidth;
|
||||
@ -248,21 +206,18 @@ func (b *Writer) writePadding(textw, cellw int) (err os.Error) {
|
||||
}
|
||||
|
||||
for n > len(b.padbytes) {
|
||||
err = b.write0(&b.padbytes);
|
||||
if err != nil {
|
||||
goto exit;
|
||||
if err := b.write0(&b.padbytes); err != nil {
|
||||
return err;
|
||||
}
|
||||
n -= len(b.padbytes);
|
||||
}
|
||||
err = b.write0(b.padbytes[0 : n]);
|
||||
|
||||
exit:
|
||||
return err;
|
||||
return b.write0(b.padbytes[0 : n]);
|
||||
}
|
||||
|
||||
|
||||
func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int, err os.Error) {
|
||||
pos = pos0;
|
||||
func (b *Writer) writeLines(pos0 int, line0, line1 int) (int, os.Error) {
|
||||
pos := pos0;
|
||||
for i := line0; i < line1; i++ {
|
||||
line_size, line_width := b.line(i);
|
||||
for j := 0; j < line_size.Len(); j++ {
|
||||
@ -271,29 +226,25 @@ func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int, err os.Error)
|
||||
switch {
|
||||
default: // align left
|
||||
|
||||
err = b.write0(b.buf.slice(pos, pos + s));
|
||||
if err != nil {
|
||||
goto exit;
|
||||
if err := b.write0(b.buf.Data()[pos : pos + s]); err != nil {
|
||||
return pos, err;
|
||||
}
|
||||
pos += s;
|
||||
if j < b.widths.Len() {
|
||||
err = b.writePadding(w, b.widths.At(j));
|
||||
if err != nil {
|
||||
goto exit;
|
||||
if err := b.writePadding(w, b.widths.At(j)); err != nil {
|
||||
return pos, err;
|
||||
}
|
||||
}
|
||||
|
||||
case b.flags & AlignRight != 0: // align right
|
||||
|
||||
if j < b.widths.Len() {
|
||||
err = b.writePadding(w, b.widths.At(j));
|
||||
if err != nil {
|
||||
goto exit;
|
||||
if err := b.writePadding(w, b.widths.At(j)); err != nil {
|
||||
return pos, err;
|
||||
}
|
||||
}
|
||||
err = b.write0(b.buf.slice(pos, pos + s));
|
||||
if err != nil {
|
||||
goto exit;
|
||||
if err := b.write0(b.buf.Data()[pos : pos + s]); err != nil {
|
||||
return pos, err;
|
||||
}
|
||||
pos += s;
|
||||
}
|
||||
@ -302,19 +253,18 @@ func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int, err os.Error)
|
||||
if i+1 == b.lines_size.Len() {
|
||||
// last buffered line - we don't have a newline, so just write
|
||||
// any outstanding buffered data
|
||||
err = b.write0(b.buf.slice(pos, pos + b.size));
|
||||
if err := b.write0(b.buf.Data()[pos : pos + b.size]); err != nil {
|
||||
return pos, err;
|
||||
}
|
||||
pos += b.size;
|
||||
} else {
|
||||
// not the last line - write newline
|
||||
err = b.write0(newline);
|
||||
}
|
||||
if err != nil {
|
||||
goto exit;
|
||||
if err := b.write0(newline); err != nil {
|
||||
return pos, err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return pos, err;
|
||||
return pos, nil;
|
||||
}
|
||||
|
||||
|
||||
@ -332,7 +282,7 @@ func (b *Writer) format(pos0 int, line0, line1 int) (pos int, err os.Error) {
|
||||
// print unprinted lines until beginning of block
|
||||
pos, err = b.writeLines(pos, last, this);
|
||||
if err != nil {
|
||||
goto exit;
|
||||
return pos, err;
|
||||
}
|
||||
last = this;
|
||||
|
||||
@ -362,10 +312,7 @@ func (b *Writer) format(pos0 int, line0, line1 int) (pos int, err os.Error) {
|
||||
}
|
||||
|
||||
// print unprinted lines until end
|
||||
pos, err = b.writeLines(pos, last, line1);
|
||||
|
||||
exit:
|
||||
return pos, err;
|
||||
return b.writeLines(pos, last, line1);
|
||||
}
|
||||
|
||||
|
||||
@ -373,9 +320,9 @@ exit:
|
||||
// that any data buffered in the Writer is written to output.
|
||||
//
|
||||
func (b *Writer) Flush() os.Error {
|
||||
dummy, err := b.format(0, 0, b.lines_size.Len());
|
||||
_, err := b.format(0, 0, b.lines_size.Len());
|
||||
// reset (even in the presence of errors)
|
||||
b.buf.clear();
|
||||
b.buf.Reset();
|
||||
b.size, b.width = 0, 0;
|
||||
b.pos = 0;
|
||||
b.lines_size.Init(0);
|
||||
@ -401,7 +348,7 @@ func unicodeLen(buf []byte) int {
|
||||
|
||||
|
||||
func (b *Writer) append(buf []byte) {
|
||||
b.buf.append(buf);
|
||||
b.buf.Write(buf);
|
||||
b.size += len(buf);
|
||||
}
|
||||
|
||||
@ -420,11 +367,11 @@ func (b *Writer) Write(buf []byte) (written int, err os.Error) {
|
||||
if b.html_char == 0 {
|
||||
// outside html tag/entity
|
||||
switch ch {
|
||||
case '\t', '\n':
|
||||
case '\t', '\n', '\f':
|
||||
b.append(buf[i0 : i]);
|
||||
i0 = i + 1; // exclude ch from (next) cell
|
||||
b.width += unicodeLen(b.buf.slice(b.pos, b.buf.len()));
|
||||
b.pos = b.buf.len();
|
||||
b.width += unicodeLen(b.buf.Data()[b.pos : b.buf.Len()]);
|
||||
b.pos = b.buf.Len();
|
||||
|
||||
// terminate cell
|
||||
last_size, last_width := b.line(b.lines_size.Len() - 1);
|
||||
@ -432,15 +379,16 @@ func (b *Writer) Write(buf []byte) (written int, err os.Error) {
|
||||
last_width.Push(b.width);
|
||||
b.size, b.width = 0, 0;
|
||||
|
||||
if ch == '\n' {
|
||||
if ch != '\t' {
|
||||
// terminate line
|
||||
b.addLine();
|
||||
if last_size.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 {
|
||||
if ch == '\f' || last_size.Len() == 1 {
|
||||
// A '\f' always forces a flush. Otherwise, if 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.
|
||||
if err = b.Flush(); err != nil {
|
||||
return i0, err;
|
||||
}
|
||||
}
|
||||
@ -450,7 +398,7 @@ func (b *Writer) Write(buf []byte) (written int, err os.Error) {
|
||||
if b.flags & FilterHTML != 0 {
|
||||
b.append(buf[i0 : i]);
|
||||
i0 = i;
|
||||
b.width += unicodeLen(b.buf.slice(b.pos, b.buf.len()));
|
||||
b.width += unicodeLen(b.buf.Data()[b.pos : b.buf.Len()]);
|
||||
b.pos = -1; // preventative - should not be used (will cause index out of bounds)
|
||||
if ch == '<' {
|
||||
b.html_char = '>';
|
||||
@ -469,7 +417,7 @@ func (b *Writer) Write(buf []byte) (written int, err os.Error) {
|
||||
if b.html_char == ';' {
|
||||
b.width++; // count as one char
|
||||
}
|
||||
b.pos = b.buf.len();
|
||||
b.pos = b.buf.Len();
|
||||
b.html_char = 0;
|
||||
}
|
||||
}
|
||||
|
@ -103,132 +103,158 @@ func check(t *testing.T, tabwidth, padding int, padchar byte, flags uint, src, e
|
||||
}
|
||||
|
||||
|
||||
func Test(t *testing.T) {
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
type entry struct {
|
||||
tabwidth, padding int;
|
||||
padchar byte;
|
||||
flags uint;
|
||||
src, expected string;
|
||||
}
|
||||
|
||||
|
||||
var tests = []entry {
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"",
|
||||
""
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"\n\n\n",
|
||||
"\n\n\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"a\nb\nc",
|
||||
"a\nb\nc"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"\t", // '\t' terminates an empty cell on last line - nothing to print
|
||||
""
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', tabwriter.AlignRight,
|
||||
entry{
|
||||
8, 1, '.', tabwriter.AlignRight,
|
||||
"\t", // '\t' terminates an empty cell on last line - nothing to print
|
||||
""
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"*\t*",
|
||||
"**"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"*\t*\n",
|
||||
"*.......*\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"*\t*\t",
|
||||
"*.......*"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', tabwriter.AlignRight,
|
||||
entry{
|
||||
8, 1, '.', tabwriter.AlignRight,
|
||||
"*\t*\t",
|
||||
".......**"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"\t\n",
|
||||
"........\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"a) foo",
|
||||
"a) foo"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, ' ', 0,
|
||||
entry{
|
||||
8, 1, ' ', 0,
|
||||
"b) foo\tbar", // "bar" is not in any cell - not formatted, just flushed
|
||||
"b) foobar"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"c) foo\tbar\t",
|
||||
"c) foo..bar"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"d) foo\tbar\n",
|
||||
"d) foo..bar\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"e) foo\tbar\t\n",
|
||||
"e) foo..bar.....\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', tabwriter.FilterHTML,
|
||||
"e) f<o\t<b>bar</b>\t\n",
|
||||
"e) f<o..<b>bar</b>.....\n"
|
||||
);
|
||||
entry{
|
||||
8, 1, '.', tabwriter.FilterHTML,
|
||||
"f) f<o\t<b>bar</b>\t\n",
|
||||
"f) f<o..<b>bar</b>.....\n"
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '*', 0,
|
||||
entry{
|
||||
8, 1, '*', 0,
|
||||
"Hello, world!\n",
|
||||
"Hello, world!\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 0, 0, '.', 0,
|
||||
entry{
|
||||
0, 0, '.', 0,
|
||||
"1\t2\t3\t4\n"
|
||||
"11\t222\t3333\t44444\n",
|
||||
|
||||
"1.2..3...4\n"
|
||||
"11222333344444\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 5, 0, '.', 0,
|
||||
entry{
|
||||
0, 0, '.', tabwriter.FilterHTML,
|
||||
"1\t2<!---\f--->\t3\t4\n" // \f inside HTML is ignored
|
||||
"11\t222\t3333\t44444\n",
|
||||
|
||||
"1.2<!---\f--->..3...4\n"
|
||||
"11222333344444\n"
|
||||
},
|
||||
|
||||
entry{
|
||||
0, 0, '.', 0,
|
||||
"1\t2\t3\t4\f" // \f causes a newline and flush
|
||||
"11\t222\t3333\t44444\n",
|
||||
|
||||
"1234\n"
|
||||
"11222333344444\n"
|
||||
},
|
||||
|
||||
entry{
|
||||
5, 0, '.', 0,
|
||||
"1\t2\t3\t4\n",
|
||||
"1....2....3....4\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 5, 0, '.', 0,
|
||||
entry{
|
||||
5, 0, '.', 0,
|
||||
"1\t2\t3\t4\t\n",
|
||||
"1....2....3....4....\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '.', 0,
|
||||
entry{
|
||||
8, 1, '.', 0,
|
||||
"本\tb\tc\n"
|
||||
"aa\t\u672c\u672c\u672c\tcccc\tddddd\n"
|
||||
"aaa\tbbbb\n",
|
||||
@ -236,10 +262,10 @@ func Test(t *testing.T) {
|
||||
"本.......b.......c\n"
|
||||
"aa......本本本.....cccc....ddddd\n"
|
||||
"aaa.....bbbb\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, ' ', tabwriter.AlignRight,
|
||||
entry{
|
||||
8, 1, ' ', tabwriter.AlignRight,
|
||||
"a\tè\tc\t\n"
|
||||
"aa\tèèè\tcccc\tddddd\t\n"
|
||||
"aaa\tèèèè\t\n",
|
||||
@ -247,10 +273,10 @@ func Test(t *testing.T) {
|
||||
" a è c\n"
|
||||
" aa èèè cccc ddddd\n"
|
||||
" aaa èèèè\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 2, 0, ' ', 0,
|
||||
entry{
|
||||
2, 0, ' ', 0,
|
||||
"a\tb\tc\n"
|
||||
"aa\tbbb\tcccc\n"
|
||||
"aaa\tbbbb\n",
|
||||
@ -258,10 +284,10 @@ func Test(t *testing.T) {
|
||||
"a b c\n"
|
||||
"aa bbbcccc\n"
|
||||
"aaabbbb\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '_', 0,
|
||||
entry{
|
||||
8, 1, '_', 0,
|
||||
"a\tb\tc\n"
|
||||
"aa\tbbb\tcccc\n"
|
||||
"aaa\tbbbb\n",
|
||||
@ -269,10 +295,10 @@ func Test(t *testing.T) {
|
||||
"a_______b_______c\n"
|
||||
"aa______bbb_____cccc\n"
|
||||
"aaa_____bbbb\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 4, 1, '-', 0,
|
||||
entry{
|
||||
4, 1, '-', 0,
|
||||
"4444\t日本語\t22\t1\t333\n"
|
||||
"999999999\t22\n"
|
||||
"7\t22\n"
|
||||
@ -288,10 +314,10 @@ func Test(t *testing.T) {
|
||||
"\n"
|
||||
"666666-666666-666666----4444\n"
|
||||
"1------1------999999999-0000000000\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 4, 3, '.', 0,
|
||||
entry{
|
||||
4, 3, '.', 0,
|
||||
"4444\t333\t22\t1\t333\n"
|
||||
"999999999\t22\n"
|
||||
"7\t22\n"
|
||||
@ -307,10 +333,10 @@ func Test(t *testing.T) {
|
||||
"\n"
|
||||
"666666...666666...666666......4444\n"
|
||||
"1........1........999999999...0000000000\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 8, 1, '\t', tabwriter.FilterHTML,
|
||||
entry{
|
||||
8, 1, '\t', tabwriter.FilterHTML,
|
||||
"4444\t333\t22\t1\t333\n"
|
||||
"999999999\t22\n"
|
||||
"7\t22\n"
|
||||
@ -326,10 +352,10 @@ func Test(t *testing.T) {
|
||||
"\n"
|
||||
"666666\t666666\t666666\t\t4444\n"
|
||||
"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n"
|
||||
);
|
||||
},
|
||||
|
||||
check(
|
||||
t, 0, 2, ' ', tabwriter.AlignRight,
|
||||
entry{
|
||||
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"
|
||||
@ -343,5 +369,12 @@ func Test(t *testing.T) {
|
||||
" .0 0.0 332.0 8908.0\n"
|
||||
" .0 -.3 456.4 22.1\n"
|
||||
" .0 1.2 44.4 -13.3"
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
func Test(t *testing.T) {
|
||||
for _, e := range tests {
|
||||
check(t, e.tabwidth, e.padding, e.padchar, e.flags, e.src, e.expected);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user