feat: [mason_logger] support validation for `prompt`, `promptAny`, and `chooseAny`
- Dominant language
- Dart
- Stars
- 1.1k
- Forks
- 113
- PR merge metrics
- No merged PRs in 30d
Description
**Description**
`Logger` has some user inputs that accept arbitrary data. It can be useful to validate that user input "inline" with a given user input without having to re-prompt the user for an input.
**Requirements**
- [ ] define `Validator` typedef like [Flutter's `FormFieldValidator`](https://api.flutter.dev/flutter/widgets/FormFieldValidator.html).
- [ ] add optional `Validator? validator` parameter to `Logger.prompt`
- [ ] add optional `Validator>? validator` parameter to `Logger.promptAny`
- [ ] add optional `Validator>? validator` parameter to `Logger.chooseAny`
**Additional Context**
> Why these methods?
I think these are the only places a validation makes sense since data types are not very constrained compored to the other inputs.
- `chooseOne` is already very limiting with select one (how would you validate "one" item?).
- `confirm`'s return value is it's "validation" by nature of booleans. "Inline" validation does seem to provide any additional information to the user.
> How would this work?
Take this current validation flow for requiring a compatible dart package name.
```dart
void main(List arguments) {
final value = collectInput();
print(value);
}
String? validate(String value) {
if (value.contains(' ')) return 'Cannot contain spaces';
if (value.contains('.')) return 'Cannot contain dots';
if (value.contains('-')) return 'Cannot contain hyphen';
// descriptive messages
return null;
}
String collectInput() {
Logger logger = Logger();
String value;
String? validation;
do {
var prompt = 'Dart package name';
if (validation != null) {
prompt = 'Dart package name ${red.wrap(validation)}';
}
value = logger.prompt(prompt, defaultValue: 'my_app');
validation = validate(value);
} while (validation != null);
return value;
}
```
Could be reduced to this kind of flow by passing in the validator directly: `validator: validate`
```dart
void main(List arguments) {
final value = collectInput();
print(value);
}
String? validate(String value) {
if (value.contains(' ')) return 'Cannot contain spaces';
if (value.contains('.')) return 'Cannot contain dots';
if (value.contains('-')) return 'Cannot contain hyphen';
return null;
}
String collectInput() {
Logger logger = Logger();
return logger.prompt(
'Dart package name',
defaultValue: 'my_app',
validator: validate,
);
}
```
> How should it look?
I think an "inline" message can use the same style as `Logger.theme.warn`.
```dart
void main(List arguments) {
Logger logger = Logger();
// simulate validation failing
String? validation = logger.theme.warn('Cannot contain spaces');
logger.prompt('Dart package name $validation', defaultValue: 'my_app');
}
```
```
Dart package name Cannot contain spaces (my_app) my app
```
> When should the `validator` function be executed?
If a `validator` is provided, the function executes when the user submits a value. When `validator(value)` returns `null` the value returns as normal to its consumer.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.