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 }