summaryrefslogtreecommitdiff
path: root/src/pkg/tabwriter
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2009-10-06 15:10:36 -0700
committerRobert Griesemer <gri@golang.org>2009-10-06 15:10:36 -0700
commit7c04866f511bcf48f5854be731c92bb62eaf6161 (patch)
tree6ee492046b176422c670ff9a210cd8ddc77e4b05 /src/pkg/tabwriter
parentd9fe3c9b7f898fffab8e50fea7c3dcb01c4f4f53 (diff)
downloadgolang-7c04866f511bcf48f5854be731c92bb62eaf6161.tar.gz
add IgnoreEmptyColumns feature to tabwriter
R=rsc DELTA=96 (74 added, 2 deleted, 20 changed) OCL=35391 CL=35402
Diffstat (limited to 'src/pkg/tabwriter')
-rw-r--r--src/pkg/tabwriter/tabwriter.go59
-rw-r--r--src/pkg/tabwriter/tabwriter_test.go55
2 files changed, 93 insertions, 21 deletions
diff --git a/src/pkg/tabwriter/tabwriter.go b/src/pkg/tabwriter/tabwriter.go
index ea98a9e87..d65e76343 100644
--- a/src/pkg/tabwriter/tabwriter.go
+++ b/src/pkg/tabwriter/tabwriter.go
@@ -106,13 +106,13 @@ func (b *Writer) reset() {
// - 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, form feed, or newline)
-// - size is the number of bytes belonging to the cell so far
-// - width is text width in runes of that cell from the start of the cell to
+// - cell.size is the number of bytes belonging to the cell so far
+// - cell.width is text width in runes of that cell from the start of the cell to
// position pos; html tags and entities are excluded from this width if html
// filtering is enabled
-// - the sizes and widths of processed text are kept in the lines_size and
-// lines_width arrays, which contain an array of sizes or widths for each line
-// - the widths array is a temporary array with current widths used during
+// - the sizes and widths of processed text are kept in the lines vector
+// which contains a vector of cells for each line
+// - the widths vector is a temporary vector with current widths used during
// formatting; it is kept in Writer because it's re-used
//
// |<---------- size ---------->|
@@ -134,6 +134,10 @@ const (
// Force right-alignment of cell content.
// Default is left-alignment.
AlignRight;
+
+ // Handle empty columns as if they were not present in
+ // the input in the first place.
+ DiscardEmptyColumns;
)
@@ -283,33 +287,43 @@ func (b *Writer) writeLines(pos0 int, line0, line1 int) (int, os.Error) {
}
+// Format the text between line0 and line1 (excluding line1); pos
+// is the buffer position corresponding to the beginning of line0.
+// Returns the buffer position corresponding to the beginning of
+// line1 and an error, if any.
+//
func (b *Writer) format(pos0 int, line0, line1 int) (pos int, err os.Error) {
pos = pos0;
column := b.widths.Len();
- last := line0;
for this := line0; this < line1; this++ {
line := b.line(this);
if column < line.Len() - 1 {
- // cell exists in this column
- // (note that the last cell per line is ignored)
+ // cell exists in this column => this line
+ // has more cells than the previous line
+ // (the last cell per line is ignored because cells are
+ // tab-terminated; the last cell per line describes the
+ // text before the newline/formfeed and does not belong
+ // to a column)
// print unprinted lines until beginning of block
- pos, err = b.writeLines(pos, last, this);
- if err != nil {
- return pos, err;
+ if pos, err = b.writeLines(pos, line0, this); err != nil {
+ return;
}
- last = this;
+ line0 = this;
// column block begin
- width := b.cellwidth; // minimal width
+ width := b.cellwidth; // minimal column width
+ wsum := 0; // the sum of all unpadded cell widths in this column
for ; this < line1; this++ {
line = b.line(this);
if column < line.Len() - 1 {
- // cell exists in this column => update width
- w := line.At(column).(cell).width + b.padding;
- if w > width {
- width = w;
+ // cell exists in this column
+ w := line.At(column).(cell).width;
+ wsum += w;
+ // update width
+ if t := w + b.padding; t > width {
+ width = t;
}
} else {
break
@@ -317,17 +331,22 @@ func (b *Writer) format(pos0 int, line0, line1 int) (pos int, err os.Error) {
}
// column block end
+ // discard empty columns if necessary
+ if wsum == 0 && b.flags & DiscardEmptyColumns != 0 {
+ width = 0;
+ }
+
// format and print all columns to the right of this column
// (we know the widths of this column and all columns to the left)
b.widths.Push(width);
- pos, err = b.format(pos, last, this);
+ pos, err = b.format(pos, line0, this);
b.widths.Pop();
- last = this;
+ line0 = this;
}
}
// print unprinted lines until end
- return b.writeLines(pos, last, line1);
+ return b.writeLines(pos, line0, line1);
}
diff --git a/src/pkg/tabwriter/tabwriter_test.go b/src/pkg/tabwriter/tabwriter_test.go
index 65641dad0..6b2fa862e 100644
--- a/src/pkg/tabwriter/tabwriter_test.go
+++ b/src/pkg/tabwriter/tabwriter_test.go
@@ -35,7 +35,7 @@ func (b *buffer) Write(buf []byte) (written int, err os.Error) {
b.a[n+i] = buf[i];
}
} else {
- panicln("buffer too small", n, m, cap(b.a));
+ panicln("buffer.Write: buffer too small", n, m, cap(b.a));
}
return len(buf), nil;
}
@@ -407,6 +407,59 @@ var tests = []entry {
" .0 -.3 456.4 22.1\n"
" .0 1.2 44.4 -13.3"
},
+
+ entry{
+ "15a",
+ 4, 0, '.', 0,
+ "a\t\tb",
+ "a.......b"
+ },
+
+ entry{
+ "15b",
+ 4, 0, '.', DiscardEmptyColumns,
+ "a\t\tb",
+ "a...b"
+ },
+
+ entry{
+ "15c",
+ 4, 0, '.', AlignRight | DiscardEmptyColumns,
+ "a\t\tb",
+ "...ab"
+ },
+
+ entry{
+ "16a",
+ 100, 0, '\t', 0,
+ "a\tb\t\td\n"
+ "a\tb\t\td\te\n"
+ "a\n"
+ "a\tb\tc\td\n"
+ "a\tb\tc\td\te\n",
+
+ "a\tb\t\td\n"
+ "a\tb\t\td\te\n"
+ "a\n"
+ "a\tb\tc\td\n"
+ "a\tb\tc\td\te\n"
+ },
+
+ entry{
+ "16b",
+ 100, 0, '\t', DiscardEmptyColumns,
+ "a\tb\t\td\n"
+ "a\tb\t\td\te\n"
+ "a\n"
+ "a\tb\tc\td\n"
+ "a\tb\tc\td\te\n",
+
+ "a\tb\td\n"
+ "a\tb\td\te\n"
+ "a\n"
+ "a\tb\tc\td\n"
+ "a\tb\tc\td\te\n"
+ },
}