print field names on struct members.

also don't concatenate strings next
to each other in the struct,
like p.doprint does.

expose additional print flags to formatters

R=r
DELTA=128  (111 added, 11 deleted, 6 changed)
OCL=20991
CL=21018
This commit is contained in:
Russ Cox 2008-12-11 16:53:33 -08:00
parent c7ab332744
commit bf67afc84e
3 changed files with 117 additions and 17 deletions

View file

@ -6,6 +6,7 @@ package fmt
import (
"fmt";
"io";
"syscall";
"testing";
)
@ -163,3 +164,77 @@ export func TestSprintf(t *testing.T) {
}
}
type FlagPrinter struct { }
func (*FlagPrinter) Format(f fmt.Formatter, c int) {
s := "%";
for i := 0; i < 128; i++ {
if f.Flag(i) {
s += string(i);
}
}
if w, ok := f.Width(); ok {
s += fmt.sprintf("%d", w);
}
if p, ok := f.Precision(); ok {
s += fmt.sprintf(".%d", p);
}
s += string(c);
io.WriteString(f, "["+s+"]");
}
type FlagTest struct {
in string;
out string;
}
var flagtests = []FlagTest {
FlagTest{ "%a", "[%a]" },
FlagTest{ "%-a", "[%-a]" },
FlagTest{ "%+a", "[%+a]" },
FlagTest{ "%#a", "[%#a]" },
FlagTest{ "% a", "[% a]" },
FlagTest{ "%0a", "[%0a]" },
FlagTest{ "%1.2a", "[%1.2a]" },
FlagTest{ "%-1.2a", "[%-1.2a]" },
FlagTest{ "%+1.2a", "[%+1.2a]" },
FlagTest{ "%-+1.2a", "[%+-1.2a]" },
FlagTest{ "%-+1.2abc", "[%+-1.2a]bc" },
FlagTest{ "%-1.2abc", "[%-1.2a]bc" },
}
export func TestFlagParser(t *testing.T) {
var flagprinter FlagPrinter;
for i := 0; i < len(flagtests); i++ {
tt := flagtests[i];
s := fmt.sprintf(tt.in, &flagprinter);
if s != tt.out {
t.Errorf("sprintf(%q, &flagprinter) => %q, want %q", tt.in, s, tt.out);
}
}
}
export func TestStructPrinter(t *testing.T) {
var s struct {
a string;
b string;
c int;
};
s.a = "abc";
s.b = "def";
s.c = 123;
type Test struct {
fmt string;
out string;
}
var tests = []Test {
Test{ "%v", "{abc def 123}" },
Test{ "%+v", "{a=abc b=def c=123}" },
};
for i := 0; i < len(tests); i++ {
tt := tests[i];
out := fmt.sprintf(tt.fmt, s);
if out != tt.out {
t.Errorf("sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out);
}
}
}

View file

@ -50,7 +50,9 @@ export type Fmt struct {
}
func (f *Fmt) clearflags() {
f.wid = 0;
f.wid_present = false;
f.prec = 0;
f.prec_present = false;
f.minus = false;
f.plus = false;

View file

@ -23,6 +23,9 @@ export type Formatter interface {
Write(b *[]byte) (ret int, err *os.Error);
Width() (wid int, ok bool);
Precision() (prec int, ok bool);
// flags
Flag(int) bool;
}
type Format interface {
@ -40,10 +43,6 @@ type P struct {
n int;
buf *[]byte;
fmt *Fmt;
wid int;
wid_ok bool;
prec int;
prec_ok bool;
}
func Printer() *P {
@ -53,11 +52,27 @@ func Printer() *P {
}
func (p *P) Width() (wid int, ok bool) {
return p.wid, p.wid_ok
return p.fmt.wid, p.fmt.wid_present
}
func (p *P) Precision() (prec int, ok bool) {
return p.prec, p.prec_ok
return p.fmt.prec, p.fmt.prec_present
}
func (p *P) Flag(b int) bool {
switch b {
case '-':
return p.fmt.minus;
case '+':
return p.fmt.plus;
case '#':
return p.fmt.sharp;
case ' ':
return p.fmt.space;
case '0':
return p.fmt.zero;
}
return false
}
func (p *P) ensure(n int) {
@ -369,7 +384,21 @@ func (p *P) printField(field reflect.Value) (was_string bool) {
}
case reflect.StructKind:
p.add('{');
p.doprint(field, true, false);
v := field.(reflect.StructValue);
t := v.Type().(reflect.StructType);
donames := p.fmt.plus; // first p.printField clears flag
for i := 0; i < v.Len(); i++ {
if i > 0 {
p.add(' ')
}
if donames {
if name, typ, tag, off := t.Field(i); name != "" {
p.addstr(name);
p.add('=');
}
}
p.printField(getField(v, i));
}
p.add('}');
case reflect.InterfaceKind:
inter := field.(reflect.InterfaceValue).Get();
@ -398,7 +427,8 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
continue;
}
i++;
// flags
// flags and widths
p.fmt.clearflags();
F: for ; i < end; i++ {
switch format[i] {
case '#':
@ -416,11 +446,10 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
}
}
// do we have 20 (width)?
p.wid, p.wid_ok, i = parsenum(format, i, end);
p.prec_ok = false;
p.fmt.wid, p.fmt.wid_present, i = parsenum(format, i, end);
// do we have .20 (precision)?
if i < end && format[i] == '.' {
p.prec, p.prec_ok, i = parsenum(format, i+1, end);
p.fmt.prec, p.fmt.prec_present, i = parsenum(format, i+1, end);
}
c, w = sys.stringtorune(format, i);
i += w;
@ -445,12 +474,6 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
}
}
s := "";
if p.wid_ok {
p.fmt.w(p.wid);
}
if p.prec_ok {
p.fmt.p(p.prec);
}
switch c {
// bool
case 't':