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