@@ -86,7 +86,9 @@ defmodule OptionParser do
86
86
87
87
"""
88
88
def parse ( argv , opts \\ [ ] ) when is_list ( argv ) and is_list ( opts ) do
89
- config = compile_config ( opts , all: true )
89
+ config =
90
+ Keyword . merge ( opts , [ all: true , strict: false ] )
91
+ |> compile_config ( )
90
92
do_parse ( argv , config , [ ] , [ ] , [ ] )
91
93
end
92
94
@@ -106,7 +108,9 @@ defmodule OptionParser do
106
108
107
109
"""
108
110
def parse_head ( argv , opts \\ [ ] ) when is_list ( argv ) and is_list ( opts ) do
109
- config = compile_config ( opts , all: false )
111
+ config =
112
+ Keyword . merge ( opts , [ all: false , strict: false ] )
113
+ |> compile_config ( )
110
114
do_parse ( argv , config , [ ] , [ ] , [ ] )
111
115
end
112
116
@@ -115,21 +119,21 @@ defmodule OptionParser do
115
119
{ Enum . reverse ( opts ) , Enum . reverse ( args ) , Enum . reverse ( invalid ) }
116
120
end
117
121
118
- defp do_parse ( argv , { aliases , switches , all } = config , opts , args , invalid ) do
119
- case next ( argv , aliases , switches ) do
122
+ defp do_parse ( argv , { aliases , switches , strict , all } = config , opts , args , invalid ) do
123
+ case next ( argv , aliases , switches , strict ) do
120
124
{ :ok , option , value , rest } ->
121
125
# the option exist and it was successfully parsed
122
126
kinds = List . wrap Keyword . get ( switches , option )
123
127
new_opts = do_store_option ( opts , option , value , kinds )
124
128
do_parse ( rest , config , new_opts , args , invalid )
125
129
126
- { :error , option , value , rest } ->
130
+ { :error , { :value , option , value } , rest } ->
127
131
# the option exist but it has wrong value
128
132
do_parse ( rest , config , opts , args , [ { option , value } | invalid ] )
129
133
130
- { :error , option , rest } ->
134
+ { :error , { :undefined , option , value } , rest } ->
131
135
# the option does not exist (for strict cases)
132
- do_parse ( rest , config , opts , args , [ { option , nil } | invalid ] )
136
+ do_parse ( rest , config , opts , args , [ { option , value } | invalid ] )
133
137
134
138
{ :error , [ "--" | rest ] } ->
135
139
{ Enum . reverse ( opts ) , Enum . reverse ( args , rest ) , Enum . reverse ( invalid ) }
@@ -149,44 +153,47 @@ defmodule OptionParser do
149
153
Low-level function that parses one option.
150
154
"""
151
155
def next ( argv , opts \\ [ ] ) when is_list ( argv ) and is_list ( opts ) do
152
- { aliases , switches , _ } = compile_config ( opts , false )
153
- next ( argv , aliases , switches )
156
+ { aliases , switches , strict , _ } = compile_config ( opts )
157
+ next ( argv , aliases , switches , strict )
154
158
end
155
159
156
- defp next ( [ ] , _aliases , _switches ) do
160
+ defp next ( [ ] , _aliases , _switches , _strict ) do
157
161
{ :error , [ ] }
158
162
end
159
163
160
- defp next ( [ "--" | _ ] = argv , _aliases , _switches ) do
164
+ defp next ( [ "--" | _ ] = argv , _aliases , _switches , _strict ) do
161
165
{ :error , argv }
162
166
end
163
167
164
- defp next ( [ "-" <> option | rest ] , aliases , switches ) do
168
+ defp next ( [ "-" <> option | rest ] , aliases , switches , strict ) do
165
169
{ option , value } = split_option ( option )
166
- { option , kinds , value } = normalize_option ( option , value , switches , aliases )
167
-
168
- #FIXME: don't modify rest for unknown options in strict mode
169
- { value , kinds , rest } = normalize_value ( value , kinds , rest )
170
+ opt = tag_option ( option , switches , aliases )
170
171
171
- case validate_option ( option , value , kinds ) do
172
- { :ok , new_value } ->
173
- { :ok , option , new_value , rest }
174
-
175
- :invalid ->
176
- { :error , option , value , rest }
172
+ if strict and not option_defined? ( opt , switches ) do
173
+ { _ , opt_name } = opt
174
+ { :error , { :undefined , opt_name , value } , rest }
175
+ else
176
+ { opt_name , kinds , value } = normalize_option ( opt , value , switches )
177
+ { value , kinds , rest } = normalize_value ( value , kinds , rest )
178
+ case validate_option ( opt_name , value , kinds ) do
179
+ { :ok , new_value } -> { :ok , opt_name , new_value , rest }
180
+ :invalid -> { :error , { :value , opt_name , value } , rest }
181
+ end
177
182
end
178
183
end
179
184
180
- defp next ( argv , _aliases , _switches ) do
185
+ defp next ( argv , _aliases , _switches , _strict ) do
181
186
{ :error , argv }
182
187
end
183
188
184
189
## Helpers
185
190
186
- defp compile_config ( opts , all: flag ) do
191
+ defp compile_config ( opts ) do
187
192
aliases = opts [ :aliases ] || [ ]
188
193
switches = opts [ :switches ] || [ ]
189
- { aliases , switches , flag }
194
+ strict = opts [ :strict ] || false
195
+ all = opts [ :all ] || false
196
+ { aliases , switches , strict , all }
190
197
end
191
198
192
199
defp validate_option ( option , value , kinds ) do
@@ -229,19 +236,35 @@ defmodule OptionParser do
229
236
end
230
237
end
231
238
232
- defp normalize_option ( << ?- , option :: binary >> , value , switches , _aliases ) do
233
- normalize_option ( get_negated ( option , switches ) , value , switches )
239
+ defp tag_option ( << ?- , option :: binary >> , switches , _aliases ) do
240
+ get_negated ( option , switches )
234
241
end
235
242
236
- defp normalize_option ( option , value , switches , aliases ) do
237
- option = get_option ( option )
238
- if alias = aliases [ option ] do
239
- normalize_option ( { :default , alias } , value , switches )
243
+ defp tag_option ( option , _switches , aliases ) when is_binary ( option ) do
244
+ opt = get_option ( option )
245
+ if alias = aliases [ opt ] do
246
+ { :default , alias }
240
247
else
241
- { option , [ :invalid ] , value }
248
+ { :unknown , opt }
242
249
end
243
250
end
244
251
252
+ defp option_defined? ( { :unknown , _option } , _switches ) do
253
+ false
254
+ end
255
+
256
+ defp option_defined? ( { :negated , option } , switches ) do
257
+ Keyword . has_key? ( switches , option )
258
+ end
259
+
260
+ defp option_defined? ( { :default , option } , switches ) do
261
+ Keyword . has_key? ( switches , option )
262
+ end
263
+
264
+ defp normalize_option ( { :unknown , option } , value , _switches ) do
265
+ { option , [ :invalid ] , value }
266
+ end
267
+
245
268
defp normalize_option ( { :negated , option } , nil , switches ) do
246
269
kinds = List . wrap ( switches [ option ] )
247
270
0 commit comments