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 (
|
import (
|
||||||
"fmt";
|
"fmt";
|
||||||
|
"io";
|
||||||
"syscall";
|
"syscall";
|
||||||
"testing";
|
"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() {
|
func (f *Fmt) clearflags() {
|
||||||
|
f.wid = 0;
|
||||||
f.wid_present = false;
|
f.wid_present = false;
|
||||||
|
f.prec = 0;
|
||||||
f.prec_present = false;
|
f.prec_present = false;
|
||||||
f.minus = false;
|
f.minus = false;
|
||||||
f.plus = false;
|
f.plus = false;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ export type Formatter interface {
|
||||||
Write(b *[]byte) (ret int, err *os.Error);
|
Write(b *[]byte) (ret int, err *os.Error);
|
||||||
Width() (wid int, ok bool);
|
Width() (wid int, ok bool);
|
||||||
Precision() (prec int, ok bool);
|
Precision() (prec int, ok bool);
|
||||||
|
|
||||||
|
// flags
|
||||||
|
Flag(int) bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Format interface {
|
type Format interface {
|
||||||
|
|
@ -40,10 +43,6 @@ type P struct {
|
||||||
n int;
|
n int;
|
||||||
buf *[]byte;
|
buf *[]byte;
|
||||||
fmt *Fmt;
|
fmt *Fmt;
|
||||||
wid int;
|
|
||||||
wid_ok bool;
|
|
||||||
prec int;
|
|
||||||
prec_ok bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Printer() *P {
|
func Printer() *P {
|
||||||
|
|
@ -53,11 +52,27 @@ func Printer() *P {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *P) Width() (wid int, ok bool) {
|
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) {
|
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) {
|
func (p *P) ensure(n int) {
|
||||||
|
|
@ -369,7 +384,21 @@ func (p *P) printField(field reflect.Value) (was_string bool) {
|
||||||
}
|
}
|
||||||
case reflect.StructKind:
|
case reflect.StructKind:
|
||||||
p.add('{');
|
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('}');
|
p.add('}');
|
||||||
case reflect.InterfaceKind:
|
case reflect.InterfaceKind:
|
||||||
inter := field.(reflect.InterfaceValue).Get();
|
inter := field.(reflect.InterfaceValue).Get();
|
||||||
|
|
@ -398,7 +427,8 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
// flags
|
// flags and widths
|
||||||
|
p.fmt.clearflags();
|
||||||
F: for ; i < end; i++ {
|
F: for ; i < end; i++ {
|
||||||
switch format[i] {
|
switch format[i] {
|
||||||
case '#':
|
case '#':
|
||||||
|
|
@ -416,11 +446,10 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// do we have 20 (width)?
|
// do we have 20 (width)?
|
||||||
p.wid, p.wid_ok, i = parsenum(format, i, end);
|
p.fmt.wid, p.fmt.wid_present, i = parsenum(format, i, end);
|
||||||
p.prec_ok = false;
|
|
||||||
// do we have .20 (precision)?
|
// do we have .20 (precision)?
|
||||||
if i < end && format[i] == '.' {
|
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);
|
c, w = sys.stringtorune(format, i);
|
||||||
i += w;
|
i += w;
|
||||||
|
|
@ -445,12 +474,6 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s := "";
|
s := "";
|
||||||
if p.wid_ok {
|
|
||||||
p.fmt.w(p.wid);
|
|
||||||
}
|
|
||||||
if p.prec_ok {
|
|
||||||
p.fmt.p(p.prec);
|
|
||||||
}
|
|
||||||
switch c {
|
switch c {
|
||||||
// bool
|
// bool
|
||||||
case 't':
|
case 't':
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue