github.com/hashicorp/packer@v1.14.3/hcl2template/repl/format.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package repl 5 6 import ( 7 "bufio" 8 "bytes" 9 "fmt" 10 "sort" 11 "strconv" 12 "strings" 13 ) 14 15 // FormatResult formats the given result value for human-readable output. 16 // 17 // The value must currently be a string, list, map, and any nested values 18 // with those same types. 19 func FormatResult(value interface{}) string { 20 return formatResult(value, false) 21 } 22 23 func formatResult(value interface{}, nested bool) string { 24 if value == nil { 25 return "null" 26 } 27 switch output := value.(type) { 28 case string: 29 if nested { 30 return fmt.Sprintf("%q", output) 31 } 32 return output 33 case int: 34 return strconv.Itoa(output) 35 case float64: 36 return fmt.Sprintf("%g", output) 37 case bool: 38 switch { 39 case output == true: 40 return "true" 41 default: 42 return "false" 43 } 44 case []interface{}: 45 return formatListResult(output) 46 case map[string]interface{}: 47 return formatMapResult(output) 48 default: 49 return "<unknown-type>" 50 } 51 } 52 53 func formatListResult(value []interface{}) string { 54 var outputBuf bytes.Buffer 55 outputBuf.WriteString("[") 56 if len(value) > 0 { 57 outputBuf.WriteString("\n") 58 } 59 60 for _, v := range value { 61 raw := formatResult(v, true) 62 outputBuf.WriteString(indent(raw)) 63 outputBuf.WriteString(",\n") 64 } 65 66 outputBuf.WriteString("]") 67 return outputBuf.String() 68 } 69 70 func formatMapResult(value map[string]interface{}) string { 71 ks := make([]string, 0, len(value)) 72 for k := range value { 73 ks = append(ks, k) 74 } 75 sort.Strings(ks) 76 77 var outputBuf bytes.Buffer 78 outputBuf.WriteString("{") 79 if len(value) > 0 { 80 outputBuf.WriteString("\n") 81 } 82 83 for _, k := range ks { 84 v := value[k] 85 rawK := formatResult(k, true) 86 rawV := formatResult(v, true) 87 88 outputBuf.WriteString(indent(fmt.Sprintf("%s = %s", rawK, rawV))) 89 outputBuf.WriteString("\n") 90 } 91 92 outputBuf.WriteString("}") 93 return outputBuf.String() 94 } 95 96 func indent(value string) string { 97 var outputBuf bytes.Buffer 98 s := bufio.NewScanner(strings.NewReader(value)) 99 newline := false 100 for s.Scan() { 101 if newline { 102 outputBuf.WriteByte('\n') 103 } 104 outputBuf.WriteString(" " + s.Text()) 105 newline = true 106 } 107 108 return outputBuf.String() 109 }