cli_annotations

Creator: coderz1093

Last updated:

0 purchases

cli_annotations Image
cli_annotations Images

Languages

Categories

Add to Cart

Description:

cli annotations

cli-gen #





🚧 This package is in early preview and is subject to API changes.

Build CLI applications from plain Dart classes and functions.


Before
After











Table of Contents #

Motivation
Quick Start

Installation
Run Build Runner
Define the Command Runner
Define a Command
Define a Subcommand
Run the Application


Features

Type Safe Argument Parsing

Supported Types
Collection Types
Enums and Allowed Values


Help Text Inference (--help)

Parameter Help Text
Command Descriptions


Name Formatting
Named and Positional Parameters


Design Goals
Under the Hood
Inspiration
License

Motivation #
The ability to quickly whip up a command line script or application is a powerful skill for a developer to have. Compared to the Dart language itself, which offers a tremendous developer experience when building all kinds of apps, cli-based libraries like package:args leave something to be desired when it comes to easily building and maintaining application logic.
cli-gen aims to offer quality-of-life improvements for building and maintaining CLI apps, by allowing you to generate command line APIs from plain Dart functions. It achives this by providing the following features:

parsing String arguments to any Dart type
--help text inference from Method declarations, doc comments, and default values
proper error handling, without printing stack traces to the console

cli-gen was designed to make writing CLI applications as intuitive as writing any other piece of Dart code.
Quick Start #
Installation #
Add cli_annotations to your pubspec dependencies and cli_gen and build_runner as dev dependencies.
name: dart_git
description: An implementation of the git CLI in Dart.

environment:
sdk: ^3.0.0

dependencies:
cli_annotations: ^0.1.0-dev.4

dev_dependencies:
build_runner: ^2.4.8
cli_gen: ^0.1.0-dev.4

# define an executable name (optional)
executables:
dart_git: main
copied to clipboard
You can optionally define an executable name and activate it using pub global activate.
Run Build Runner #
Once dependencies are installed, start the build_runner to begin code generation.
$ dart run build_runner watch -d
copied to clipboard
Define the Command Runner #
Create a CommandRunner by annotating a class with @cliRunner and extending the generated superclass (using the usual _$ prefix).
The generated code contains a single CommandRunner.run() method, which is the entry point for your CLI application, to be called from the main function.
@cliRunner
class GitRunner extends _$GitRunner {
// ...
}
copied to clipboard
Define a Command #
Inside the CommandRunner class, create a Command by creating a method and annotating it with @cliCommand. See the Features section for more information on the supported types and features.
@cliRunner
class GitRunner extends _$GitRunner {
@cliCommand
Future<void> merge({
required String branch,
MergeStrategy strategy = MergeStrategy.ort,
bool? commit,
}) async {
// ... `git merge` logic ...
}
}
copied to clipboard
You can create as many commands inside the CommandRunner class as you'd like:
@cliRunner
class GitRunner extends _$GitRunner {
@cliCommand
Future<void> merge({
required String branch,
MergeStrategy strategy = MergeStrategy.ort,
bool? commit,
}) async { /* ... */ }

@cliCommand
Future<void> stashPush() async { /* ... */ }

@cliCommand
Future<void> stashPop() async { /* ... */ }

// ...
}
copied to clipboard
Define a Subcommand #
As your application grows, you may want to separate your commands into their own groups.
To do so, create a Subcommand class by annotating the class with @cliSubcommand and extending the generated superclass.
@cliSubcommand
class StashSubcommand extends _$StashSubcommand {
@cliCommand
Future<void> push() async { /* ... */ }

@cliCommand
Future<void> pop() async { /* ... */ }
}

copied to clipboard
Subcommands can then be connected to the main CommandRunner class, or to another Subcommand class, by using the @cliMount annotation.
@cliRunner
class GitRunner extends _$GitRunner {
@cliMount
StashSubcommand get stash => StashSubcommand();
}
copied to clipboard
Run the Application #
Finally, create a main function that calls the run method on your CommandRunner.
void main(List<String> arguments) async {
final runner = GitRunner();
await runner.run(arguments);
}
copied to clipboard
Your application is ready to go! 🎉
Run a command to test out the generated help text and see the argument parsing in action.
# activate the executable (if executable is defined in `pubspec.yaml`)
$ dart pub global activate . --source=path

# run the application
$ dart_git merge --help
copied to clipboard
You should see the following output:
$ dart_git merge --help
Join two or more development histories together.

Usage: git-runner merge [arguments]
--branch (mandatory)
--commit
--options

