mirror of
https://github.com/golang/go
synced 2024-11-18 10:14:45 -07: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
|
package tabwriter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes";
|
|
||||||
"container/vector";
|
"container/vector";
|
||||||
"io";
|
"io";
|
||||||
"os";
|
"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
|
// Filter implementation
|
||||||
|
|
||||||
@ -88,6 +36,16 @@ func (b *byteArray) append(s []byte) {
|
|||||||
// this may not be true in some fonts, especially with certain
|
// this may not be true in some fonts, especially with certain
|
||||||
// UTF-8 characters.
|
// 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
|
// The Writer must buffer input internally, because proper spacing
|
||||||
// of one line may depend on the cells in future lines. Clients must
|
// of one line may depend on the cells in future lines. Clients must
|
||||||
// call Flush when done calling Write.
|
// call Flush when done calling Write.
|
||||||
@ -102,7 +60,7 @@ type Writer struct {
|
|||||||
|
|
||||||
// current state
|
// current state
|
||||||
html_char byte; // terminating char of html tag/entity, or 0 ('>', ';', or 0)
|
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
|
size int; // size of incomplete cell in bytes
|
||||||
width int; // width of incomplete cell in runes up to buf[pos] w/o ignored sections
|
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
|
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):
|
// 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
|
// - at any given time there is a (possibly empty) incomplete cell at the end
|
||||||
// (the cell starts after a tab or newline)
|
// (the cell starts after a tab or newline)
|
||||||
// - size is the number of bytes belonging to the cell so far
|
// - 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' {
|
if padchar == '\t' {
|
||||||
// tab enforces left-alignment
|
// tab enforces left-alignment
|
||||||
t := ^AlignRight; // TODO 6g bug
|
flags &^= AlignRight;
|
||||||
flags &= uint(t);
|
|
||||||
}
|
}
|
||||||
b.flags = flags;
|
b.flags = flags;
|
||||||
|
|
||||||
b.buf.init(1024);
|
|
||||||
b.lines_size.Init(0);
|
b.lines_size.Init(0);
|
||||||
b.lines_width.Init(0);
|
b.lines_width.Init(0);
|
||||||
b.widths.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() {
|
func (b *Writer) dump() {
|
||||||
pos := 0;
|
pos := 0;
|
||||||
for i := 0; i < b.lines_size.Len(); i++ {
|
for i := 0; i < b.lines_size.Len(); i++ {
|
||||||
@ -219,6 +176,7 @@ func (b *Writer) dump() {
|
|||||||
}
|
}
|
||||||
print("\n");
|
print("\n");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
func (b *Writer) write0(buf []byte) os.Error {
|
func (b *Writer) write0(buf []byte) os.Error {
|
||||||
@ -232,7 +190,7 @@ func (b *Writer) write0(buf []byte) os.Error {
|
|||||||
|
|
||||||
var newline = []byte{'\n'}
|
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' {
|
if b.padbytes[0] == '\t' {
|
||||||
// make cell width a multiple of cellwidth
|
// make cell width a multiple of cellwidth
|
||||||
cellw = ((cellw + b.cellwidth - 1) / b.cellwidth) * b.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) {
|
for n > len(b.padbytes) {
|
||||||
err = b.write0(&b.padbytes);
|
if err := b.write0(&b.padbytes); err != nil {
|
||||||
if err != nil {
|
return err;
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
n -= len(b.padbytes);
|
n -= len(b.padbytes);
|
||||||
}
|
}
|
||||||
err = b.write0(b.padbytes[0 : n]);
|
|
||||||
|
|
||||||
exit:
|
return b.write0(b.padbytes[0 : n]);
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int, err os.Error) {
|
func (b *Writer) writeLines(pos0 int, line0, line1 int) (int, os.Error) {
|
||||||
pos = pos0;
|
pos := pos0;
|
||||||
for i := line0; i < line1; i++ {
|
for i := line0; i < line1; i++ {
|
||||||
line_size, line_width := b.line(i);
|
line_size, line_width := b.line(i);
|
||||||
for j := 0; j < line_size.Len(); j++ {
|
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 {
|
switch {
|
||||||
default: // align left
|
default: // align left
|
||||||
|
|
||||||
err = b.write0(b.buf.slice(pos, pos + s));
|
if err := b.write0(b.buf.Data()[pos : pos + s]); err != nil {
|
||||||
if err != nil {
|
return pos, err;
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
pos += s;
|
pos += s;
|
||||||
if j < b.widths.Len() {
|
if j < b.widths.Len() {
|
||||||
err = b.writePadding(w, b.widths.At(j));
|
if err := b.writePadding(w, b.widths.At(j)); err != nil {
|
||||||
if err != nil {
|
return pos, err;
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case b.flags & AlignRight != 0: // align right
|
case b.flags & AlignRight != 0: // align right
|
||||||
|
|
||||||
if j < b.widths.Len() {
|
if j < b.widths.Len() {
|
||||||
err = b.writePadding(w, b.widths.At(j));
|
if err := b.writePadding(w, b.widths.At(j)); err != nil {
|
||||||
if err != nil {
|
return pos, err;
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = b.write0(b.buf.slice(pos, pos + s));
|
if err := b.write0(b.buf.Data()[pos : pos + s]); err != nil {
|
||||||
if err != nil {
|
return pos, err;
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
pos += s;
|
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() {
|
if i+1 == b.lines_size.Len() {
|
||||||
// last buffered line - we don't have a newline, so just write
|
// last buffered line - we don't have a newline, so just write
|
||||||
// any outstanding buffered data
|
// 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;
|
pos += b.size;
|
||||||
} else {
|
} else {
|
||||||
// not the last line - write newline
|
// not the last line - write newline
|
||||||
err = b.write0(newline);
|
if err := b.write0(newline); err != nil {
|
||||||
}
|
return pos, err;
|
||||||
if err != nil {
|
}
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return pos, nil;
|
||||||
exit:
|
|
||||||
return pos, err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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
|
// print unprinted lines until beginning of block
|
||||||
pos, err = b.writeLines(pos, last, this);
|
pos, err = b.writeLines(pos, last, this);
|
||||||
if err != nil {
|
if err != nil {
|
||||||
goto exit;
|
return pos, err;
|
||||||
}
|
}
|
||||||
last = this;
|
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
|
// print unprinted lines until end
|
||||||
pos, err = b.writeLines(pos, last, line1);
|
return b.writeLines(pos, last, line1);
|
||||||
|
|
||||||
exit:
|
|
||||||
return pos, err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -373,9 +320,9 @@ exit:
|
|||||||
// that any data buffered in the Writer is written to output.
|
// that any data buffered in the Writer is written to output.
|
||||||
//
|
//
|
||||||
func (b *Writer) Flush() os.Error {
|
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)
|
// reset (even in the presence of errors)
|
||||||
b.buf.clear();
|
b.buf.Reset();
|
||||||
b.size, b.width = 0, 0;
|
b.size, b.width = 0, 0;
|
||||||
b.pos = 0;
|
b.pos = 0;
|
||||||
b.lines_size.Init(0);
|
b.lines_size.Init(0);
|
||||||
@ -401,7 +348,7 @@ func unicodeLen(buf []byte) int {
|
|||||||
|
|
||||||
|
|
||||||
func (b *Writer) append(buf []byte) {
|
func (b *Writer) append(buf []byte) {
|
||||||
b.buf.append(buf);
|
b.buf.Write(buf);
|
||||||
b.size += len(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 {
|
if b.html_char == 0 {
|
||||||
// outside html tag/entity
|
// outside html tag/entity
|
||||||
switch ch {
|
switch ch {
|
||||||
case '\t', '\n':
|
case '\t', '\n', '\f':
|
||||||
b.append(buf[i0 : i]);
|
b.append(buf[i0 : i]);
|
||||||
i0 = i + 1; // exclude ch from (next) cell
|
i0 = i + 1; // exclude ch from (next) cell
|
||||||
b.width += unicodeLen(b.buf.slice(b.pos, b.buf.len()));
|
b.width += unicodeLen(b.buf.Data()[b.pos : b.buf.Len()]);
|
||||||
b.pos = b.buf.len();
|
b.pos = b.buf.Len();
|
||||||
|
|
||||||
// terminate cell
|
// terminate cell
|
||||||
last_size, last_width := b.line(b.lines_size.Len() - 1);
|
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);
|
last_width.Push(b.width);
|
||||||
b.size, b.width = 0, 0;
|
b.size, b.width = 0, 0;
|
||||||
|
|
||||||
if ch == '\n' {
|
if ch != '\t' {
|
||||||
|
// terminate line
|
||||||
b.addLine();
|
b.addLine();
|
||||||
if last_size.Len() == 1 {
|
if ch == '\f' || last_size.Len() == 1 {
|
||||||
// The previous line has only one cell which does not have
|
// A '\f' always forces a flush. Otherwise, if the previous
|
||||||
// an impact on the formatting of the following lines (the
|
// line has only one cell which does not have an impact on
|
||||||
// last cell per line is ignored by format()), thus we can
|
// the formatting of the following lines (the last cell per
|
||||||
// flush the Writer contents.
|
// line is ignored by format()), thus we can flush the
|
||||||
err = b.Flush();
|
// Writer contents.
|
||||||
if err != nil {
|
if err = b.Flush(); err != nil {
|
||||||
return i0, err;
|
return i0, err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -450,7 +398,7 @@ func (b *Writer) Write(buf []byte) (written int, err os.Error) {
|
|||||||
if b.flags & FilterHTML != 0 {
|
if b.flags & FilterHTML != 0 {
|
||||||
b.append(buf[i0 : i]);
|
b.append(buf[i0 : i]);
|
||||||
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)
|
b.pos = -1; // preventative - should not be used (will cause index out of bounds)
|
||||||
if ch == '<' {
|
if ch == '<' {
|
||||||
b.html_char = '>';
|
b.html_char = '>';
|
||||||
@ -469,7 +417,7 @@ func (b *Writer) Write(buf []byte) (written int, err os.Error) {
|
|||||||
if b.html_char == ';' {
|
if b.html_char == ';' {
|
||||||
b.width++; // count as one char
|
b.width++; // count as one char
|
||||||
}
|
}
|
||||||
b.pos = b.buf.len();
|
b.pos = b.buf.Len();
|
||||||
b.html_char = 0;
|
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) {
|
type entry struct {
|
||||||
check(
|
tabwidth, padding int;
|
||||||
t, 8, 1, '.', 0,
|
padchar byte;
|
||||||
|
flags uint;
|
||||||
|
src, expected string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var tests = []entry {
|
||||||
|
entry{
|
||||||
|
8, 1, '.', 0,
|
||||||
"",
|
"",
|
||||||
""
|
""
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"\n\n\n",
|
"\n\n\n",
|
||||||
"\n\n\n"
|
"\n\n\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"a\nb\nc",
|
"a\nb\nc",
|
||||||
"a\nb\nc"
|
"a\nb\nc"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"\t", // '\t' terminates an empty cell on last line - nothing to print
|
"\t", // '\t' terminates an empty cell on last line - nothing to print
|
||||||
""
|
""
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', tabwriter.AlignRight,
|
8, 1, '.', tabwriter.AlignRight,
|
||||||
"\t", // '\t' terminates an empty cell on last line - nothing to print
|
"\t", // '\t' terminates an empty cell on last line - nothing to print
|
||||||
""
|
""
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"*\t*",
|
"*\t*",
|
||||||
"**"
|
"**"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"*\t*\n",
|
"*\t*\n",
|
||||||
"*.......*\n"
|
"*.......*\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"*\t*\t",
|
"*\t*\t",
|
||||||
"*.......*"
|
"*.......*"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', tabwriter.AlignRight,
|
8, 1, '.', tabwriter.AlignRight,
|
||||||
"*\t*\t",
|
"*\t*\t",
|
||||||
".......**"
|
".......**"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"\t\n",
|
"\t\n",
|
||||||
"........\n"
|
"........\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"a) foo",
|
"a) foo",
|
||||||
"a) foo"
|
"a) foo"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, ' ', 0,
|
8, 1, ' ', 0,
|
||||||
"b) foo\tbar", // "bar" is not in any cell - not formatted, just flushed
|
"b) foo\tbar", // "bar" is not in any cell - not formatted, just flushed
|
||||||
"b) foobar"
|
"b) foobar"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"c) foo\tbar\t",
|
"c) foo\tbar\t",
|
||||||
"c) foo..bar"
|
"c) foo..bar"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"d) foo\tbar\n",
|
"d) foo\tbar\n",
|
||||||
"d) foo..bar\n"
|
"d) foo..bar\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"e) foo\tbar\t\n",
|
"e) foo\tbar\t\n",
|
||||||
"e) foo..bar.....\n"
|
"e) foo..bar.....\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', tabwriter.FilterHTML,
|
8, 1, '.', tabwriter.FilterHTML,
|
||||||
"e) f<o\t<b>bar</b>\t\n",
|
"f) f<o\t<b>bar</b>\t\n",
|
||||||
"e) f<o..<b>bar</b>.....\n"
|
"f) f<o..<b>bar</b>.....\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '*', 0,
|
8, 1, '*', 0,
|
||||||
"Hello, world!\n",
|
"Hello, world!\n",
|
||||||
"Hello, world!\n"
|
"Hello, world!\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 0, 0, '.', 0,
|
0, 0, '.', 0,
|
||||||
"1\t2\t3\t4\n"
|
"1\t2\t3\t4\n"
|
||||||
"11\t222\t3333\t44444\n",
|
"11\t222\t3333\t44444\n",
|
||||||
|
|
||||||
"1.2..3...4\n"
|
"1.2..3...4\n"
|
||||||
"11222333344444\n"
|
"11222333344444\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 5, 0, '.', 0,
|
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\t2\t3\t4\n",
|
||||||
"1....2....3....4\n"
|
"1....2....3....4\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 5, 0, '.', 0,
|
5, 0, '.', 0,
|
||||||
"1\t2\t3\t4\t\n",
|
"1\t2\t3\t4\t\n",
|
||||||
"1....2....3....4....\n"
|
"1....2....3....4....\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '.', 0,
|
8, 1, '.', 0,
|
||||||
"本\tb\tc\n"
|
"本\tb\tc\n"
|
||||||
"aa\t\u672c\u672c\u672c\tcccc\tddddd\n"
|
"aa\t\u672c\u672c\u672c\tcccc\tddddd\n"
|
||||||
"aaa\tbbbb\n",
|
"aaa\tbbbb\n",
|
||||||
@ -236,10 +262,10 @@ func Test(t *testing.T) {
|
|||||||
"本.......b.......c\n"
|
"本.......b.......c\n"
|
||||||
"aa......本本本.....cccc....ddddd\n"
|
"aa......本本本.....cccc....ddddd\n"
|
||||||
"aaa.....bbbb\n"
|
"aaa.....bbbb\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, ' ', tabwriter.AlignRight,
|
8, 1, ' ', tabwriter.AlignRight,
|
||||||
"a\tè\tc\t\n"
|
"a\tè\tc\t\n"
|
||||||
"aa\tèèè\tcccc\tddddd\t\n"
|
"aa\tèèè\tcccc\tddddd\t\n"
|
||||||
"aaa\tèèèè\t\n",
|
"aaa\tèèèè\t\n",
|
||||||
@ -247,10 +273,10 @@ func Test(t *testing.T) {
|
|||||||
" a è c\n"
|
" a è c\n"
|
||||||
" aa èèè cccc ddddd\n"
|
" aa èèè cccc ddddd\n"
|
||||||
" aaa èèèè\n"
|
" aaa èèèè\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 2, 0, ' ', 0,
|
2, 0, ' ', 0,
|
||||||
"a\tb\tc\n"
|
"a\tb\tc\n"
|
||||||
"aa\tbbb\tcccc\n"
|
"aa\tbbb\tcccc\n"
|
||||||
"aaa\tbbbb\n",
|
"aaa\tbbbb\n",
|
||||||
@ -258,10 +284,10 @@ func Test(t *testing.T) {
|
|||||||
"a b c\n"
|
"a b c\n"
|
||||||
"aa bbbcccc\n"
|
"aa bbbcccc\n"
|
||||||
"aaabbbb\n"
|
"aaabbbb\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '_', 0,
|
8, 1, '_', 0,
|
||||||
"a\tb\tc\n"
|
"a\tb\tc\n"
|
||||||
"aa\tbbb\tcccc\n"
|
"aa\tbbb\tcccc\n"
|
||||||
"aaa\tbbbb\n",
|
"aaa\tbbbb\n",
|
||||||
@ -269,10 +295,10 @@ func Test(t *testing.T) {
|
|||||||
"a_______b_______c\n"
|
"a_______b_______c\n"
|
||||||
"aa______bbb_____cccc\n"
|
"aa______bbb_____cccc\n"
|
||||||
"aaa_____bbbb\n"
|
"aaa_____bbbb\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 4, 1, '-', 0,
|
4, 1, '-', 0,
|
||||||
"4444\t日本語\t22\t1\t333\n"
|
"4444\t日本語\t22\t1\t333\n"
|
||||||
"999999999\t22\n"
|
"999999999\t22\n"
|
||||||
"7\t22\n"
|
"7\t22\n"
|
||||||
@ -288,10 +314,10 @@ func Test(t *testing.T) {
|
|||||||
"\n"
|
"\n"
|
||||||
"666666-666666-666666----4444\n"
|
"666666-666666-666666----4444\n"
|
||||||
"1------1------999999999-0000000000\n"
|
"1------1------999999999-0000000000\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 4, 3, '.', 0,
|
4, 3, '.', 0,
|
||||||
"4444\t333\t22\t1\t333\n"
|
"4444\t333\t22\t1\t333\n"
|
||||||
"999999999\t22\n"
|
"999999999\t22\n"
|
||||||
"7\t22\n"
|
"7\t22\n"
|
||||||
@ -307,10 +333,10 @@ func Test(t *testing.T) {
|
|||||||
"\n"
|
"\n"
|
||||||
"666666...666666...666666......4444\n"
|
"666666...666666...666666......4444\n"
|
||||||
"1........1........999999999...0000000000\n"
|
"1........1........999999999...0000000000\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 8, 1, '\t', tabwriter.FilterHTML,
|
8, 1, '\t', tabwriter.FilterHTML,
|
||||||
"4444\t333\t22\t1\t333\n"
|
"4444\t333\t22\t1\t333\n"
|
||||||
"999999999\t22\n"
|
"999999999\t22\n"
|
||||||
"7\t22\n"
|
"7\t22\n"
|
||||||
@ -326,10 +352,10 @@ func Test(t *testing.T) {
|
|||||||
"\n"
|
"\n"
|
||||||
"666666\t666666\t666666\t\t4444\n"
|
"666666\t666666\t666666\t\t4444\n"
|
||||||
"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n"
|
"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n"
|
||||||
);
|
},
|
||||||
|
|
||||||
check(
|
entry{
|
||||||
t, 0, 2, ' ', tabwriter.AlignRight,
|
0, 2, ' ', tabwriter.AlignRight,
|
||||||
".0\t.3\t2.4\t-5.1\t\n"
|
".0\t.3\t2.4\t-5.1\t\n"
|
||||||
"23.0\t12345678.9\t2.4\t-989.4\t\n"
|
"23.0\t12345678.9\t2.4\t-989.4\t\n"
|
||||||
"5.1\t12.0\t2.4\t-7.0\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 0.0 332.0 8908.0\n"
|
||||||
" .0 -.3 456.4 22.1\n"
|
" .0 -.3 456.4 22.1\n"
|
||||||
" .0 1.2 44.4 -13.3"
|
" .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