mirror of
https://github.com/golang/go
synced 2024-11-25 11:57:58 -07:00
support for "hard" and "soft" tabs:
- soft-tab separated columns can be discarded if empty and DiscardEmptyColumns is set - hard-tab separated columns are never discarded R=rsc DELTA=63 (42 added, 7 deleted, 14 changed) OCL=35421 CL=35435
This commit is contained in:
parent
c2874976e4
commit
f77b255c38
@ -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 {
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user