Run "git-runner help" to see global options.
copied to clipboard
Features #
Type-Safe Argument Parsing #
cli-gen automatically parses incoming string arguments into the correct type, and automatically informs your user if they've entered an invalid value.
Supported Types
You can define your command methods with any Dart primitive type or enum, and cli-gen will automatically parse the incoming string arguments into the correct type.
@cliCommand
Future<void> myCustomCommand({
// Use any supported type, nullable or not
Uri? outputFile,

// Enums can automatically be parsed from strings
MergeStrategy? strategy,

// Custom types can also be used, but require passing your own
// String parser to the `@Option` annotation
@Option(parser: Email.fromString) Email? email,
}) async {
// ...
}
copied to clipboard

NOTE: Types that can be automatically parsed are: String, int, double, bool, num, Uri, BigInt, and DateTime

Collection Types
The Collection types List, Set, and Iterable are also supported, and can be used in combination with any of the above supported types.
@cliCommand
Future<void> myCustomCommand({
List<Uri>? inputFiles,
}) async {
// ...
}
copied to clipboard
Help Text Inference (--help) #
CLI applications typically provide a --help option that displays a list of available commands and descriptions of their parameters, to help users understand how they can interact with the application.
Rather than manually manitaining these details yourself, cli-gen automatically generates help text from your annotated methods, based on the method and parameter names, doc comments, default values, and whether each parameter is required or not.
Parameter Help Text
@cliCommand
Future<void> myCustomCommand({
// Required parameters will be shown to the user as `mandatory`
required String requiredParam,

// Optional and/or nullable parameters are not `mandatory`
int? optionalParam,

// Default values are also shown in the help text
String defaultPath = '~/',

// Use doc comments (i.e. 3 slashes) to display a description of the parameter
/// A parameter that uses a doc comment
String someDocumentedParameter,
}) async {
// ...
}
copied to clipboard
The above Dart function will generate a cli command with the following help text:
$ my-custom-command --help
Save your local modifications to a new stash.

Usage: git stash my-custom-command [arguments]
-h, --help Print this usage information.
--required-param (mandatory)
--optional-param
--default-path (defaults to "~/")
--some-documented-parameter A parameter that uses a doc comment

Run "git help" to see global options.
copied to clipboard
Command Descriptions
You can also generate descriptions for your commands and the entire application by using doc comments on the annotated classes and methods.
/// A dart implementation of the git CLI.
@cliRunner
class GitRunner extends _$GitRunner {

/// Merge two or more development histories together.
@cliCommand
Future<void> commit() async {
// ...
}
}
copied to clipboard
will generate:
$ git-runner --help
A dart implementation of the git CLI.

Usage: git-runner [arguments]
-h, --help Print this usage information.

Available commands:
commit Merge two or more development histories together.

Run "git help" to see global options.
copied to clipboard
Enums and Allowed Values
Enums are unique in that they inherently define a finite set of allowable values. cli-gen can use that information to generate a list of allowed values in the help text.
enum Values { a, b, c }
copied to clipboard
Using the above Values enum as a parameter to a cliCommand will generate the following help text:
--values (allowed: a, b, c)
copied to clipboard
If you ever need to override the default allowed values, you can do so by providing a list of values to the allowed parameter of the @Option annotation.
Name Formatting #
cli-gen translates Dart class, method and parameter names to kebab-case, which is the convention for CLI commands and flags.
For example, a method named stashChanges will be translated to stash-changes, and a parameter named outputFile will be translated to --output-file.
To override the default behavior, simply provide a name to the respective annotation (supported for @cliCommand, @cliSubcommand, @cliRunner, and @Option).
Named and Positional Parameters #
cli_gen can handle parameters no matter if they're positional or named; you're free to mix and match as you see fit.
@cliCommand
Future<void> myCustomCommand(
int? positionalParam, {
String? namedParam,
}) async {
// ...
}
copied to clipboard
Under the Hood #
cli-gen generates code that uses package:args classes and utilities to manage command hierarchies and help text generation. The annotations included with this package are a 1:1 mapping to similar or identical concepts included with package:args, for example:

@cliRunner

generates a CommandRunner class
has a run method that should be passed args and run from your main function
mounts any nested commands as subcommands via CommandRunner.addCommand


@cliCommand

generates a Command class
overrides the run method with a call to your method or function


@cliSubcommand

generates a Command class
adds all nested commands as subcommands via Command.addSubcommand



Examples of generated code can be found in the example project, within their respective .g.dart files.
Design Goals #
TODO: a little blurb about the project goals (incl. what cli-gen is and what it is not).
Inspiration #
Several projects were researched as references of CLI ergonomics and macro libraries, including:

clap - a declarative CLI parser for Rust

License #
cli-gen is released under the MIT License. See LICENSE for details.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files In This Product:

Customer Reviews

There are no reviews.