github.com/abdfnx/gh-api@v0.0.0-20210414084727-f5432eec23b8/internal/config/config_type.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"gopkg.in/yaml.v3"
     7  )
     8  
     9  // This interface describes interacting with some persistent configuration for gh.
    10  type Config interface {
    11  	Get(string, string) (string, error)
    12  	GetWithSource(string, string) (string, string, error)
    13  	Set(string, string, string) error
    14  	UnsetHost(string)
    15  	Hosts() ([]string, error)
    16  	DefaultHost() (string, error)
    17  	DefaultHostWithSource() (string, string, error)
    18  	Aliases() (*AliasConfig, error)
    19  	CheckWriteable(string, string) error
    20  	Write() error
    21  }
    22  
    23  type ConfigOption struct {
    24  	Key           string
    25  	Description   string
    26  	DefaultValue  string
    27  	AllowedValues []string
    28  }
    29  
    30  var configOptions = []ConfigOption{
    31  	{
    32  		Key:           "git_protocol",
    33  		Description:   "the protocol to use for git clone and push operations",
    34  		DefaultValue:  "https",
    35  		AllowedValues: []string{"https", "ssh"},
    36  	},
    37  	{
    38  		Key:          "editor",
    39  		Description:  "the text editor program to use for authoring text",
    40  		DefaultValue: "",
    41  	},
    42  	{
    43  		Key:           "prompt",
    44  		Description:   "toggle interactive prompting in the terminal",
    45  		DefaultValue:  "enabled",
    46  		AllowedValues: []string{"enabled", "disabled"},
    47  	},
    48  	{
    49  		Key:          "pager",
    50  		Description:  "the terminal pager program to send standard output to",
    51  		DefaultValue: "",
    52  	},
    53  }
    54  
    55  func ConfigOptions() []ConfigOption {
    56  	return configOptions
    57  }
    58  
    59  func ValidateKey(key string) error {
    60  	for _, configKey := range configOptions {
    61  		if key == configKey.Key {
    62  			return nil
    63  		}
    64  	}
    65  
    66  	return fmt.Errorf("invalid key")
    67  }
    68  
    69  type InvalidValueError struct {
    70  	ValidValues []string
    71  }
    72  
    73  func (e InvalidValueError) Error() string {
    74  	return "invalid value"
    75  }
    76  
    77  func ValidateValue(key, value string) error {
    78  	var validValues []string
    79  
    80  	for _, v := range configOptions {
    81  		if v.Key == key {
    82  			validValues = v.AllowedValues
    83  			break
    84  		}
    85  	}
    86  
    87  	if validValues == nil {
    88  		return nil
    89  	}
    90  
    91  	for _, v := range validValues {
    92  		if v == value {
    93  			return nil
    94  		}
    95  	}
    96  
    97  	return &InvalidValueError{ValidValues: validValues}
    98  }
    99  
   100  func NewConfig(root *yaml.Node) Config {
   101  	return &fileConfig{
   102  		ConfigMap:    ConfigMap{Root: root.Content[0]},
   103  		documentRoot: root,
   104  	}
   105  }
   106  
   107  // NewFromString initializes a Config from a yaml string
   108  func NewFromString(str string) Config {
   109  	root, err := parseConfigData([]byte(str))
   110  	if err != nil {
   111  		panic(err)
   112  	}
   113  	return NewConfig(root)
   114  }
   115  
   116  // NewBlankConfig initializes a config file pre-populated with comments and default values
   117  func NewBlankConfig() Config {
   118  	return NewConfig(NewBlankRoot())
   119  }
   120  
   121  func NewBlankRoot() *yaml.Node {
   122  	return &yaml.Node{
   123  		Kind: yaml.DocumentNode,
   124  		Content: []*yaml.Node{
   125  			{
   126  				Kind: yaml.MappingNode,
   127  				Content: []*yaml.Node{
   128  					{
   129  						HeadComment: "What protocol to use when performing git operations. Supported values: ssh, https",
   130  						Kind:        yaml.ScalarNode,
   131  						Value:       "git_protocol",
   132  					},
   133  					{
   134  						Kind:  yaml.ScalarNode,
   135  						Value: "https",
   136  					},
   137  					{
   138  						HeadComment: "What editor gh should run when creating issues, pull requests, etc. If blank, will refer to environment.",
   139  						Kind:        yaml.ScalarNode,
   140  						Value:       "editor",
   141  					},
   142  					{
   143  						Kind:  yaml.ScalarNode,
   144  						Value: "",
   145  					},
   146  					{
   147  						HeadComment: "When to interactively prompt. This is a global config that cannot be overridden by hostname. Supported values: enabled, disabled",
   148  						Kind:        yaml.ScalarNode,
   149  						Value:       "prompt",
   150  					},
   151  					{
   152  						Kind:  yaml.ScalarNode,
   153  						Value: "enabled",
   154  					},
   155  					{
   156  						HeadComment: "A pager program to send command output to, e.g. \"less\". Set the value to \"cat\" to disable the pager.",
   157  						Kind:        yaml.ScalarNode,
   158  						Value:       "pager",
   159  					},
   160  					{
   161  						Kind:  yaml.ScalarNode,
   162  						Value: "",
   163  					},
   164  					{
   165  						HeadComment: "Aliases allow you to create nicknames for gh commands",
   166  						Kind:        yaml.ScalarNode,
   167  						Value:       "aliases",
   168  					},
   169  					{
   170  						Kind: yaml.MappingNode,
   171  						Content: []*yaml.Node{
   172  							{
   173  								Kind:  yaml.ScalarNode,
   174  								Value: "co",
   175  							},
   176  							{
   177  								Kind:  yaml.ScalarNode,
   178  								Value: "pr checkout",
   179  							},
   180  						},
   181  					},
   182  				},
   183  			},
   184  		},
   185  	}
   186  }