github.com/samlitowitz/goimportcycle@v1.0.9/internal/config/config.go (about) 1 package config 2 3 import ( 4 "fmt" 5 stdColor "image/color" 6 "io" 7 "log" 8 "os" 9 10 "github.com/go-playground/colors" 11 inColor "github.com/samlitowitz/goimportcycle/internal/color" 12 "gopkg.in/yaml.v3" 13 ) 14 15 type Resolution int 16 17 const ( 18 FileResolution Resolution = iota 19 PackageResolution Resolution = iota 20 ) 21 22 type Config struct { 23 Palette *inColor.Palette 24 25 Resolution Resolution 26 Debug *log.Logger 27 } 28 29 type ExternalPalette struct { 30 PackageName string `yaml:"packageName,omitempty"` 31 PackageBackground string `yaml:"packageBackground,omitempty"` 32 FileName string `yaml:"fileName,omitempty"` 33 FileBackground string `yaml:"fileBackground,omitempty"` 34 ImportArrow string `yaml:"importArrow,omitempty"` 35 } 36 37 type externalConfig struct { 38 Resolution string `yaml:"resolution,omitempty"` 39 Palette *struct { 40 Base *ExternalPalette `yaml:"base,omitempty"` 41 Cycle *ExternalPalette `yaml:"cycle,omitempty"` 42 } `yaml:"palette,omitempty"` 43 } 44 45 func Default() *Config { 46 return &Config{ 47 Palette: inColor.Default, 48 Resolution: FileResolution, 49 Debug: log.New(io.Discard, "Debug: ", log.LstdFlags), 50 } 51 } 52 53 func FromYamlFile(filepath string) (*Config, error) { 54 f, err := os.Open(filepath) 55 56 if err != nil { 57 return nil, err 58 } 59 defer f.Close() 60 61 var ecfg externalConfig 62 decoder := yaml.NewDecoder(f) 63 err = decoder.Decode(&ecfg) 64 if err == io.EOF { 65 return Default(), nil 66 } 67 if err != nil { 68 return nil, err 69 } 70 cfg := Default() 71 err = fromExternalConfig(cfg, &ecfg) 72 if err != nil { 73 return nil, err 74 } 75 return cfg, nil 76 } 77 78 func fromExternalConfig(to *Config, from *externalConfig) error { 79 // resolution 80 switch from.Resolution { 81 case "": 82 case "file": 83 to.Resolution = FileResolution 84 case "package": 85 to.Resolution = PackageResolution 86 87 default: 88 return fmt.Errorf( 89 "invalid resolution %s, must be one of ['file', 'package']", 90 from.Resolution, 91 ) 92 } 93 94 // palette 95 if from.Palette == nil { 96 return nil 97 } 98 99 // base palette 100 err := fromExternalPalette(to.Palette.Base, from.Palette.Base) 101 if err != nil { 102 return err 103 } 104 105 // cycle palette 106 err = fromExternalPalette(to.Palette.Cycle, from.Palette.Cycle) 107 if err != nil { 108 return err 109 } 110 111 return nil 112 } 113 114 func fromExternalPalette(to *inColor.HalfPalette, from *ExternalPalette) error { 115 if from == nil { 116 return nil 117 } 118 119 tryParseColor := func(in string) (stdColor.Color, error) { 120 if in == "" { 121 return nil, nil 122 } 123 hex, err := colors.ParseHEX(in) 124 if err == nil { 125 return hex, nil 126 } 127 rgb, err := colors.ParseRGB(in) 128 if err == nil { 129 return rgb, nil 130 } 131 rgba, err := colors.ParseRGBA(in) 132 if err == nil { 133 return rgba, nil 134 } 135 136 if err != nil { 137 return nil, err 138 } 139 return nil, fmt.Errorf("failed to parse color %s", in) 140 } 141 142 if from.PackageName != "" { 143 c, err := tryParseColor(from.PackageName) 144 if err != nil { 145 return err 146 } 147 if c != nil { 148 to.PackageName = inColor.Color{Color: c} 149 } 150 } 151 if from.PackageBackground != "" { 152 c, err := tryParseColor(from.PackageBackground) 153 if err != nil { 154 return err 155 } 156 if c != nil { 157 to.PackageBackground = inColor.Color{Color: c} 158 } 159 } 160 if from.FileName != "" { 161 c, err := tryParseColor(from.FileName) 162 if err != nil { 163 return err 164 } 165 if c != nil { 166 to.FileName = inColor.Color{Color: c} 167 } 168 } 169 if from.FileBackground != "" { 170 c, err := tryParseColor(from.FileBackground) 171 if err != nil { 172 return err 173 } 174 if c != nil { 175 to.FileBackground = inColor.Color{Color: c} 176 } 177 } 178 if from.ImportArrow != "" { 179 c, err := tryParseColor(from.ImportArrow) 180 if err != nil { 181 return err 182 } 183 if c != nil { 184 to.ImportArrow = inColor.Color{Color: c} 185 } 186 } 187 return nil 188 } 189 190 //# File Resolution 191 //1. package name 192 //1. package background 193 //1. file name 194 //1. file background 195 //1. import arrow 196 // 197 //1. not in cycle/in cycle 198 // 199 // 200 //# Package Resolution 201 //1. package name 202 //1. package background 203 //1. import arrow 204 // 205 //1. not in cycle/in cycle