github.com/cli/cli@v1.14.1-0.20210902173923-1af6a669e342/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 Key: "http_unix_socket", 55 Description: "the path to a unix socket through which to make HTTP connection", 56 DefaultValue: "", 57 }, 58 { 59 Key: "browser", 60 Description: "the web browser to use for opening URLs", 61 DefaultValue: "", 62 }, 63 } 64 65 func ConfigOptions() []ConfigOption { 66 return configOptions 67 } 68 69 func ValidateKey(key string) error { 70 for _, configKey := range configOptions { 71 if key == configKey.Key { 72 return nil 73 } 74 } 75 76 return fmt.Errorf("invalid key") 77 } 78 79 type InvalidValueError struct { 80 ValidValues []string 81 } 82 83 func (e InvalidValueError) Error() string { 84 return "invalid value" 85 } 86 87 func ValidateValue(key, value string) error { 88 var validValues []string 89 90 for _, v := range configOptions { 91 if v.Key == key { 92 validValues = v.AllowedValues 93 break 94 } 95 } 96 97 if validValues == nil { 98 return nil 99 } 100 101 for _, v := range validValues { 102 if v == value { 103 return nil 104 } 105 } 106 107 return &InvalidValueError{ValidValues: validValues} 108 } 109 110 func NewConfig(root *yaml.Node) Config { 111 return &fileConfig{ 112 ConfigMap: ConfigMap{Root: root.Content[0]}, 113 documentRoot: root, 114 } 115 } 116 117 // NewFromString initializes a Config from a yaml string 118 func NewFromString(str string) Config { 119 root, err := parseConfigData([]byte(str)) 120 if err != nil { 121 panic(err) 122 } 123 return NewConfig(root) 124 } 125 126 // NewBlankConfig initializes a config file pre-populated with comments and default values 127 func NewBlankConfig() Config { 128 return NewConfig(NewBlankRoot()) 129 } 130 131 func NewBlankRoot() *yaml.Node { 132 return &yaml.Node{ 133 Kind: yaml.DocumentNode, 134 Content: []*yaml.Node{ 135 { 136 Kind: yaml.MappingNode, 137 Content: []*yaml.Node{ 138 { 139 HeadComment: "What protocol to use when performing git operations. Supported values: ssh, https", 140 Kind: yaml.ScalarNode, 141 Value: "git_protocol", 142 }, 143 { 144 Kind: yaml.ScalarNode, 145 Value: "https", 146 }, 147 { 148 HeadComment: "What editor gh should run when creating issues, pull requests, etc. If blank, will refer to environment.", 149 Kind: yaml.ScalarNode, 150 Value: "editor", 151 }, 152 { 153 Kind: yaml.ScalarNode, 154 Value: "", 155 }, 156 { 157 HeadComment: "When to interactively prompt. This is a global config that cannot be overridden by hostname. Supported values: enabled, disabled", 158 Kind: yaml.ScalarNode, 159 Value: "prompt", 160 }, 161 { 162 Kind: yaml.ScalarNode, 163 Value: "enabled", 164 }, 165 { 166 HeadComment: "A pager program to send command output to, e.g. \"less\". Set the value to \"cat\" to disable the pager.", 167 Kind: yaml.ScalarNode, 168 Value: "pager", 169 }, 170 { 171 Kind: yaml.ScalarNode, 172 Value: "", 173 }, 174 { 175 HeadComment: "Aliases allow you to create nicknames for gh commands", 176 Kind: yaml.ScalarNode, 177 Value: "aliases", 178 }, 179 { 180 Kind: yaml.MappingNode, 181 Content: []*yaml.Node{ 182 { 183 Kind: yaml.ScalarNode, 184 Value: "co", 185 }, 186 { 187 Kind: yaml.ScalarNode, 188 Value: "pr checkout", 189 }, 190 }, 191 }, 192 { 193 HeadComment: "The path to a unix socket through which send HTTP connections. If blank, HTTP traffic will be handled by net/http.DefaultTransport.", 194 Kind: yaml.ScalarNode, 195 Value: "http_unix_socket", 196 }, 197 { 198 Kind: yaml.ScalarNode, 199 Value: "", 200 }, 201 { 202 HeadComment: "What web browser gh should use when opening URLs. If blank, will refer to environment.", 203 Kind: yaml.ScalarNode, 204 Value: "browser", 205 }, 206 { 207 Kind: yaml.ScalarNode, 208 Value: "", 209 }, 210 }, 211 }, 212 }, 213 } 214 }