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
diff --git a/src/lib/fmt/fmt_test.go b/src/lib/fmt/fmt_test.go
index 4b423c6..d7372c0 100644
--- a/src/lib/fmt/fmt_test.go
+++ b/src/lib/fmt/fmt_test.go
@@ -6,6 +6,7 @@
import (
"fmt";
+ "io";
"syscall";
"testing";
)
@@ -163,3 +164,77 @@
}
}
+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);
+ }
+ }
+}
diff --git a/src/lib/fmt/format.go b/src/lib/fmt/format.go
index d1c20a5..4a5dea5 100644
--- a/src/lib/fmt/format.go
+++ b/src/lib/fmt/format.go
@@ -50,7 +50,9 @@
}
func (f *Fmt) clearflags() {
+ f.wid = 0;
f.wid_present = false;
+ f.prec = 0;
f.prec_present = false;
f.minus = false;
f.plus = false;
diff --git a/src/lib/fmt/print.go b/src/lib/fmt/print.go
index 0ce27ce..9ac241f 100644
--- a/src/lib/fmt/print.go
+++ b/src/lib/fmt/print.go
@@ -23,6 +23,9 @@
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 @@
n int;
buf *[]byte;
fmt *Fmt;
- wid int;
- wid_ok bool;
- prec int;
- prec_ok bool;
}
func Printer() *P {
@@ -53,11 +52,27 @@
}
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 @@
}
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 @@
continue;
}
i++;
- // flags
+ // flags and widths
+ p.fmt.clearflags();
F: for ; i < end; i++ {
switch format[i] {
case '#':
@@ -416,11 +446,10 @@
}
}
// 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 @@
}
}
s := "";
- if p.wid_ok {
- p.fmt.w(p.wid);
- }
- if p.prec_ok {
- p.fmt.p(p.prec);
- }
switch c {
// bool
case 't':