darted_cli 0.1.19 darted_cli: ^0.1.19 copied to clipboard
darted_cli is a customizable Dart CLI framework for building command-line tools with hierarchical command structures, argument parsing, and flag management.
darted_cli #
____ __ __ ________ ____
/ __ \____ ______/ /____ ____/ / / ____/ / / _/
/ / / / __ `/ ___/ __/ _ \/ __ / / / / / / /
/ /_/ / /_/ / / / /_/ __/ /_/ / / /___/ /____/ /
/_____/\__,_/_/ \__/\___/\__,_/____\____/_____/___/
/_____/
darted_cli
is a powerful and developer-friendly Dart package for building feature-rich, structured command-line interfaces (CLI). It simplifies the process of creating command trees, parsing arguments and flags, and handling input validation with a focus on developer experience and ease of use.
You can see how to implement your next big idea using darted_cli through This Blog Post.
Table of Contents #
Features #
- Command Tree Validation: Ensures commands follow the hierarchy and validates parent-child relationships.
- Argument Parsing: Supports named and multi-option arguments with default values.
- Flag Parsing: Handles boolean flags and their negations (e.g.,
--no-flag
). - Call Stack Management: Tracks commands, arguments, and flags in execution order.
- Error Handling: Provides descriptive errors for invalid commands, arguments, or flags.
- Help and Version Flags: Built-in support for
--help
and--version
flags. - Console Management: Display formatted output with colors and styles.
- Extensibility: Easily add custom commands, arguments, and flags.
- Customizable Responses: Define custom error messages for invalid inputs.
- Interactive CLI: Generate dynamic help text for commands.
- Developer-Friendly: Focused on ease of use with minimal boilerplate.
Installation #
Add the following to your pubspec.yaml
file:
dependencies:
darted_cli: [latest_version]
Then, run:
dart pub get
Usage #
1. Define your Commands
Define your CLI commands using a tree structure:
final List<DartedCommand> commandsTree = [
DartedCommand(
// Give the command a name..
name: 'create',
// Give it a helper description.. (optional)
helperDescription: "This will create something..",
// Give it the allowed arguments..
arguments: [
// --name [something] & -n [something] are now allowed and will be availbale in your callback if the user input it!
// If the user didn't input the argument, you will get the default value..
DartedArgument(name: 'name', abbreviation: 'n', defaultValue: 'new_flutter_project', isMultiOption: false),
// You also have the option to allow an argument to have multible options, with input validation based on the accepted options YOU enter!
DartedArgument(name: 'platforms', abbreviation: 'p', acceptedMultiOptionValues: 'android,ios,web', isMultiOption: true, optionsSeparator: ','),
],
// Now, give it the flags allowed for this specific command, You can allow it to be negated too! (--no-flag)
flags: [
// Provided flag template for the --help/-h flag, it's automatically captured and you can customize it's output!
DartedFlag.help,
// Oh, and you can also allow flags to be applied by default even if they are not passed in..
DartedFlag(name: 'package', abbreviation: 'pa', canBeNegated: false, appliedByDefault: true),
DartedFlag(name: 'solo', abbreviation: 's', canBeNegated: true, appliedByDefault: false),
],
// And finally, give your command a callback based on the arguments and flags you get. It can't get any easier!
callback: (arguments, flags) => ConsoleHelper.write(
'${'This command is ' 'create'.withColor(ConsoleColor.green)} I have the arguments: $arguments, and the flags: $flags',
),
subCommands: [
DartedCommand(name: 'a_sub_command',
helperDescription: "A sub command for create..",
callback: (arguments, flags) {
// With the console helper you could:
// - Get an user input?
ConsoleHelper.getUserInput(
promptBuilder: (def, secToTimeout) => 'Give me your name!');
// - Confirm an user's action?
ConsoleHelper.confirm(
prompt: 'Are you absolutely sure??',
acceptedAffirmatives: ['Yea']);
// - Execute a command?
ConsoleHelper.executeCommand('flutter doctor -v');
// - Load a task interactively?
ConsoleHelper.loadWithTask(
task: 'doing something...',
process: () async =>
await Future.delayed(const Duration(seconds: 4)));
// - **NEW in 0.1.11** Prompt the user to select an option interactively?
List<int> theGottenChoices = ConsoleHelper.chooseOption(
'Choose an option',
['Option 1', 'Option 2', 'Option 3'],
isMultiSelect: true,
unselectedIndicator: "[]",
selectedIndicator: "[x]",
selectionIndicator: "->",
);
ConsoleHelper.write('Got the choices: $theGottenChoices');
},
),
],
),
DartedCommand(name: 'another_command', callback: (arguments, flags) {}, helperDescription: "Another top level command...")
];
2. Extend your callback powers with our helpers!
Console Helper
// Get the user's input (with default value and time-out support!)
ConsoleHelper.getUserInput(promptBuilder: (defValue, timeout) => 'enter something...');
// Write out to the console
ConsoleHelper.write("Here's an output!...");
// That's just the easy stuff!
I/O Helper
// All the basic stuff! Creating, deleting, reading, and writing to files and directories.
// Some more exciting things? Here you go..
// List all files in here?
IOHelper.list('lib');
// Find all the files with a custom RegExp pattern and get all their pathes?
IOHelper.files.findAdvanced('lib',RegExp(r'*.yaml'));
// Search all the files in a directory for a specific keyword? Ignore hidded files? exclude some files? All There!
IOHelper.files.search('lib',RegExp(r'someWord'), exclude: [main.dart], ignoreHidden: true);
// Replacing the keyword, renaming, moving, and more, Just check the docs!
Some more stuff we're too modest to mention?
- Loading YAML files and quick parsing?
- ASCII artwork support to get those pretty prints?
- In-console loading animations for those step-by-step tasks?
- ? ( Leave feature request or contribute!)
3. Execute it
Create a main entry point:
import 'package:darted_cli/darted_cli.dart';
void main(List<String> input) async => await dartedEntry(
input: input,
commandsTree: commandsTree,
// The main entry command when someone types in [your_package]
customEntryHelper: (tree) async {
return await AsciiArtModule.textToAscii('DARTED', beforeEachLine: "| ");
},
// Available commands, arguments, and flags to process.
customVersionResponse: () => "when i get -v, here's a response!",
// Oh yeah, the console helper has colors, background colors, and text modifiers!
customHelpResponse: () => 'custom response for the -h flag?'
.withColor(ConsoleColor.cyan),
);
So when the user enters
dart run my_package create --name project_name -p android,ios
You get:
Command: create
Arguments: { name: project_name, platforms: [android, ios] }
Flags: { package: true, solo: false }
Now, Done building your 1-billion dollar CLI Tool?
Run the script in your terminal
dart run [your_package] create --name my_project -flag --no-flag
Or upload it so we all get to take a look!
Developer Experience #
darted_cli is designed with developers in mind, offering:
- Ease of Use: Focus on defining your command logic instead of boilerplate code.
- Minimal Setup: Get started quickly with built-in argument and flag parsing.
- Customizability: Tailor commands, error messages, and output to suit your needs.
- Interactive Debugging: Test your command hierarchy with detailed validation output.
- Scalable Design: Add commands, subcommands, and features without breaking existing functionality.
Why Choose darted_cli?
- Save Time: No need to reimplement parsing logic or validation checks.
- Focus on Logic: Concentrate on the functionality of your CLI application.
- Reliable Framework: Built to handle both simple and complex CLI needs.
Featurs and Requests #
- ✅ Adding custom Ascii art fonts.
- ✅ Adding Command Execution functionality.
- ✅ Adding Prompt to choose an option.
- ❌ Adding option to compile.
- ❌ Adding more animated loaders.
- ❌ You tell me!
License #
Licensed under the MIT License. You are free to use, modify, and distribute this package.