1// Copyright (c) Microsoft Corporation. All rights reserved. 2// Licensed under the MIT License. See License.txt in the project root for license information. 3 4package model 5 6import ( 7 "fmt" 8 "regexp" 9 "strings" 10) 11 12// OptionType describes the type of the option, possible values are 'Argument', 'Flag' or 'KeyValue' 13type OptionType string 14 15const ( 16 // Argument ... 17 Argument OptionType = "Argument" 18 // Flag ... 19 Flag OptionType = "Flag" 20 // KeyValue ... 21 KeyValue OptionType = "KeyValue" 22) 23 24// Option describes an option of a autorest command line 25type Option interface { 26 // Type returns the type of this option 27 Type() OptionType 28 // Format returns the actual option in string 29 Format() string 30} 31 32// ArgumentOption is an option not starting with '--' or '-' 33type ArgumentOption interface { 34 Option 35 Argument() string 36} 37 38// FlagOption is an option that starts with '--' but do not have a value 39type FlagOption interface { 40 Option 41 Flag() string 42} 43 44// KeyValueOption is an option that starts with '--' and have a value 45type KeyValueOption interface { 46 Option 47 Key() string 48 Value() string 49} 50 51// NewOption returns an Option from a formatted string. We should hold this result using this function: input == result.Format() 52func NewOption(input string) (Option, error) { 53 if strings.HasPrefix(input, "--") { 54 // this option is either a flag or a key value pair option 55 return parseFlagOrKeyValuePair(strings.TrimPrefix(input, "--")) 56 } 57 // this should be an argument 58 return argument{value: input}, nil 59} 60 61var flagRegex = regexp.MustCompile(`^[a-zA-Z]`) 62 63func parseFlagOrKeyValuePair(input string) (Option, error) { 64 if !flagRegex.MatchString(input) { 65 return nil, fmt.Errorf("cannot parse flag '%s', a flag or option should only start with letters", input) 66 } 67 segments := strings.Split(input, "=") 68 if len(segments) <= 1 { 69 // this should be a flag 70 return flagOption{value: input}, nil 71 } 72 return keyValueOption{ 73 key: segments[0], 74 value: strings.Join(segments[1:], "="), 75 }, nil 76} 77 78type argument struct { 79 value string 80} 81 82func (f argument) Type() OptionType { 83 return Argument 84} 85 86// Format ... 87func (f argument) Format() string { 88 return f.value 89} 90 91func (f argument) Argument() string { 92 return f.value 93} 94 95func (f argument) String() string { 96 return f.Format() 97} 98 99var _ ArgumentOption = (*argument)(nil) 100 101type flagOption struct { 102 value string 103} 104 105func (f flagOption) Type() OptionType { 106 return Flag 107} 108 109// Format ... 110func (f flagOption) Format() string { 111 return fmt.Sprintf("--%s", f.value) 112} 113 114func (f flagOption) String() string { 115 return f.Format() 116} 117 118func (f flagOption) Flag() string { 119 return f.value 120} 121 122var _ FlagOption = (*flagOption)(nil) 123 124type keyValueOption struct { 125 key string 126 value string 127} 128 129func (f keyValueOption) Type() OptionType { 130 return KeyValue 131} 132 133// Format ... 134func (f keyValueOption) Format() string { 135 return fmt.Sprintf("--%s=%s", f.key, f.value) 136} 137 138func (f keyValueOption) String() string { 139 return f.Format() 140} 141 142func (f keyValueOption) Key() string { 143 return f.key 144} 145 146func (f keyValueOption) Value() string { 147 return f.value 148} 149 150var _ KeyValueOption = (*keyValueOption)(nil) 151 152// NewArgument returns a new argument option (without "--") 153func NewArgument(value string) Option { 154 return argument{ 155 value: value, 156 } 157} 158 159// NewFlagOption returns a flag option (with "--", without value) 160func NewFlagOption(flag string) Option { 161 return flagOption{ 162 value: flag, 163 } 164} 165 166// NewKeyValueOption returns a key-value option like "--tag=something" 167func NewKeyValueOption(key, value string) Option { 168 return keyValueOption{ 169 key: key, 170 value: value, 171 } 172} 173