github.com/cjdelisle/matterfoss@v5.11.1+incompatible/cmd/mattermost/commands/utils.go (about) 1 // Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package commands 5 6 import ( 7 "bytes" 8 "fmt" 9 "reflect" 10 "strings" 11 12 "github.com/mattermost/mattermost-server/mlog" 13 ) 14 15 // prettyPrintStruct will return a prettyPrint version of a given struct 16 func prettyPrintStruct(t interface{}) string { 17 return prettyPrintMap(structToMap(t)) 18 } 19 20 // structToMap converts a struct into a map 21 func structToMap(t interface{}) map[string]interface{} { 22 defer func() { 23 if r := recover(); r != nil { 24 mlog.Error(fmt.Sprintf("Panicked in structToMap. This should never happen. %v", r)) 25 } 26 }() 27 28 val := reflect.ValueOf(t) 29 30 if val.Kind() != reflect.Struct { 31 return nil 32 } 33 34 out := map[string]interface{}{} 35 36 for i := 0; i < val.NumField(); i++ { 37 field := val.Field(i) 38 39 var value interface{} 40 41 switch field.Kind() { 42 case reflect.Struct: 43 value = structToMap(field.Interface()) 44 case reflect.Ptr: 45 indirectType := field.Elem() 46 47 if indirectType.Kind() == reflect.Struct { 48 value = structToMap(indirectType.Interface()) 49 } else { 50 value = indirectType.Interface() 51 } 52 default: 53 value = field.Interface() 54 } 55 56 out[val.Type().Field(i).Name] = value 57 } 58 59 return out 60 } 61 62 // prettyPrintMap will return a prettyPrint version of a given map 63 func prettyPrintMap(configMap map[string]interface{}) string { 64 value := reflect.ValueOf(configMap) 65 return printMap(value, 0) 66 } 67 68 // printMap takes a reflect.Value and prints it out, recursively if it's a map with the given tab settings 69 func printMap(value reflect.Value, tabVal int) string { 70 out := &bytes.Buffer{} 71 72 for _, key := range value.MapKeys() { 73 val := value.MapIndex(key) 74 if newVal, ok := val.Interface().(map[string]interface{}); !ok { 75 fmt.Fprintf(out, "%s", strings.Repeat("\t", tabVal)) 76 fmt.Fprintf(out, "%v: \"%v\"\n", key.Interface(), val.Interface()) 77 } else { 78 fmt.Fprintf(out, "%s", strings.Repeat("\t", tabVal)) 79 fmt.Fprintf(out, "%v:\n", key.Interface()) 80 // going one level in, increase the tab 81 tabVal++ 82 fmt.Fprintf(out, "%s", printMap(reflect.ValueOf(newVal), tabVal)) 83 // coming back one level, decrease the tab 84 tabVal-- 85 } 86 } 87 88 return out.String() 89 }