github.com/elves/elvish@v0.15.0/pkg/eval/vals/repr.go (about) 1 package vals 2 3 import ( 4 "fmt" 5 "math" 6 "reflect" 7 8 "github.com/elves/elvish/pkg/parse" 9 ) 10 11 // NoPretty can be passed to Repr to suppress pretty-printing. 12 const NoPretty = math.MinInt32 13 14 // Reprer wraps the Repr method. 15 type Reprer interface { 16 // Repr returns a string that represents a Value. The string either be a 17 // literal of that Value that is preferably deep-equal to it (like `[a b c]` 18 // for a list), or a string enclosed in "<>" containing the kind and 19 // identity of the Value(like `<fn 0xdeadcafe>`). 20 // 21 // If indent is at least 0, it should be pretty-printed with the current 22 // indentation level of indent; the indent of the first line has already 23 // been written and shall not be written in Repr. The returned string 24 // should never contain a trailing newline. 25 Repr(indent int) string 26 } 27 28 // Repr returns the representation for a value, a string that is preferably (but 29 // not necessarily) an Elvish expression that evaluates to the argument. If 30 // indent >= 0, the representation is pretty-printed. It is implemented for the 31 // builtin types nil, bool and string, the File, List and Map types, StructMap 32 // types, and types satisfying the Reprer interface. For other types, it uses 33 // fmt.Sprint with the format "<unknown %v>". 34 func Repr(v interface{}, indent int) string { 35 switch v := v.(type) { 36 case nil: 37 return "$nil" 38 case bool: 39 if v { 40 return "$true" 41 } 42 return "$false" 43 case string: 44 return parse.Quote(v) 45 case float64: 46 return "(float64 " + formatFloat64(v) + ")" 47 case Reprer: 48 return v.Repr(indent) 49 case File: 50 return fmt.Sprintf("<file{%s %d}>", parse.Quote(v.Name()), v.Fd()) 51 case List: 52 b := NewListReprBuilder(indent) 53 for it := v.Iterator(); it.HasElem(); it.Next() { 54 b.WriteElem(Repr(it.Elem(), indent+1)) 55 } 56 return b.String() 57 case Map: 58 builder := NewMapReprBuilder(indent) 59 for it := v.Iterator(); it.HasElem(); it.Next() { 60 k, v := it.Elem() 61 builder.WritePair(Repr(k, indent+1), indent+2, Repr(v, indent+2)) 62 } 63 return builder.String() 64 case StructMap: 65 return reprStructMap(v, indent) 66 case PseudoStructMap: 67 return reprStructMap(v.Fields(), indent) 68 default: 69 return fmt.Sprintf("<unknown %v>", v) 70 } 71 } 72 73 func reprStructMap(v StructMap, indent int) string { 74 vValue := reflect.ValueOf(v) 75 vType := vValue.Type() 76 builder := NewMapReprBuilder(indent) 77 it := iterateStructMap(vType) 78 for it.Next() { 79 k, v := it.Get(vValue) 80 builder.WritePair(Repr(k, indent+1), indent+2, Repr(v, indent+2)) 81 } 82 return builder.String() 83 }