Commander is a Dart library for creating user interfaces within the terminal.
It provides interactive components such as option selection and text input with advanced management of user input.
To use Commander in your Dart project, add this to your pubspec.yaml
file :
dependencies:
commander_ui: ^2.0.0
Then run pub get
to install the dependencies.
A simple example of using Commander to create an ask component :
- β Secure
- β Integrated or custom validators
- β Default value
Future<void> main() async {
final commander = Commander(level: Level.verbose);
final value = await commander.ask('What is your email ?',
validate: (validator) => validator
..notEmpty(message: 'Name cannot be empty :)')
..email(message: 'Please enter a valid email'));
// Custom validator
final value = await commander.ask('What is your name ?',
validate: (validator) => validator
..validate((value) => value == 'Bob'
? 'Bob is not allowed'
: null));
print(value);
}
A simple example of using Commander to create a number component :
- β Integrated or custom validators
- β Default value
- β Custom rendering
- β
double
orint
(num
by default)
Future<void> main() async {
final commander = Commander(level: Level.verbose);
final value = await commander.number('What is your age ?',
interval: 1,
onDisplay: (value) => value?.toStringAsFixed(2),
validate: (validator) => validator
..greaterThan(18, message: 'You must be at least 18 years old')
..lowerThan(99, message: 'You must be at most 99 years old'));
print(value);
}
A simple example of using Commander to create an option selection component :
- β Placeholder
- β Default selected
- β Searchable values
- β Display transformer
- β Max display count (default as 5)
Future<void> main() async {
final commander = Commander(level: Level.verbose);
final value = await commander.select('What is your name ?',
onDisplay: (value) => value,
placeholder: 'Type to search',
defaultValue: 'Charlie',
options: ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'John']);
print(value);
}
A simple example of using Commander to create a swap component :
- β Select value with directional arrows
Future<void> main() async {
final commander = Commander(level: Level.verbose);
final value = await commander.swap('Do you love cats',
defaultValue: true,
placeholder: 'π'
);
final str = switch (value) {
true => 'I love cats π',
false => 'I prefer dogs π',
};
print(str);
}
A simple example of using Commander to create a task component :
- β Multiple steps per task
- β Success, warn and error results
- β Sync and async action supports
Future<void> sleep() => Future.delayed(Duration(seconds: 1));
Future<String> sleepWithValue() =>
Future.delayed(Duration(seconds: 1), () => 'Hello World !');
Future<void> main() async {
final commander = Commander(level: Level.verbose);
final successTask = await commander.task();
await successTask.step('Success step 1', callback: sleepWithValue);
await successTask.step('Success step 2', callback: sleep);
successTask.success('Success task data are available !');
final warnTask = await commander.task();
await warnTask.step('Warn step 1', callback: sleepWithValue);
await warnTask.step('Warn step 2', callback: sleep);
await warnTask.step('Warn step 3', callback: sleep);
warnTask.warn('Warn task !');
final errorTask = await commander.task();
await errorTask.step('Error step 1', callback: sleepWithValue);
await errorTask.step('Error step 2', callback: sleep);
await errorTask.step('Error step 3', callback: sleep);
errorTask.error('Error task !');
}
A simple example of using Commander to create a checkbox component :
- β Placeholder
- β Default checked
- β Single or multiple selection
- β Display transforme
Future<void> main() async {
final commander = Commander(level: Level.verbose);
final value = await commander.checkbox(
'What is your favorite pet ?',
defaultValue: 'Charlie',
options: ['cat', 'dog', 'bird'],
);
print(value);
}
A simple example of using Commander to create a table component :
- β Without column and line borders
- β With column and line borders
- β With column borders and without line borders
- β With line borders and without column borders
Future<void> main() async {
final commander = Commander(level: Level.verbose);
commander.table(
columns: ['Name', 'Age', 'Country', 'City'],
lineSeparator: false,
columnSeparator: false,
data: [
['Alice', '20', 'USA', 'New York'],
['Bob', '25', 'Canada', 'Toronto'],
['Charlie', '30', 'France', 'Paris'],
['David', '35', 'Germany', 'Berlin'],
['Eve', '40', 'Italy', 'Rome'],
['Frank', '45', 'Japan', 'Tokyo'],
['John', '50', 'China', 'Beijing'],
],
);
}
A simple example of using Commander to create an alternative screen component :
- β Set title
- β Clear screen on start
- β Restore screen on stop
Future<void> main() async {
final commander = Commander(level: Level.verbose);
final screen = commander.screen(title: 'First screen');
screen.enter();
await sleep();
print('Hello screen !');
await sleep();
screen.leave();
print('Goodbye screen !');
}
Future<void> wait() =>
Future.delayed(Duration(seconds: Random().nextInt(3) + 1));
Commander provides a theming system to customize the appearance of the components. It is possible to define a global theme for all components or a specific theme for each component.
Future<void> main() async {
final commander = Commander(
level: Level.verbose,
componentTheme: ComponentTheme(
askTheme: DefaultAskTheme.copyWith(askPrefix: 'π€')
));
final value = await commander.ask('What is your email ?',
validate: (validator) => validator
..notEmpty(message: 'Name cannot be empty :)')
..email(message: 'Please enter a valid email'));
print(value);
}
Each component that interacts with the user has a theme
property that allows the appearance to be customised.
Future<void> main() async {
final commander = Commander(level: Level.verbose);
final value = await commander.ask('What is your email ?',
theme: DefaultAskTheme.copyWith(askPrefix: 'π€'),
validate: (validator) => validator
..notEmpty(message: 'Name cannot be empty :)')
..email(message: 'Please enter a valid email'));
print(value);
}