mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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:
parent
c7ab332744
commit
bf67afc84e
3 changed files with 117 additions and 17 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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':
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue