Skip to content

Commit d149c4c

Browse files
committed
Polish and fix docs for OptionParser (#4924)
I also * fixed some style in just a couple of lines of code * renamed a couple of variables for clarity Signed-off-by: Andrea Leopardi <[email protected]>
1 parent 58810bd commit d149c4c

File tree

1 file changed

+97
-72
lines changed

1 file changed

+97
-72
lines changed

lib/elixir/lib/option_parser.ex

Lines changed: 97 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,24 @@ defmodule OptionParser do
1515
@doc """
1616
Parses `argv` into a keywords list.
1717
18-
It returns a three-element tuple as follows:
18+
It returns a three-element tuple with the form `{parsed, args, invalid}`, where:
1919
20-
1. parsed switches,
21-
2. remaining arguments,
22-
3. invalid options.
20+
* `parsed` is a keyword list of parsed switches with `{switch_name, value}`
21+
tuples in it; `switch_name` is the atom representing the switch name while
22+
`value` is the value for that switch parsed according to `opts` (see the
23+
"Examples" section for more information)
24+
* `args` is a list of the remaining arguments in `argv` as strings
25+
* `invalid` is a list of invalid options as `{option_name, value}` where
26+
`option_name` is the raw option and `value` is `nil` if the option wasn't
27+
expected or the string value if the value didn't have the expected type for
28+
the corresponding option
2329
24-
## Examples
30+
Elixir converts switches to underscored atoms, so `--source-path` becomes
31+
`:source_path`. This is done to better suit Elixir conventions. However, this
32+
means that switches can't contain underscores and switches that do contain
33+
underscores are always returned in the list of invalid options.
34+
35+
Without any options, this function will try to parse all switches in the `argv`.
2536
2637
iex> OptionParser.parse(["--debug"])
2738
{[debug: true], [], []}
@@ -32,65 +43,85 @@ defmodule OptionParser do
3243
iex> OptionParser.parse(["--source-path", "lib", "test/enum_test.exs", "--verbose"])
3344
{[source_path: "lib", verbose: true], ["test/enum_test.exs"], []}
3445
35-
By default, Elixir will try to automatically parse all switches.
3646
Switches followed by a value will be assigned the value, as a string.
37-
Switches without an argument, like `--debug` will automatically
38-
be set to `true`.
47+
Switches without an argument, like `--debug` in the examples above, will
48+
automatically be set to `true`.
49+
50+
## Options
3951
40-
Note: Elixir also converts the switches to underscore atoms, so
41-
`--source-path` becomes `:source_path`, to better suit Elixir
42-
conventions. This means that option names on the command line cannot
43-
contain underscores; such options will be put in the invalid options
44-
list.
52+
The following options are supported:
4553
46-
## Switch Definitions
54+
* `:switches` or `:strict` - see the "Switch definitions" section below
55+
* `:aliases` - see the "Aliases" section below
56+
57+
## Switch definitions
4758
4859
Often it is better to explicitly list the known
49-
switches and their formats. The switches can be specified via two
50-
alternative options:
60+
switches and their formats. The switches can be specified via one of two
61+
options:
5162
52-
* `:switches` - defines some switches. An attempt is still made to parse
53-
switches that do not appear in the list.
63+
* `:switches` - defines some switches and their types. This function
64+
still attempts to parse switches that are not in this list.
65+
* `:strict` - defines strict switches. Any switch in `argv` that is not
66+
specified in the list is returned in the invalid options list.
5467
55-
* `:strict` - the switches are strict. Any switch that is not specified
56-
in the list is returned in the invalid options list.
68+
Both these options accept a keyword list of `{name, type}` tuples where `name`
69+
is an atom defining the name of the switch and `type` is an atom that
70+
specifies the type for the value of this switch (see the "Types" section below
71+
for the possible types and more information about type casting).
5772
5873
Note that you should only supply the `:switches` or `:strict` option.
59-
If you supply both, an error will be raised.
74+
If you supply both, an `ArgumentError` exception will be raised.
6075
6176
### Types
6277
63-
Option parser switches may take 0 or 1 argument.
78+
Switches parsed by `OptionParser` may take zero or one arguments.
6479
65-
The following switches take no argument:
80+
The following switches types take no arguments:
6681
67-
* `:boolean` - sets the value to true when given
68-
* `:count` - counts the number of times the switch is given
82+
* `:boolean` - sets the value to `true` when given (see also the
83+
"Negation switches" section below)
84+
* `:count` - counts the number of times the switch is given
6985
70-
The following switches take 1 argument:
86+
The following switches take one argument:
7187
72-
* `:integer` - parses the upcoming value as an integer.
73-
* `:float` - parses the upcoming value as a float.
74-
* `:string` - parses the upcoming value as a string.
88+
* `:integer` - parses the value as an integer
89+
* `:float` - parses the value as a float
90+
* `:string` - parses the value as a string
7591
76-
If a switch can't be parsed, it is returned in the invalid
77-
options list.
92+
If a switch can't be parsed according to the given type, it is returned
93+
in the invalid options list.
7894
7995
### Modifiers
8096
8197
Switches can be specified with modifiers, which change how
8298
they behave. The following modifiers are supported:
8399
84-
* `:keep` - keeps duplicated items instead of overriding them.
85-
Works with all types except `:count`.
100+
* `:keep` - keeps duplicated items instead of overriding them; works with
101+
all types except `:count`. Specifying `switch_name: :keep` assumes the
102+
type of `:switch_name` will be `:string`.
86103
87-
Note: if you want to use `:keep` with a non-string type, use a list, e.g.
88-
`[foo: [:integer, :keep]]`.
104+
Note that if you want to use `:keep` with a type other than `:string`, use a list
105+
as the type for the switch. For example: `[foo: [:integer, :keep]]`.
89106
90-
### Examples
107+
### Negation switches
108+
109+
In case a switch `SWITCH` is specified to have type `:boolean`, it may be
110+
passed as `--no-SWITCH` as well which will set the option to `false`:
111+
112+
iex> OptionParser.parse(["--no-op", "path/to/file"], switches: [op: :boolean])
113+
{[op: false], ["path/to/file"], []}
114+
115+
## Aliases
116+
117+
A set of aliases can be specified in the `:aliases` option:
118+
119+
iex> OptionParser.parse(["-d"], aliases: [d: :debug])
120+
{[debug: true], [], []}
121+
122+
## Examples
91123
92-
Here are some examples of option parser working with different types
93-
and modifiers:
124+
Here are some examples of working with different types and modifiers:
94125
95126
iex> OptionParser.parse(["--unlock", "path/to/file"], strict: [unlock: :boolean])
96127
{[unlock: true], ["path/to/file"], []}
@@ -121,21 +152,6 @@ defmodule OptionParser do
121152
iex> OptionParser.parse(["--unlock", "path/to/file", "--unlock", "path/to/another/file"], strict: [unlock: :keep])
122153
{[unlock: "path/to/file", unlock: "path/to/another/file"], [], []}
123154
124-
### Negation switches
125-
126-
In case a switch is declared as boolean, it may be passed as `--no-SWITCH`
127-
which will set the option to `false`:
128-
129-
iex> OptionParser.parse(["--no-op", "path/to/file"], switches: [op: :boolean])
130-
{[op: false], ["path/to/file"], []}
131-
132-
## Aliases
133-
134-
A set of aliases can be given as options too:
135-
136-
iex> OptionParser.parse(["-d"], aliases: [d: :debug])
137-
{[debug: true], [], []}
138-
139155
"""
140156
@spec parse(argv, options) :: {parsed, argv, errors}
141157
def parse(argv, opts \\ []) when is_list(argv) and is_list(opts) do
@@ -146,14 +162,16 @@ defmodule OptionParser do
146162
The same as `parse/2` but raises an `OptionParser.ParseError`
147163
exception if any invalid options are given.
148164
149-
If there weren't any errors, returns a three-element tuple as follows:
165+
If there are no errors, returns a `{parsed, rest}` tuple where:
150166
151-
1. parsed options,
152-
2. remaining arguments,
153-
3. empty list.
167+
* `parsed` is the list of parsed switches (same as in `parse/2`)
168+
* `rest` is the list of arguments (same as in `parse/2`)
154169
155170
## Examples
156171
172+
iex> OptionParser.parse!(["--debug", "path/to/file"], strict: [debug: :boolean])
173+
{[debug: true], ["path/to/file"]}
174+
157175
iex> OptionParser.parse!(["--limit", "xyz"], strict: [limit: :integer])
158176
** (OptionParser.ParseError) 1 error found!
159177
--limit : Expected type integer, got "xyz"
@@ -172,7 +190,7 @@ defmodule OptionParser do
172190
@spec parse!(argv, options) :: {parsed, argv} | no_return
173191
def parse!(argv, opts \\ []) when is_list(argv) and is_list(opts) do
174192
case parse(argv, opts) do
175-
{parsed, argv, []} -> {parsed, argv}
193+
{parsed, args, []} -> {parsed, args}
176194
{_, _, errors} -> raise ParseError, format_errors(errors, opts)
177195
end
178196
end
@@ -201,14 +219,16 @@ defmodule OptionParser do
201219
The same as `parse_head/2` but raises an `OptionParser.ParseError`
202220
exception if any invalid options are given.
203221
204-
If there weren't any errors, returns a three-element tuple as follows:
222+
If there are no errors, returns a `{parsed, rest}` tuple where:
205223
206-
1. parsed options,
207-
2. remaining arguments,
208-
3. empty list.
224+
* `parsed` is the list of parsed switches (same as in `parse_head/2`)
225+
* `rest` is the list of arguments (same as in `parse_head/2`)
209226
210227
## Examples
211228
229+
iex> OptionParser.parse_head!(["--source", "lib", "path/to/file", "--verbose"])
230+
{[source: "lib"], ["path/to/file", "--verbose"]}
231+
212232
iex> OptionParser.parse_head!(["--number", "lib", "test/enum_test.exs", "--verbose"], strict: [number: :integer])
213233
** (OptionParser.ParseError) 1 error found!
214234
--number : Expected type integer, got "lib"
@@ -222,7 +242,7 @@ defmodule OptionParser do
222242
@spec parse_head!(argv, options) :: {parsed, argv, errors} | no_return
223243
def parse_head!(argv, opts \\ []) when is_list(argv) and is_list(opts) do
224244
case parse_head(argv, opts) do
225-
{parsed, argv, []} -> {parsed, argv}
245+
{parsed, args, []} -> {parsed, args}
226246
{_, _, errors} -> raise ParseError, format_errors(errors, opts)
227247
end
228248
end
@@ -250,7 +270,7 @@ defmodule OptionParser do
250270
{:error, ["--" | rest]} ->
251271
{Enum.reverse(opts), Enum.reverse(args, rest), Enum.reverse(invalid)}
252272

253-
{:error, [arg | rest]=remaining_args} ->
273+
{:error, [arg | rest] = remaining_args} ->
254274
# there is no option
255275
if all? do
256276
do_parse(rest, config, opts, [arg | args], invalid, all?)
@@ -264,20 +284,20 @@ defmodule OptionParser do
264284
Low-level function that parses one option.
265285
266286
It accepts the same options as `parse/2` and `parse_head/2`
267-
as both functions are built on top of next. This function
287+
as both functions are built on top of this function. This function
268288
may return:
269289
270290
* `{:ok, key, value, rest}` - the option `key` with `value` was
271291
successfully parsed
272292
273293
* `{:invalid, key, value, rest}` - the option `key` is invalid with `value`
274-
(returned when the switch type does not match the one given via the
275-
command line)
294+
(returned when the value cannot be parsed according to the switch type)
276295
277296
* `{:undefined, key, value, rest}` - the option `key` is undefined
278297
(returned in strict mode when the switch is unknown)
279298
280-
* `{:error, rest}` - there are no switches at the top of the given argv
299+
* `{:error, rest}` - there are no switches at the head of the given `argv`
300+
281301
"""
282302

283303
@spec next(argv, options) ::
@@ -295,15 +315,15 @@ defmodule OptionParser do
295315
{:error, []}
296316
end
297317

298-
defp next(["--" | _]=argv, _aliases, _switches, _strict) do
318+
defp next(["--" | _] = argv, _aliases, _switches, _strict) do
299319
{:error, argv}
300320
end
301321

302-
defp next(["-" | _]=argv, _aliases, _switches, _strict) do
322+
defp next(["-" | _] = argv, _aliases, _switches, _strict) do
303323
{:error, argv}
304324
end
305325

306-
defp next(["- " <> _ | _]=argv, _aliases, _switches, _strict) do
326+
defp next(["- " <> _ | _] = argv, _aliases, _switches, _strict) do
307327
{:error, argv}
308328
end
309329

@@ -334,8 +354,9 @@ defmodule OptionParser do
334354
@doc """
335355
Receives a key-value enumerable and converts it to argv.
336356
337-
Keys must be atoms. Keys with nil value are discarded,
357+
Keys must be atoms. Keys with `nil` value are discarded,
338358
boolean values are converted to `--key` or `--no-key`
359+
(if the value is `true` or `false`, respectively),
339360
and all other values are converted using `to_string/1`.
340361
341362
## Examples
@@ -364,13 +385,17 @@ defmodule OptionParser do
364385
@doc ~S"""
365386
Splits a string into argv chunks.
366387
388+
This function splits the given `string` into a list of strings in a similar
389+
way to many shells.
390+
367391
## Examples
368392
369393
iex> OptionParser.split("foo bar")
370394
["foo", "bar"]
371395
372396
iex> OptionParser.split("foo \"bar baz\"")
373397
["foo", "bar baz"]
398+
374399
"""
375400
@spec split(String.t) :: argv
376401
def split(string) do

0 commit comments

Comments
 (0)