summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pkg/tabwriter/tabwriter.go36
-rw-r--r--src/pkg/tabwriter/tabwriter_test.go35
2 files changed, 53 insertions, 18 deletions
diff --git a/src/pkg/tabwriter/tabwriter.go b/src/pkg/tabwriter/tabwriter.go
index 5103f6ce2..15ffc79cc 100644
--- a/src/pkg/tabwriter/tabwriter.go
+++ b/src/pkg/tabwriter/tabwriter.go
@@ -23,11 +23,13 @@ import (
// A cell represents a segment of text delineated by tabs, form-feed,
// or newline chars. The text itself is stored in a separate buffer;
-// cell only describes the segment's size in bytes and width in runes.
+// cell only describes the segment's size in bytes, its width in runes,
+// and whether it's an htab ('\t') or vtab ('\v') terminated call.
//
type cell struct {
size int; // cell size in bytes
width int; // cell width in runes
+ htab bool; // true if the cell is terminated by an htab ('\t')
}
@@ -43,6 +45,12 @@ type cell struct {
// not tab-separated: trailing non-tab text at the end of a line
// is not part of any cell.
//
+// Horizontal and vertical tabs may be used to terminate a cell.
+// If DiscardEmptyColumns is set, empty columns that are terminated
+// entirely by vertical (or "soft") tabs are discarded. Columns
+// terminated by horizontal (or "hard") tabs are not affected by
+// this flag.
+//
// The Writer assumes that all characters have the same width;
// this may not be true in some fonts, especially with certain
// UTF-8 characters.
@@ -314,16 +322,19 @@ func (b *Writer) format(pos0 int, line0, line1 int) (pos int, err os.Error) {
// column block begin
width := b.cellwidth; // minimal column width
- wsum := 0; // the sum of all unpadded cell widths in this column
+ discardable := true; // true if all cells in this column are empty and "soft"
for ; this < line1; this++ {
line = b.line(this);
if column < line.Len() - 1 {
// cell exists in this column
- w := line.At(column).(cell).width;
- wsum += w;
+ c := line.At(column).(cell);
// update width
- if t := w + b.padding; t > width {
- width = t;
+ if w := c.width + b.padding; w > width {
+ width = w;
+ }
+ // update discardable
+ if c.width > 0 || c.htab {
+ discardable = false;
}
} else {
break
@@ -332,7 +343,7 @@ 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 {
+ if discardable && b.flags & DiscardEmptyColumns != 0 {
width = 0;
}
@@ -391,7 +402,8 @@ func (b *Writer) terminateHTML() {
// Terminate the current cell by adding it to the list of cells of the
// current line. Returns the number of cells in that line.
//
-func (b *Writer) terminateCell() int {
+func (b *Writer) terminateCell(htab bool) int {
+ b.cell.htab = htab;
line := b.line(b.lines.Len() - 1);
line.Push(b.cell);
b.cell = cell{};
@@ -411,7 +423,7 @@ func (b *Writer) Flush() os.Error {
// inside html tag/entity - terminate it even if incomplete
b.terminateHTML();
}
- b.terminateCell();
+ b.terminateCell(false);
}
// format contents of buffer
@@ -435,12 +447,12 @@ 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', '\f':
+ case '\t', '\v', '\n', '\f':
// end of cell
b.append(buf[i0 : i], true);
i0 = i+1; // exclude ch from (next) cell
- ncells := b.terminateCell();
- if ch != '\t' {
+ ncells := b.terminateCell(ch == '\t');
+ if ch == '\n' || ch == '\f' {
// terminate line
b.addLine();
if ch == '\f' || ncells == 1 {
diff --git a/src/pkg/tabwriter/tabwriter_test.go b/src/pkg/tabwriter/tabwriter_test.go
index 6b2fa862e..b43a26980 100644
--- a/src/pkg/tabwriter/tabwriter_test.go
+++ b/src/pkg/tabwriter/tabwriter_test.go
@@ -418,14 +418,21 @@ var tests = []entry {
entry{
"15b",
4, 0, '.', DiscardEmptyColumns,
- "a\t\tb",
- "a...b"
+ "a\t\tb", // htabs - do not discard column
+ "a.......b"
},
entry{
"15c",
+ 4, 0, '.', DiscardEmptyColumns,
+ "a\v\vb",
+ "a...b"
+ },
+
+ entry{
+ "15d",
4, 0, '.', AlignRight | DiscardEmptyColumns,
- "a\t\tb",
+ "a\v\vb",
"...ab"
},
@@ -448,14 +455,30 @@ var tests = []entry {
entry{
"16b",
100, 0, '\t', DiscardEmptyColumns,
- "a\tb\t\td\n"
+ "a\vb\v\vd\n"
+ "a\vb\v\vd\ve\n"
+ "a\n"
+ "a\vb\vc\vd\n"
+ "a\vb\vc\vd\ve\n",
+
+ "a\tb\td\n"
+ "a\tb\td\te\n"
+ "a\n"
+ "a\tb\tc\td\n"
+ "a\tb\tc\td\te\n"
+ },
+
+ entry{
+ "16c",
+ 100, 0, '\t', DiscardEmptyColumns,
+ "a\tb\t\td\n" // hard tabs - do not discard column
"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\tb\t\td\n"
+ "a\tb\t\td\te\n"
"a\n"
"a\tb\tc\td\n"
"a\tb\tc\td\te\n"