args_macro 0.1.0-8.dev args_macro: ^0.1.0-8.dev copied to clipboard
Generates a parser for command-line arguments based on your data class.
Generates a parser for command-line arguments based on your data class, wraps the standard args package.
Usage #
import 'package:args_macro/args_macro.dart';
@Args()
class MyArgs {
final String requiredString;
final String? optionalString;
String stringWithDefault = 'My default string.';
final int requiredInt;
final int? optionalInt;
int intWithDefault = 7;
final double requiredDouble;
final double? optionalDouble;
double doubleWithDefault = 7.77;
bool boolWithDefaultFalse = false;
bool boolWithDefaultTrue = true;
final Fruit requiredEnum;
final Fruit? optionalEnum;
Fruit enumWithDefault = Fruit.mango;
final List<String> stringList;
List<String> stringListWithDefault = ['Huey', 'Dewey', 'Louie'];
final List<int> intList;
List<int> intListWithDefault = [1, 2];
final List<double> doubleList;
List<double> doubleListWithDefault = [1, 2.0];
final List<Fruit> enumList;
List<Fruit> enumListWithDefault = [Fruit.apple, Fruit.banana];
}
enum Fruit { apple, banana, mango, orange }
void main(List<String> argv) {
final parser = MyArgsParser(); // Generated class.
final MyArgs args = parser.parse(argv);
// ...
}
This will create an instance of MyArgs
class filled with parsed data.
Option Types #
Configuration #
- A non-nullable field without an initializer creates a mandatory option.
- A nullable field without an initializer creates an optional option that defaults to
null
. - A field with an initializer creates an optional option with the default value of that initializer. Such a field must not be final or nullable.
Supported types #
String
String options are not interpreted in any way.
@Args()
class MyArgs {
final String requiredString;
final String? optionalString;
String stringWithDefault = 'My default string.';
}
int
An integer is parsed using int.parse(String)
.
This means that the value must contain only digits and optionally dash in the beginning, no decimal point.
If it can't be parsed, the call to MyArgsParser.parse()
shows a message and terminates the program.
@Args()
class MyArgs {
final int requiredInt;
final int? optionalInt;
int intWithDefault = 7;
}
double
A double is parsed using double.parse(String)
.
If it can't be parsed, the call to MyArgsParser.parse()
shows a message and terminates the program.
@Args()
class MyArgs {
final double requiredDouble;
final double? optionalDouble;
double doubleWithDefault = 7.77;
}
bool
A boolean field produces a flag. A boolean field must have an initializer because it cannot be required since missing a flag just means the opposite of its presence. For the same reason, a boolean field can't be nullable.
Most of the times you want a boolean with the default of false
so that adding a flag turns it to true.
A field with the default of true
produces a flag to negate it,
and no-
is prepended to the flag name.
@Args()
class MyArgs {
bool boolWithDefaultFalse = false; // Use --bool-with-default-false to make it true.
bool boolWithDefaultTrue = true; // Use --no-bool-with-default-true to make it false.
}
enum
An enum is parsed using MyEnum.values.byName(String)
.
If the value does not match any of the enum constants,
the call to MyArgsParser.parse()
shows a message and terminates the program.
@Args()
class MyArgs {
final Fruit requiredEnum;
final Fruit? optionalEnum;
Fruit enumWithDefault = Fruit.mango;
}
enum Fruit { apple, banana, mango, orange }
List, Set
A List
and Set
field produce options that can be passed multiple times in the command line.
Each time adds an item to the collection.
A default value can be used if the option was passed zero times.
Use Set
if you don't care about the order of the values and want them deduplicated.
Otherwise, use List
.
The collections support String
, int
, double
, and enum
.
@Args()
class MyArgs {
final List<String> stringList;
List<String> stringListWithDefault = ['Huey', 'Dewey', 'Louie'];
final List<int> intList;
List<int> intListWithDefault = [1, 2];
final List<double> doubleList;
List<double> doubleListWithDefault = [1, 2.0];
final List<Fruit> enumList;
List<Fruit> enumListWithDefault = [Fruit.apple, Fruit.banana];
final Set<String> stringSet;
Set<String> stringSetWithDefault = {'Huey', 'Dewey', 'Louie'};
final Set<int> intSet;
Set<int> intSetWithDefault = {3, 4};
final Set<double> doubleSet;
Set<double> doubleSetWithDefault = {3, 4.0};
final Set<Fruit> enumSet;
Set<Fruit> enumSetWithDefault = {Fruit.orange, Fruit.banana};
}
enum Fruit { apple, banana, mango, orange }
Help #
The parser automatically adds --help
option.
It prints the usage and terminates the program (parse()
method never returns).
Help messages for arguments #
To add a help message for an option, define a static variable by prepending an underscore
and appending Help
to the field name:
@Args()
class MyArgs {
final String requiredString;
static const _requiredStringHelp = 'Help for the required string.';
// ...
}
Executable Name and Description #
To prepend the help text with the description and an example of the command, pass the following parameters to the macro:
@Args(
description: 'The command description.',
executableName: 'executable_name',
)
class MyArgs { /* ... */ }
Help Example #
This is the output of the full-fledged example file:
The command description.
Usage: executable_name [arguments]
--required-string (mandatory) Help for the required string.
--optional-string
--string-with-default (defaults to "My default string.")
--required-int (mandatory)
--optional-int Help for the optional int.
--int-with-default (defaults to "7")
--required-double (mandatory) Help for the required double.
--optional-double
--double-with-default (defaults to "7.77")
--bool-with-default-false Help for the flag.
--no-bool-with-default-true
--required-enum (mandatory) [apple, banana, mango, orange]
--optional-enum Help for the optional Enum.
[apple, banana, mango, orange]
--enum-with-default [apple, banana, mango (default), orange]
--string-list
--string-list-with-default Help for String[] with default.
(defaults to "Huey", "Dewey", "Louie")
--int-list Help for int[].
--int-list-with-default (defaults to "1", "2")
--double-list Help for double[].
--double-list-with-default (defaults to "1.0", "2.0")
--enum-list Help for Enum[].
[apple, banana, mango, orange]
--enum-list-with-default [apple (default), banana (default), mango, orange]
--string-set Help for String{}.
--string-set-with-default (defaults to "Huey", "Dewey", "Louie")
--int-set Help for int{}.
--int-set-with-default (defaults to "3", "4")
--double-set Help for double{}.
--double-set-with-default (defaults to "3.0", "4.0")
--enum-set Help for Enum{}.
[apple, banana, mango, orange]
--enum-set-with-default [apple, banana (default), mango, orange (default)]
-h, --help Print this usage information.
Error Handling #
Unless --help
is passed, all data is validated according to your data class structure.
On any error, parse()
method prints the first error occurred and the usage to stderr
and terminates the program with the exit code 64.
To ignore all errors but still have the parser populated with the options
derived from your data class (and skip the automatic handling of --help
),
use the standard ArgParser
instance
which this generated parser wraps.
It will return the regular ArgResults
without any error handling:
void main(List<String> argv) {
final result = MyArgsParser().parser.parse(argv);
print(result.option('required-string'));
}
Status #
The macros feature is experimental in Dart. Things are expected to break. Do not use this package in production code.
Roadmap #
The following improvements are blocked because the Macro API does not allow them at this point: