cellwidth int;
padding int;
padbytes [8]byte;
- align_left bool;
- filter_html bool;
+ flags uint;
// current state
html_char byte; // terminating char of html tag/entity, or 0 ('>', ';', or 0)
}
+// Formatting can be controlled with these flags.
+const (
+ // Ignore html tags and treat entities (starting with '&'
+ // and ending in ';') as single characters (width = 1).
+ FilterHTML = 1 << iota;
+
+ // Force right-alignment of cell content.
+ // Default is left-alignment.
+ AlignRight;
+)
+
+
// A Writer must be initialized with a call to Init. The first parameter (output)
// specifies the filter output. The remaining parameters control the formatting:
//
// and cells are left-aligned independent of align_left
// (for correct-looking results, cellwidth must correspond
// to the tab width in the viewer displaying the result)
-// align_left alignment of cell content
-// filter_html ignores html tags and treats entities (starting with '&'
-// and ending in ';') as single characters (width = 1)
+// flags formatting control
//
-func (b *Writer) Init(output io.Write, cellwidth, padding int, padchar byte, align_left, filter_html bool) *Writer {
+func (b *Writer) Init(output io.Write, cellwidth, padding int, padchar byte, flags uint) *Writer {
if cellwidth < 0 {
panic("negative cellwidth");
}
for i := len(b.padbytes) - 1; i >= 0; i-- {
b.padbytes[i] = padchar;
}
- b.align_left = align_left || padchar == '\t'; // tab enforces left-alignment
- b.filter_html = filter_html;
+ if padchar == '\t' {
+ // tab enforces left-alignment
+ t := ^AlignRight; // TODO 6g bug
+ flags &= uint(t);
+ }
+ b.flags = flags;
b.buf.Init(1024);
b.lines_size.Init(0);
for j := 0; j < line_size.Len(); j++ {
s, w := line_size.At(j), line_width.At(j);
- if b.align_left {
+ switch {
+ default: // align left
+
err = b.write0(b.buf.slice(pos, pos + s));
if err != nil {
goto exit;
}
}
- } else { // align right
+ case b.flags & AlignRight != 0: // align right
if j < b.widths.Len() {
err = b.writePadding(w, b.widths.At(j));
}
case '<', '&':
- if b.filter_html {
+ if b.flags & FilterHTML != 0 {
b.append(buf[i0 : i]);
i0 = i;
b.width += unicodeLen(b.buf.slice(b.pos, b.buf.Len()));
}
-// New allocates and initializes a new tabwriter.Writer.
+// NewWriter allocates and initializes a new tabwriter.Writer.
// The parameters are the same as for the the Init function.
//
-func New(writer io.Write, cellwidth, padding int, padchar byte, align_left, filter_html bool) *Writer {
- return new(Writer).Init(writer, cellwidth, padding, padchar, align_left, filter_html)
+func NewWriter(writer io.Write, cellwidth, padding int, padchar byte, flags uint) *Writer {
+ return new(Writer).Init(writer, cellwidth, padding, padchar, flags)
}
}
-func check(t *testing.T, tabwidth, padding int, padchar byte, align_left, filter_html bool, src, expected string) {
+func check(t *testing.T, tabwidth, padding int, padchar byte, flags uint, src, expected string) {
var b buffer;
b.init(1000);
var w tabwriter.Writer;
- w.Init(&b, tabwidth, padding, padchar, align_left, filter_html);
+ w.Init(&b, tabwidth, padding, padchar, flags);
// write all at once
b.clear();
func Test(t *testing.T) {
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"",
""
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"\n\n\n",
"\n\n\n"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"a\nb\nc",
"a\nb\nc"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"\t", // '\t' terminates an empty cell on last line - nothing to print
""
);
check(
- t, 8, 1, '.', false, false,
+ t, 8, 1, '.', tabwriter.AlignRight,
"\t", // '\t' terminates an empty cell on last line - nothing to print
""
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"*\t*",
"**"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"*\t*\n",
"*.......*\n"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"*\t*\t",
"*.......*"
);
check(
- t, 8, 1, '.', false, false,
+ t, 8, 1, '.', tabwriter.AlignRight,
"*\t*\t",
".......**"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"\t\n",
"........\n"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"a) foo",
"a) foo"
);
check(
- t, 8, 1, ' ', true, false,
+ t, 8, 1, ' ', 0,
"b) foo\tbar", // "bar" is not in any cell - not formatted, just flushed
"b) foobar"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"c) foo\tbar\t",
"c) foo..bar"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"d) foo\tbar\n",
"d) foo..bar\n"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"e) foo\tbar\t\n",
"e) foo..bar.....\n"
);
check(
- t, 8, 1, '.', true, true,
+ t, 8, 1, '.', tabwriter.FilterHTML,
"e) f<o\t<b>bar</b>\t\n",
"e) f<o..<b>bar</b>.....\n"
);
check(
- t, 8, 1, '*', true, false,
+ t, 8, 1, '*', 0,
"Hello, world!\n",
"Hello, world!\n"
);
check(
- t, 0, 0, '.', true, false,
+ t, 0, 0, '.', 0,
"1\t2\t3\t4\n"
"11\t222\t3333\t44444\n",
);
check(
- t, 5, 0, '.', true, false,
+ t, 5, 0, '.', 0,
"1\t2\t3\t4\n",
"1....2....3....4\n"
);
check(
- t, 5, 0, '.', true, false,
+ t, 5, 0, '.', 0,
"1\t2\t3\t4\t\n",
"1....2....3....4....\n"
);
check(
- t, 8, 1, '.', true, false,
+ t, 8, 1, '.', 0,
"本\tb\tc\n"
"aa\t\u672c\u672c\u672c\tcccc\tddddd\n"
"aaa\tbbbb\n",
);
check(
- t, 8, 1, ' ', false, false,
+ t, 8, 1, ' ', tabwriter.AlignRight,
"a\tè\tc\t\n"
"aa\tèèè\tcccc\tddddd\t\n"
"aaa\tèèèè\t\n",
);
check(
- t, 2, 0, ' ', true, false,
+ t, 2, 0, ' ', 0,
"a\tb\tc\n"
"aa\tbbb\tcccc\n"
"aaa\tbbbb\n",
);
check(
- t, 8, 1, '_', true, false,
+ t, 8, 1, '_', 0,
"a\tb\tc\n"
"aa\tbbb\tcccc\n"
"aaa\tbbbb\n",
);
check(
- t, 4, 1, '-', true, false,
+ t, 4, 1, '-', 0,
"4444\t日本語\t22\t1\t333\n"
"999999999\t22\n"
"7\t22\n"
);
check(
- t, 4, 3, '.', true, false,
+ t, 4, 3, '.', 0,
"4444\t333\t22\t1\t333\n"
"999999999\t22\n"
"7\t22\n"
);
check(
- t, 8, 1, '\t', true, true,
+ t, 8, 1, '\t', tabwriter.FilterHTML,
"4444\t333\t22\t1\t333\n"
"999999999\t22\n"
"7\t22\n"
);
check(
- t, 0, 2, ' ', false, false,
+ t, 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"