Expand description
§Immediate Arguments
No-hassle, on-the-spot, command line argument parser
Highlights:
- Straightforward declaration of arguments with proc-macro.
- Supports POSIX / GNU argument syntax conventions.
- Supports arguments of any type that implements
FromStr+Debug. - Supports (sub)commands, with aliases.
- Supports declaration of conflicting arguments.
- Supports automatic
--versionand--helphandling, with possibility to opt-out. - Tested on Linux, macOS and Windows.
- No run-time dependencies.
§Basic Example
This exanple is using immargs_from_env! for on-the-spot declaration and parsing of
command line arguments.
use immargs::immargs_from_env;
let args = immargs_from_env! {
--force "overwrite destination",
-l --log <level> u8 "set log level",
-h --help "print help message",
<src>... String "source(s)",
<dest> String "destination",
};
// Assuming this program was executed with "myprog -l 3 Src0 Src1 Dest"
assert!(!args.force);
assert!(args.log == Some(3));
assert!(args.src.len() == 2);
assert!(args.src[0] == "Src0");
assert!(args.src[1] == "Src1");
assert!(args.dest == "Dest");immargs_from_env! returns a struct with fields derived from to the arguments
specification. The fields are populated with the corresponding values from the command
line. For the example above, the returned struct looks like this:
pub struct ImmArgs {
pub force: bool,
pub log: Option<u8>,
pub src: Vec<String>,
pub dest: String,
}A help message will also be derived from the arguments specification, and is printed if the
-h or --help option is used. For the above example, the help message looks like this:
usage: myprog [options] <src>... <dest>
options:
--force overwrite destination
-l, --log <level> set log level
-h, --help print help message
arguments:
<src>... source(s)
<dest> desination
§Advanced Example
This example is using immargs! to declare command line arguments. The main program
takes a command as its last argument, and each (sub)command use immargs! do declare
the arguments they each accept. Any arguments following the command will be returned as
an Args that is part of the command enum, which is converted into the (sub)command
arguments struct using into().
use immargs::immargs;
// The last argument is a command, with available commands (and their aliases) enclosed
// by braces. An `enum`, with variants matching the commands, will be generated.
immargs! {
MainArgs, // Argument struct will be called "MainArgs"
-v --verbose "enable verbose logging", // An option
--version "print version", // --version enables automatic version printing
-h --help "print help message", // --help enables automatic help printing
<command> Command "the command to run" { // Command enum will be named "Command"
add "add file(s)", // "add" has no aliases
remove rm "remove file(s)", // "rm" is an alias for "remove"
commit co c "commit changes", // "co" and "c" are aliases for "commit"
}
}
// The "?" indicates that these are conflicting arguments, i.e. they can't be
// used at the same time, but one of them must be present on the command line.
immargs! {
AddArgs,
-a --all ? "add all files", // Conflicts with [<file>...]
--force "overwrite destination",
-h --help "print help message",
[<file>...] String ? "file(s) to add", // Conflicts with -a, --all
}
immargs! {
RemoveArgs,
-r --recursive "recursively remove files",
-h --help "print help message",
<file>... String "file(s) to remove", // "..." means it's a variadic argument
}
immargs! {
CommitArgs,
-a --amend "amend latest commit",
-h --help "print help message",
[<message>] String "commit message", // "[ ]" means it's an optional argument
}
fn main() {
let main_args = MainArgs::from_env();
let verbose = main_args.verbose;
match main_args.command {
Command::Add(args) => add(verbose, args.into()),
Command::Remove(args) => remove(verbose, args.into()),
Command::Commit(args) => commit(verbose, args.into()),
}
}
fn add(verbose: bool, args: AddArgs) {
// ...
}
fn remove(verbose: bool, args: RemoveArgs) {
// ...
}
fn commit(verbose: bool, args: CommitArgs) {
// ...
}§Additional Examples
Additional examples can be found in examples directory.
§Terminology
Terms and definitions used by immargs (mostly derived from POSIX and GNU definitions):
-
Arguments - The umbrella term for all kinds of strings that appear on the command line. Arguments are further divided into options and non-options.
-
Options - The subset of arguments that start with
-or--, e.g.-vor--verbose. The order in which options appear on the command line carries no meaning, i.e.-a -bhas the same meaning as-b -a. Options are, as the name implies, always optional and never required. Options are further divided into short and long options. -
Short options - The subset of options that start with
-followed by a single character, e.g.-v. -
Long options - The subset of options that start with
--followed by two or more characters, e.g.--verbose. -
Value - An additional piece of information associated with an option, e.g.
--speed 100, where100is the value. Value-less options implicitly hold a binary value (trueorfalse) through their presence or absence on the command line. -
Non-options - The subset of arguments that don’t start with
-or--, e.g.commitorfile.txt. The order in which non-options appear on the command line carries meaning, i.e.commit file.txtdoesn’t have the same meaning asfile.txt commit. Non-optons are further divided into required and optional non-options. -
Required non-option - A non-option that must be present on the command line. In text, required non-options are represented by enclosing
<>, e.g.<file>. -
Optional non-option - A non-options that doesn’t have to be present on the command line. In text, optional non-options are represented by enclosing
[<>], e.g.[<file>]. -
Variadic option - An option that is materialized from multiple separate instances of the option, as opposed to the last instance taking precedence. E.g.
--file hello.txt --file world.txtresults in the option file holding two values,hello.txtandworld.txt. A value-less option can also be variadic, in which case the value held by the option is an unsigned integer representing the number of times the option appeared on the command line. E.g.--verbose --verbose --verboseresults in the option verbose holding the value3. In text, variadic options are represented by trailing..., e.g.--file... <path>or--verbose.... -
Variadic non-option - A non-option that is materialized from multiple separate command line arguments of the same type. In text, variadic non-options are represented by trailing
..., e.g.<file>...or[<file>...].
§Command Line Argument Syntax
The following POSIX / GNU argument syntax conventions are supported:
- Short option,
-followed by a single character, e.g.-f. - Long option,
--followed by two or more characters, e.g.--foo. - Short/Long option with separate value, e.g.
-f 100or--foo 100. - Short/Long option with attached value delimited by
=, e.g.-f=100or--foo=100. - Short option with attached value without delimiter, e.g.
-f100. - Combined short options, e.g.
-abcis equivalent to-a -b -c. - Short/Long options may appear in any order, but must come before any non-option arguments.
- Short/Long options may appear multiple times, the last appearance takes precedence unless
it’s a variadic (repeatable) option, where the number of times the option appears has
meaning, e.g.
-vvvwhere each-vincreases the verbosity level. - The order of non-option arguments carries meaning.
- A standalone
-argument is treated as a non-option argument. - A standalone
--argument marks the end of options. Any following arguments are treated as non-option arguments.
§The Arguments struct
§Field Names
The field names of the struct generated by immargs! are derived as follows.
| Argument Type | Field Name | Example |
|---|---|---|
| Option | Field name is direved from the first long-option (or the first short-option if no long-option exists) | --foo uses field name foo |
| Non-Option | Field name is derived from the non-option name | <bar> T uses field name bar |
Note that the specified option and non-option names must be valid Rust non-keyword identifiers,
as they will become the names of the struct fields. However, the names visible to the user of
the program will be transformed as follows, to allow use of names that aren’t valid Rust struct
field names (keywords, words starting with a number, etc).
- Any starting and trailing
_will be stripped. - Any other
_will be replaced by-. - Letters will be converted to lower case (does not apply to short-options).
Examples:
| Specified Argument | struct Field Name | User Visibale Name |
|---|---|---|
-_1 | _1 | -1 |
--move_ | move_ | --move |
--_1_to_1 | _1_to_1 | --1-to-1 |
--Report_Error | Report_Error | --report-error |
--log <Log_Level> u8 | log | --log <log-level> |
<number_of_items> | number_or_items | <number-of-items> |
[_4th] | _4th | [4th] |
§Field Types
The field types of the struct generated by immargs! are derived as follows.
| Argument Type | Example | Field Type |
|---|---|---|
| Option | --foo | bool |
| Option with Value | --foo <bar> T | Option<T> |
| Variadic Option | --foo... | usize |
| Variadic Option with Value | --foo... <bar> T | Vec<T> |
| Required Non-option | <foo> T | T |
| Optional Non-option | [<foo>] T | Option<T> |
| Required Variadic Non-option | <foo>... T | Vec<T>, with length > 0 |
| Optional Variadic Non-option | [<foo>...] T | Vec<T>, with length >= 0 |
| Required Command | <foo> T { /* commands */ } | T(Args) |
| Optional Command | [<foo>] T { /* commands */ } | Option<T(Args)> |
§Methods
The following methods are available on structs generated by immargs!.
| Method | Return Type |
|---|---|
from_env() | Self |
from<T: IntoIterator<Item: Into<String>>>(args: T) | Self |
try_from_env() | Result<Self> |
try_from<T: IntoIterator<Item: Into<String>>>(args: T) | Result<Self> |
Most applications would want to use from_env(), which uses arguments provided by
std::env::args_os() and on failure prints an error message and terminates the
program with an appropriate exit code.
The other methods exist to allow applications to opt-out of the default behaviours
provided by from_env(), such as explicltly providing the command line arguments to
parse, or to implement custom error and help handling.
§Conflicting Arguments
An argument can be declared to be in conflict with one or more other arguments. This is
useful when two or more arguments are incompatible or otherwise mutually exclusive. A
conflict is declared using an ! or ? optionally followed by a conflict-id. The
conflict-id is an identifier used if there are more than one group of conflicting
options. ! (plain conflict) means that zero or one of the options in the group is
allowed to be present on the command line, while ? (choice) means that exactly one of
the options in the group is must be present on the command line.
Example with one group of conflicting arguments, i.e. without an explicit conflict-id, where exacly one of them must be present on the command line:
use immargs::immargs;
immargs! {
--verbose, // Doesn't conflict with any other argument
--all ?, // Conflicts with [names...]
[<names>...] String ?, // Conflicts with --all
}Example with two groups (B_C and C_D_E) of conflicting arguments, where one argument is
part of both groups. Exactly one of the options in group B_C must be present, and zero or
one of the options in group C_D_E is allowed to be present on the command line.
use immargs::immargs;
immargs! {
--feature_a, // Doesn't conflict with any other argument
--feature_b ?B_C, // Conflicts with --feature-c
--feature_c ?B_C !C_D_E, // Conflicts with --feature-b, --feature-d and --feature-e
--feature_d !C_D_E, // Conflicts with --feature-c and --feature-e
--feature_e !C_D_E, // Conflicts with --feature-c and --feature-d
}§Help and Version
Options with long-option names --help and --version are special. These options are
intercepted during arguments parsing and will not be visible, or have corresponding fields,
in the arguments struct generated by immargs!. When parsing the command line using
from() or from_env(), these options will cause a version or help message to be displayed
and the application will be terminated. When parsing the command line using try_from() or
try_from_env() these options will instead generate a Help or
Version error, which the application can react to, e.g. if the application
wants to display custom version or help messages.
§Unicode
Non-unicode command line arguments will be converted to unicode using
to_string_lossy() before they are parsed.
Macros§
- immargs
- Macro for declaring command line arguments.
- immargs_
from - Convenience macro for on-the-spot command line argument parsing.
- immargs_
from_ env - Convenience macro for on-the-spot command line argument parsing.
- immargs_
try_ from - Convenience macro for on-the-spot command line argument parsing.
- immargs_
try_ from_ env - Convenience macro for on-the-spot command line argument parsing.
Structs§
- Args
- Command line arguments in raw form, i.e. not yet parsed.
Enums§
- Error
- Errors returned by argument parser.
Traits§
Type Aliases§
- Result
- Result returned by argument parser.