Expand description
§Introduction
This library crate implements a Posix getopt-like command-line
option parser with simple programming interface. More specifically
the parser is like getopt’s GNU extension called getopt_long
which is familiar command-line option format for users of
Linux-based operating systems.
The name is just_getopt because this is just a getopt parser and
(almost) nothing more. The intent is to provide the parsed output
and basic methods for examining the output. There will not be
anything for interpreting the output or for printing messages to
program’s user. The responsibility of interpretation is left to your
program.
In getopt logic there are two types of command-line options:
- short options with a single letter name (
-f) - long options with more than one letter as their name (
--file).
Both option types may accept an optional value or they may require a value. Values are given after the option. See the section Parsing Rules below for more information.
Programming examples are in the Examples section below and in the source code repository’s “examples” directory.
§Parsing Rules
By default, all options are expected to come first in the command
line. Other arguments (non-options) come after options. Therefore
the first argument that does not look like an option stops option
parsing and the rest of the command line is parsed as non-options.
This default can be changed, so that options and non-options can be
mixed in their order in the command line. See OptSpecs::flag
method for more information.
In command line the “pseudo option” -- (two dashes) always stops
the option parser. Then the rest of the command line is parsed as
regular arguments (non-options).
§Short Options
Short options in the command line start with the - character which
is followed by option’s name character (-c), usually a letter.
If option requires a value the value must be entered either directly
after the option character (-cVALUE) or as the next command-line
argument (-c VALUE). In the latter case anything that follows -c
will be parsed as option’s value.
If option accepts an optional value the value must always be entered
directly after the option character (-cVALUE). Otherwise there is
no value for this option.
Several short options can be entered together after one -
character (-abc) but then only the last option in the series may
have required or optional value.
§Long Options
Long options start with -- characters and the option name comes
directly after it (--foo). The name must be at least two
characters long.
If option requires a value the value must be entered either directly
after the option name and = character (--foo=VALUE) or as the
next command-line argument (--foo VALUE). In the latter case
anything that follows --foo will be parsed as option’s value.
If option accepts an optional value the value must always be entered
directly after the option name and = character (--foo=VALUE).
Otherwise there is no value for this option.
Option --foo= is valid format when the option requires a value or
accepts an optional value. It means that the value is empty string.
It is not valid format when the option does not accept a value.
§Examples
Following examples will guide through a typical use of this library crate and command-line parsing.
§Prepare
First we bring some important paths into the scope of our program.
use just_getopt::{OptFlags, OptSpecs, OptValue};Then we define which command-line options are valid for the program.
We do this by creating an instance of OptSpecs struct by calling
function OptSpecs::new. Then we modify the struct instance with
option and flag methods.
let specs = OptSpecs::new()
.option("help", "h", OptValue::None) // Arguments: (id, name, value_type)
.option("help", "help", OptValue::None)
.option("file", "f", OptValue::RequiredNonEmpty)
.option("file", "file", OptValue::RequiredNonEmpty)
.option("verbose", "v", OptValue::OptionalNonEmpty)
.option("verbose", "verbose", OptValue::OptionalNonEmpty)
.flag(OptFlags::OptionsEverywhere);Each option method above adds a single option
information to the option specification. Method’s arguments are:
-
id: Programmer’s identifier string for the option. The same identifier is used later to check if this particular option was present in the command line. Several options may have the sameid. This makes sense when short option and long option have the same meaning, like-hand--helpfor printing help. -
name: Option’s name string in the command line, without prefix. A single-character name (likeh) defines a short option which is entered like-hin the command line. Longer name defines a long option which is entered like--helpin the command line. -
value_type: Whether or not this option accepts a value and if the value is optional or required. The argument is a variant of enumOptValue.
The flag method above adds a configuration flag
for the command-line parser. It is a variant of enum OptFlags.
This variant OptionsEverywhere
changes the command-line parser to accept options and other
arguments in mixed order in the command line. That is, options can
come after non-option arguments.
For better explanation see the documentation of OptSpecs struct
and its methods option and
flag. Also see methods
limit_options,
limit_other_args and
limit_unknown_options.
§Parse the Command Line
We are ready to parse program’s command-line arguments. We do this
with OptSpecs::getopt method. Arguments we get from
std::env::args function which returns an iterator.
// Get arguments iterator from operating system and skip the first item
let args = std::env::args().skip(1); // which is this program's file path.
let parsed = specs.getopt(args); // Getopt! Use the "specs" variable defined above.If you want to try getopt method without
program’s real command-line arguments you can also run it with other
iterator argument or with a vector or an array as an argument. Like
this:
let parsed = specs.getopt(["--file=123", "-f456", "foo", "-av", "bar"]);§Examine the Parsed Output
The command line is now parsed and the variable parsed (see above)
owns an Args struct which represents the parsed output in
organized form. It is a public struct and it can be examined
manually. There are some methods for convenience, and some of them
are shown in the following examples.
At this stage it is useful to see the returned Args struct. One
of its fields may contain some Opt structs too if the parser
found valid command-line options. Let’s print it:
eprintln!("{:#?}", parsed);That could print something like this:
Args {
options: [
Opt {
id: "file",
name: "file",
value_required: true,
value: Some(
"123",
),
},
Opt {
id: "file",
name: "f",
value_required: true,
value: Some(
"456",
),
},
Opt {
id: "verbose",
name: "v",
value_required: false,
value: None,
},
],
other: [
"foo",
"bar",
],
unknown: [
"a",
],
}§Check for Bad Options
Usually we want to check if there were bad options, and if so, exit the program with friendly help messages. We create a flag variable to hold the condition if we need to exit.
let mut error_exit = false;Print error messages about possible unknown options.
for u in &parsed.unknown {
eprintln!("Unknown option: {u}");
error_exit = true;
}Print error message about possible missing values for options which require a value.
for o in parsed.required_value_missing() {
eprintln!("Value is required for option '{}'.", o.name);
error_exit = true;
}Exit the program if there were bad options (see above).
if error_exit {
eprintln!("Use '-h' for help.");
std::process::exit(1);
}§Print Help Message
Command-line programs always have -h or --help option for
printing a friendly help message. The following example shows how to
detect that option.
if parsed.option_exists("help") {
println!("Print friendly help about program's usage.");
std::process::exit(0);
}The "help" string in the first line above is the identifier string
(id) for the option. It was defined with OptSpecs::option
method in the example code earlier. Identifier strings are used to
find if a specific option was given in the command line.
§Collect Values and Other Arguments
The rest depends very much on individual program’s needs. Probably
often we would collect what values were given to options. In our
example program there are -f and --file options that require a
value. We could collect all those values next.
for f in parsed.options_value_all("file") {
println!("File name: {:?}", f);
}Notice if -v or --verbose was given, even without a value. Then
collect all (optional) values for the option.
if parsed.option_exists("verbose") {
println!("Option 'verbose' was given.");
for v in parsed.options_value_all("verbose") {
println!("Verbose level: {:?}", v);
}
}Finally, our example program will handle all other arguments, that is, non-option arguments.
for o in &parsed.other {
println!("Other argument: {:?}", o);
}§More Help
A complete working example code – very similar to previous examples
– is in the source code repository’s “examples” directory. It can
be run with command cargo run --example basic -- your arguments.
Try it with different command-line arguments.
Further reading:
Structs§
- Args
- Parsed command line in organized form.
- Opt
- Structured option information.
- OptSpecs
- Specification for program’s valid command-line options.