gopkg.in/tools/godep.v67@v67.0.0-20160513230433-2d182dfe781d/Godeps/_workspace/src/github.com/kr/pretty/formatter.go (about) 1 package pretty 2 3 import ( 4 "fmt" 5 "io" 6 "reflect" 7 "strconv" 8 "text/tabwriter" 9 10 "github.com/tools/godep/Godeps/_workspace/src/github.com/kr/text" 11 ) 12 13 const ( 14 limit = 50 15 ) 16 17 type formatter struct { 18 x interface{} 19 force bool 20 quote bool 21 } 22 23 // Formatter makes a wrapper, f, that will format x as go source with line 24 // breaks and tabs. Object f responds to the "%v" formatting verb when both the 25 // "#" and " " (space) flags are set, for example: 26 // 27 // fmt.Sprintf("%# v", Formatter(x)) 28 // 29 // If one of these two flags is not set, or any other verb is used, f will 30 // format x according to the usual rules of package fmt. 31 // In particular, if x satisfies fmt.Formatter, then x.Format will be called. 32 func Formatter(x interface{}) (f fmt.Formatter) { 33 return formatter{x: x, quote: true} 34 } 35 36 func (fo formatter) String() string { 37 return fmt.Sprint(fo.x) // unwrap it 38 } 39 40 func (fo formatter) passThrough(f fmt.State, c rune) { 41 s := "%" 42 for i := 0; i < 128; i++ { 43 if f.Flag(i) { 44 s += string(i) 45 } 46 } 47 if w, ok := f.Width(); ok { 48 s += fmt.Sprintf("%d", w) 49 } 50 if p, ok := f.Precision(); ok { 51 s += fmt.Sprintf(".%d", p) 52 } 53 s += string(c) 54 fmt.Fprintf(f, s, fo.x) 55 } 56 57 func (fo formatter) Format(f fmt.State, c rune) { 58 if fo.force || c == 'v' && f.Flag('#') && f.Flag(' ') { 59 w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0) 60 p := &printer{tw: w, Writer: w, visited: make(map[visit]int)} 61 p.printValue(reflect.ValueOf(fo.x), true, fo.quote) 62 w.Flush() 63 return 64 } 65 fo.passThrough(f, c) 66 } 67 68 type printer struct { 69 io.Writer 70 tw *tabwriter.Writer 71 visited map[visit]int 72 depth int 73 } 74 75 func (p *printer) indent() *printer { 76 q := *p 77 q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0) 78 q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'}) 79 return &q 80 } 81 82 func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) { 83 if showType { 84 io.WriteString(p, v.Type().String()) 85 fmt.Fprintf(p, "(%#v)", x) 86 } else { 87 fmt.Fprintf(p, "%#v", x) 88 } 89 } 90 91 // printValue must keep track of already-printed pointer values to avoid 92 // infinite recursion. 93 type visit struct { 94 v uintptr 95 typ reflect.Type 96 } 97 98 func (p *printer) printValue(v reflect.Value, showType, quote bool) { 99 if p.depth > 10 { 100 io.WriteString(p, "!%v(DEPTH EXCEEDED)") 101 return 102 } 103 104 switch v.Kind() { 105 case reflect.Bool: 106 p.printInline(v, v.Bool(), showType) 107 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 108 p.printInline(v, v.Int(), showType) 109 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 110 p.printInline(v, v.Uint(), showType) 111 case reflect.Float32, reflect.Float64: 112 p.printInline(v, v.Float(), showType) 113 case reflect.Complex64, reflect.Complex128: 114 fmt.Fprintf(p, "%#v", v.Complex()) 115 case reflect.String: 116 p.fmtString(v.String(), quote) 117 case reflect.Map: 118 t := v.Type() 119 if showType { 120 io.WriteString(p, t.String()) 121 } 122 writeByte(p, '{') 123 if nonzero(v) { 124 expand := !canInline(v.Type()) 125 pp := p 126 if expand { 127 writeByte(p, '\n') 128 pp = p.indent() 129 } 130 keys := v.MapKeys() 131 for i := 0; i < v.Len(); i++ { 132 showTypeInStruct := true 133 k := keys[i] 134 mv := v.MapIndex(k) 135 pp.printValue(k, false, true) 136 writeByte(pp, ':') 137 if expand { 138 writeByte(pp, '\t') 139 } 140 showTypeInStruct = t.Elem().Kind() == reflect.Interface 141 pp.printValue(mv, showTypeInStruct, true) 142 if expand { 143 io.WriteString(pp, ",\n") 144 } else if i < v.Len()-1 { 145 io.WriteString(pp, ", ") 146 } 147 } 148 if expand { 149 pp.tw.Flush() 150 } 151 } 152 writeByte(p, '}') 153 case reflect.Struct: 154 t := v.Type() 155 if v.CanAddr() { 156 addr := v.UnsafeAddr() 157 vis := visit{addr, t} 158 if vd, ok := p.visited[vis]; ok && vd < p.depth { 159 p.fmtString(t.String()+"{(CYCLIC REFERENCE)}", false) 160 break // don't print v again 161 } 162 p.visited[vis] = p.depth 163 } 164 165 if showType { 166 io.WriteString(p, t.String()) 167 } 168 writeByte(p, '{') 169 if nonzero(v) { 170 expand := !canInline(v.Type()) 171 pp := p 172 if expand { 173 writeByte(p, '\n') 174 pp = p.indent() 175 } 176 for i := 0; i < v.NumField(); i++ { 177 showTypeInStruct := true 178 if f := t.Field(i); f.Name != "" { 179 io.WriteString(pp, f.Name) 180 writeByte(pp, ':') 181 if expand { 182 writeByte(pp, '\t') 183 } 184 showTypeInStruct = labelType(f.Type) 185 } 186 pp.printValue(getField(v, i), showTypeInStruct, true) 187 if expand { 188 io.WriteString(pp, ",\n") 189 } else if i < v.NumField()-1 { 190 io.WriteString(pp, ", ") 191 } 192 } 193 if expand { 194 pp.tw.Flush() 195 } 196 } 197 writeByte(p, '}') 198 case reflect.Interface: 199 switch e := v.Elem(); { 200 case e.Kind() == reflect.Invalid: 201 io.WriteString(p, "nil") 202 case e.IsValid(): 203 pp := *p 204 pp.depth++ 205 pp.printValue(e, showType, true) 206 default: 207 io.WriteString(p, v.Type().String()) 208 io.WriteString(p, "(nil)") 209 } 210 case reflect.Array, reflect.Slice: 211 t := v.Type() 212 if showType { 213 io.WriteString(p, t.String()) 214 } 215 if v.Kind() == reflect.Slice && v.IsNil() && showType { 216 io.WriteString(p, "(nil)") 217 break 218 } 219 if v.Kind() == reflect.Slice && v.IsNil() { 220 io.WriteString(p, "nil") 221 break 222 } 223 writeByte(p, '{') 224 expand := !canInline(v.Type()) 225 pp := p 226 if expand { 227 writeByte(p, '\n') 228 pp = p.indent() 229 } 230 for i := 0; i < v.Len(); i++ { 231 showTypeInSlice := t.Elem().Kind() == reflect.Interface 232 pp.printValue(v.Index(i), showTypeInSlice, true) 233 if expand { 234 io.WriteString(pp, ",\n") 235 } else if i < v.Len()-1 { 236 io.WriteString(pp, ", ") 237 } 238 } 239 if expand { 240 pp.tw.Flush() 241 } 242 writeByte(p, '}') 243 case reflect.Ptr: 244 e := v.Elem() 245 if !e.IsValid() { 246 writeByte(p, '(') 247 io.WriteString(p, v.Type().String()) 248 io.WriteString(p, ")(nil)") 249 } else { 250 pp := *p 251 pp.depth++ 252 writeByte(pp, '&') 253 pp.printValue(e, true, true) 254 } 255 case reflect.Chan: 256 x := v.Pointer() 257 if showType { 258 writeByte(p, '(') 259 io.WriteString(p, v.Type().String()) 260 fmt.Fprintf(p, ")(%#v)", x) 261 } else { 262 fmt.Fprintf(p, "%#v", x) 263 } 264 case reflect.Func: 265 io.WriteString(p, v.Type().String()) 266 io.WriteString(p, " {...}") 267 case reflect.UnsafePointer: 268 p.printInline(v, v.Pointer(), showType) 269 case reflect.Invalid: 270 io.WriteString(p, "nil") 271 } 272 } 273 274 func canInline(t reflect.Type) bool { 275 switch t.Kind() { 276 case reflect.Map: 277 return !canExpand(t.Elem()) 278 case reflect.Struct: 279 for i := 0; i < t.NumField(); i++ { 280 if canExpand(t.Field(i).Type) { 281 return false 282 } 283 } 284 return true 285 case reflect.Interface: 286 return false 287 case reflect.Array, reflect.Slice: 288 return !canExpand(t.Elem()) 289 case reflect.Ptr: 290 return false 291 case reflect.Chan, reflect.Func, reflect.UnsafePointer: 292 return false 293 } 294 return true 295 } 296 297 func canExpand(t reflect.Type) bool { 298 switch t.Kind() { 299 case reflect.Map, reflect.Struct, 300 reflect.Interface, reflect.Array, reflect.Slice, 301 reflect.Ptr: 302 return true 303 } 304 return false 305 } 306 307 func labelType(t reflect.Type) bool { 308 switch t.Kind() { 309 case reflect.Interface, reflect.Struct: 310 return true 311 } 312 return false 313 } 314 315 func (p *printer) fmtString(s string, quote bool) { 316 if quote { 317 s = strconv.Quote(s) 318 } 319 io.WriteString(p, s) 320 } 321 322 func tryDeepEqual(a, b interface{}) bool { 323 defer func() { recover() }() 324 return reflect.DeepEqual(a, b) 325 } 326 327 func writeByte(w io.Writer, b byte) { 328 w.Write([]byte{b}) 329 } 330 331 func getField(v reflect.Value, i int) reflect.Value { 332 val := v.Field(i) 333 if val.Kind() == reflect.Interface && !val.IsNil() { 334 val = val.Elem() 335 } 336 return val 337 }