github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/util/ui/ui_for_push.go (about) 1 package ui 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "sort" 8 "strings" 9 10 "github.com/liamawhite/cli-with-i18n/types" 11 12 "github.com/fatih/color" 13 ) 14 15 var ErrValueMissmatch = errors.New("values provided were of different types") 16 17 type Change struct { 18 Header string 19 CurrentValue interface{} 20 NewValue interface{} 21 HiddenValue bool 22 } 23 24 // DisplayChangesForPush will display the set of changes via 25 // DisplayChangeForPush in the order given. 26 func (ui *UI) DisplayChangesForPush(changeSet []Change) error { 27 if len(changeSet) == 0 { 28 return nil 29 } 30 31 var columnWidth int 32 for _, change := range changeSet { 33 if width := wordSize(ui.TranslateText(change.Header)); width > columnWidth { 34 columnWidth = width 35 } 36 } 37 38 for _, change := range changeSet { 39 padding := columnWidth - wordSize(ui.TranslateText(change.Header)) + 3 40 err := ui.DisplayChangeForPush(change.Header, padding, change.HiddenValue, change.CurrentValue, change.NewValue) 41 if err != nil { 42 return err 43 } 44 } 45 46 return nil 47 } 48 49 // DisplayChangeForPush will display the header and old/new value with the 50 // appropriately red/green minuses and pluses. 51 func (ui *UI) DisplayChangeForPush(header string, stringTypePadding int, hiddenValue bool, originalValue interface{}, newValue interface{}) error { 52 ui.terminalLock.Lock() 53 defer ui.terminalLock.Unlock() 54 55 originalType := reflect.ValueOf(originalValue).Type() 56 newType := reflect.ValueOf(newValue).Type() 57 if originalType != newType { 58 return ErrValueMissmatch 59 } 60 61 offset := strings.Repeat(" ", stringTypePadding) 62 63 switch oVal := originalValue.(type) { 64 case int: 65 nVal := newValue.(int) 66 ui.displayDiffForInt(offset, header, oVal, nVal) 67 case types.NullInt: 68 nVal := newValue.(types.NullInt) 69 ui.displayDiffForNullInt(offset, header, oVal, nVal) 70 case string: 71 nVal := newValue.(string) 72 ui.displayDiffForString(offset, header, hiddenValue, oVal, nVal) 73 case []string: 74 nVal := newValue.([]string) 75 if len(oVal) == 0 && len(nVal) == 0 { 76 return nil 77 } 78 79 ui.displayDiffForStrings(offset, header, oVal, nVal) 80 case map[string]string: 81 nVal := newValue.(map[string]string) 82 if len(oVal) == 0 && len(nVal) == 0 { 83 return nil 84 } 85 86 ui.displayDiffForMapStringString(offset, header, oVal, nVal) 87 default: 88 panic(fmt.Sprintf("diff display does not have case for '%s'", header)) 89 } 90 return nil 91 } 92 93 func (ui UI) displayDiffForInt(offset string, header string, oldValue int, newValue int) { 94 if oldValue != newValue { 95 formattedOld := fmt.Sprintf("- %s%s%d", ui.TranslateText(header), offset, oldValue) 96 formattedNew := fmt.Sprintf("+ %s%s%d", ui.TranslateText(header), offset, newValue) 97 98 if oldValue != 0 { 99 fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed))) 100 } 101 fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen))) 102 } else { 103 fmt.Fprintf(ui.Out, " %s%s%d\n", ui.TranslateText(header), offset, oldValue) 104 } 105 } 106 107 func (ui UI) displayDiffForMapStringString(offset string, header string, oldMap map[string]string, newMap map[string]string) { 108 var oldKeys []string 109 for key := range oldMap { 110 oldKeys = append(oldKeys, key) 111 } 112 113 var newKeys []string 114 for key := range newMap { 115 newKeys = append(newKeys, key) 116 } 117 118 sortedKeys := sortedUniqueArray(oldKeys, newKeys) 119 120 fmt.Fprintf(ui.Out, " %s\n", ui.TranslateText(header)) 121 for _, key := range sortedKeys { 122 newVal, ok := newMap[key] 123 if !ok { 124 formattedOld := fmt.Sprintf("- %s", key) 125 fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed))) 126 continue 127 } 128 oldVal, ok := oldMap[key] 129 if !ok { 130 formattedNew := fmt.Sprintf("+ %s", key) 131 fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen))) 132 continue 133 } 134 135 if oldVal == newVal { 136 fmt.Fprintf(ui.Out, " %s\n", key) 137 } else { 138 formattedOld := fmt.Sprintf("- %s", key) 139 fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed))) 140 formattedNew := fmt.Sprintf("+ %s", key) 141 fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen))) 142 } 143 } 144 } 145 146 func (ui UI) displayDiffForNullInt(offset string, header string, oldValue types.NullInt, newValue types.NullInt) { 147 if oldValue != newValue { 148 formattedOld := fmt.Sprintf("- %s%s%d", ui.TranslateText(header), offset, oldValue.Value) 149 formattedNew := fmt.Sprintf("+ %s%s%d", ui.TranslateText(header), offset, newValue.Value) 150 151 if oldValue.IsSet { 152 fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed))) 153 } 154 fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen))) 155 } else { 156 fmt.Fprintf(ui.Out, " %s%s%d\n", ui.TranslateText(header), offset, oldValue.Value) 157 } 158 } 159 160 func (ui UI) displayDiffForString(offset string, header string, hiddenValue bool, oVal string, nVal string) { 161 if oVal != nVal { 162 var formattedOld, formattedNew string 163 if hiddenValue { 164 formattedOld = fmt.Sprintf("- %s%s%s", ui.TranslateText(header), offset, RedactedValue) 165 formattedNew = fmt.Sprintf("+ %s%s%s", ui.TranslateText(header), offset, RedactedValue) 166 } else { 167 formattedOld = fmt.Sprintf("- %s%s%s", ui.TranslateText(header), offset, oVal) 168 formattedNew = fmt.Sprintf("+ %s%s%s", ui.TranslateText(header), offset, nVal) 169 } 170 171 if oVal != "" { 172 fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed))) 173 } 174 if nVal != "" { 175 fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen))) 176 } 177 } else { 178 if hiddenValue { 179 fmt.Fprintf(ui.Out, " %s%s%s\n", ui.TranslateText(header), offset, RedactedValue) 180 } else { 181 fmt.Fprintf(ui.Out, " %s%s%s\n", ui.TranslateText(header), offset, oVal) 182 } 183 } 184 } 185 186 func (ui UI) displayDiffForStrings(offset string, header string, oldList []string, newList []string) { 187 fmt.Fprintf(ui.Out, " %s\n", ui.TranslateText(header)) 188 189 fullList := sortedUniqueArray(oldList, newList) 190 for _, item := range fullList { 191 inOld := existsIn(item, oldList) 192 inNew := existsIn(item, newList) 193 194 if inOld && inNew { 195 fmt.Fprintf(ui.Out, " %s\n", item) 196 } else if inOld { 197 formattedOld := fmt.Sprintf("- %s", item) 198 fmt.Fprintln(ui.Out, ui.modifyColor(formattedOld, color.New(color.FgRed))) 199 } else { 200 formattedNew := fmt.Sprintf("+ %s", item) 201 fmt.Fprintln(ui.Out, ui.modifyColor(formattedNew, color.New(color.FgGreen))) 202 } 203 } 204 } 205 206 func existsIn(str string, ary []string) bool { 207 for _, val := range ary { 208 if val == str { 209 return true 210 } 211 } 212 return false 213 } 214 215 func sortedUniqueArray(ary1 []string, ary2 []string) []string { 216 uniq := append([]string{}, ary1...) 217 218 for _, str := range ary2 { 219 if !existsIn(str, uniq) { 220 uniq = append(uniq, str) 221 } 222 } 223 224 sort.Strings(uniq) 225 return uniq 226 }