Skip to content

Commit

Permalink
chore: deploy 2.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
LeadcodeDev committed Nov 1, 2024
1 parent 0af500f commit 2375cbf
Show file tree
Hide file tree
Showing 19 changed files with 225 additions and 103 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# 2.3.0
- Implement theming components
- Add `AskTheme` property in `ask` component
- Add `SelectTheme` property in `select` component
- Add `CheckboxTheme` property in `checkbox` component
- Add `TaskTheme` property in `task` component
- Add `SwapTheme` property in `swap` component
- Remove useless `message` property in task component

# 2.2.4
- Make `task` component as windows compatible
- Change default placeholder for `swap` component in example
Expand Down
3 changes: 2 additions & 1 deletion example/task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import 'package:commander_ui/src/level.dart';

Future<void> sleep() => Future.delayed(Duration(seconds: 1));

Future<String> sleepWithValue() => Future.delayed(Duration(seconds: 1), () => 'Hello World !');
Future<String> sleepWithValue() =>
Future.delayed(Duration(seconds: 1), () => 'Hello World !');

Future<void> main() async {
final commander = Commander(level: Level.verbose);
Expand Down
3 changes: 2 additions & 1 deletion lib/src/application/components/ask.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ final class Ask<T> with TerminalTools implements Component<Future<T>> {

void _waitResponse() {
final input = _hidden ? readLineHiddenSync() : readLineSync();
final response = input == null || input.isEmpty ? _resolvedDefaultValue : input;
final response =
input == null || input.isEmpty ? _resolvedDefaultValue : input;

if (_validate != null) {
final result = _validate!(response);
Expand Down
22 changes: 16 additions & 6 deletions lib/src/application/components/checkbox.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import 'package:commander_ui/src/io.dart';
import 'package:mansion/mansion.dart';

/// A component that asks the user to select one or more options.
final class Checkbox<T> with TerminalTools implements Component<Future<List<T>>> {
final class Checkbox<T>
with TerminalTools
implements Component<Future<List<T>>> {
final _completer = Completer<List<T>>();

final Terminal _terminal;
Expand Down Expand Up @@ -69,14 +71,16 @@ final class Checkbox<T> with TerminalTools implements Component<Future<List<T>>>
_currentIndex = _currentIndex - 1;
_render();
}
} else if (key.controlChar == ControlCharacter.arrowDown || key.char == 'j') {
} else if (key.controlChar == ControlCharacter.arrowDown ||
key.char == 'j') {
if (_currentIndex < _options.length - 1) {
_currentIndex = _currentIndex + 1;
_render();
}
} else if (key.char == ' ') {
_onSelect();
} else if ([ControlCharacter.ctrlJ, ControlCharacter.ctrlM].contains(key.controlChar)) {
} else if ([ControlCharacter.ctrlJ, ControlCharacter.ctrlM]
.contains(key.controlChar)) {
_onSubmit();
}
}
Expand Down Expand Up @@ -110,8 +114,13 @@ final class Checkbox<T> with TerminalTools implements Component<Future<List<T>>>

buffer.writeAnsiAll([
if (_currentIndex == index) ..._theme.currentLineColor,
if (isSelected) ..._theme.selectedLineColor else ..._theme.defaultLineColor,
Print(isSelected || _currentIndex == index ? _theme.selectedIcon : _theme.unselectedIcon),
if (isSelected)
..._theme.selectedLineColor
else
..._theme.defaultLineColor,
Print(isSelected || _currentIndex == index
? _theme.selectedIcon
: _theme.unselectedIcon),
if (_currentIndex == index) SetStyles.reset,
]);

Expand Down Expand Up @@ -157,7 +166,8 @@ final class Checkbox<T> with TerminalTools implements Component<Future<List<T>>>
}

void _onSubmit() {
final selectedOptions = _selectedOptions.map((index) => _options[index]).toList();
final selectedOptions =
_selectedOptions.map((index) => _options[index]).toList();

restoreCursorPosition();
clearFromCursorToEnd();
Expand Down
31 changes: 21 additions & 10 deletions lib/src/application/components/select.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ final class Select<T> with TerminalTools implements Component<Future<T>> {
final _completer = Completer<T>();

final Terminal _terminal;
SelectTheme _theme;
late int _displayCount;
final SelectTheme _theme;
late final int _displayCount;

int _currentIndex = 0;
T? _selectedOption;
Expand Down Expand Up @@ -69,18 +69,22 @@ final class Select<T> with TerminalTools implements Component<Future<T>> {
_currentIndex = _currentIndex - 1;
_render();
}
} else if (key.controlChar == ControlCharacter.arrowDown || key.char == 'j') {
} else if (key.controlChar == ControlCharacter.arrowDown ||
key.char == 'j') {
if (_currentIndex < _filteredOptions.length - 1) {
_currentIndex = _currentIndex + 1;
_render();
}
} else if ([ControlCharacter.ctrlJ, ControlCharacter.ctrlM].contains(key.controlChar)) {
} else if ([ControlCharacter.ctrlJ, ControlCharacter.ctrlM]
.contains(key.controlChar)) {
_onSubmit();
} else {
if (RegExp(r'^[\p{L}\p{N}\p{P}\s\x7F]*$', unicode: true).hasMatch(key.char)) {
if (RegExp(r'^[\p{L}\p{N}\p{P}\s\x7F]*$', unicode: true)
.hasMatch(key.char)) {
_currentIndex = 0;

if (key.controlChar == ControlCharacter.backspace && _filter.isNotEmpty) {
if (key.controlChar == ControlCharacter.backspace &&
_filter.isNotEmpty) {
_filter = _filter.substring(0, _filter.length - 1);
} else if (key.controlChar != ControlCharacter.backspace) {
_filter = _filter + key.char;
Expand All @@ -97,7 +101,9 @@ final class Select<T> with TerminalTools implements Component<Future<T>> {
List<T> _filterOptions() {
return _options.where((item) {
final value = _onDisplay?.call(item) ?? item.toString();
return _options.isNotEmpty ? value.toLowerCase().contains(_filter.toLowerCase()) : true;
return _options.isNotEmpty
? value.toLowerCase().contains(_filter.toLowerCase())
: true;
}).toList();
}

Expand All @@ -112,7 +118,9 @@ final class Select<T> with TerminalTools implements Component<Future<T>> {
Print(_theme.askPrefix),
SetStyles.reset,
Print(' $_message '),
..._filter.isEmpty ? _theme.placeholderColorMessage : _theme.filterColorMessage,
..._filter.isEmpty
? _theme.placeholderColorMessage
: _theme.filterColorMessage,
_filter.isEmpty ? Print(_placeholder) : Print(_filter),
SetStyles.reset,
AsciiControl.lineFeed,
Expand All @@ -121,7 +129,9 @@ final class Select<T> with TerminalTools implements Component<Future<T>> {
_filteredOptions.clear();
_filteredOptions.addAll(_filterOptions());

int start = _currentIndex - _displayCount >= 0 ? _currentIndex - _displayCount + 1 : 0;
int start = _currentIndex - _displayCount >= 0
? _currentIndex - _displayCount + 1
: 0;

for (final choice in _filteredOptions.skip(start).take(_displayCount)) {
final isCurrent = _filteredOptions.indexOf(choice) == _currentIndex;
Expand Down Expand Up @@ -172,7 +182,8 @@ final class Select<T> with TerminalTools implements Component<Future<T>> {
SetStyles.reset,
Print(' $_message '),
..._theme.resultMessageColor,
Print(_onDisplay?.call(_selectedOption as T) ?? _selectedOption.toString()),
Print(
_onDisplay?.call(_selectedOption as T) ?? _selectedOption.toString()),
SetStyles.reset,
AsciiControl.lineFeed,
]);
Expand Down
6 changes: 3 additions & 3 deletions lib/src/application/components/swap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import 'package:commander_ui/src/application/terminals/terminal.dart';
import 'package:commander_ui/src/application/themes/default_swap_theme.dart';
import 'package:commander_ui/src/application/utils/terminal_tools.dart';
import 'package:commander_ui/src/domains/models/component.dart';
import 'package:commander_ui/src/domains/themes/checkbox_theme.dart';
import 'package:commander_ui/src/domains/themes/swap_theme.dart';
import 'package:commander_ui/src/io.dart';
import 'package:mansion/mansion.dart';
Expand Down Expand Up @@ -60,7 +59,8 @@ final class Swap<T> with TerminalTools implements Component<Future<bool>> {
} else if (key.controlChar == ControlCharacter.arrowRight) {
_value = false;
_render();
} else if ([ControlCharacter.ctrlJ, ControlCharacter.ctrlM].contains(key.controlChar)) {
} else if ([ControlCharacter.ctrlJ, ControlCharacter.ctrlM]
.contains(key.controlChar)) {
_onSubmit();
}
}
Expand Down Expand Up @@ -91,7 +91,7 @@ final class Swap<T> with TerminalTools implements Component<Future<bool>> {

for (final value in values) {
buffer.writeAnsiAll([
...value == _value ? _theme.selected : _theme.unselected,
...value == _value ? _theme.unselected : _theme.selected,
Print(value ? 'Yes' : ' No'),
SetStyles.reset,
]);
Expand Down
3 changes: 2 additions & 1 deletion lib/src/application/components/task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ final class Task with TerminalTools implements Component<Future<StepManager>> {
final Terminal _terminal;
final TaskTheme _theme;

Task(this._terminal, {TaskTheme? theme}) : _theme = theme ?? DefaultTaskTheme();
Task(this._terminal, {TaskTheme? theme})
: _theme = theme ?? DefaultTaskTheme();

@override
Future<StepManager> handle() async {
Expand Down
4 changes: 2 additions & 2 deletions lib/src/application/ffi/control_mode.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Control Modes
/// https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_node/libc_354.html#SEC363
final class ControlMode {
static const int CSIZE = 0x00000300;
static const int CS8 = 0x00000300;
static const int cSize = 0x00000300;
static const int cS8 = 0x00000300;
}
2 changes: 1 addition & 1 deletion lib/src/application/terminals/unix_terminal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class UnixTerminal implements Terminal {
InputMode.IXON)
..ref.c_oflag = origTermIOS.c_oflag & ~OutputMode.OPOST
..ref.c_cflag =
(origTermIOS.c_cflag & ~ControlMode.CSIZE) | ControlMode.CS8
(origTermIOS.c_cflag & ~ControlMode.cSize) | ControlMode.cS8
..ref.c_lflag = origTermIOS.c_lflag &
~(LocalMode.ECHO |
LocalMode.ICANON |
Expand Down
35 changes: 24 additions & 11 deletions lib/src/application/themes/default_ask_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,38 @@ final class DefaultAskTheme implements AskTheme {
(String? value) => value?.replaceAll(RegExp(r'.'), '*') ?? '';

@override
String Function(String? value) defaultValueFormatter = (String? value) => switch (value) {
String value => ' ($value)',
_ => '',
};
String Function(String? value) defaultValueFormatter =
(String? value) => switch (value) {
String value => ' ($value)',
_ => '',
};

@override
String? Function(String? value) inputFormatter = (String? value) => value;

@override
List<Sequence> successPrefixColor = [SetStyles.reset, SetStyles(Style.foreground(Color.green))];
List<Sequence> successPrefixColor = [
SetStyles.reset,
SetStyles(Style.foreground(Color.green))
];

@override
List<Sequence> errorPrefixColor = [SetStyles(Style.foreground(Color.brightRed))];
List<Sequence> errorPrefixColor = [
SetStyles(Style.foreground(Color.brightRed))
];

@override
List<Sequence> askPrefixColor = [SetStyles(Style.foreground(Color.yellow))];

@override
List<Sequence> validatorColorMessage = [SetStyles(Style.foreground(Color.brightRed))];
List<Sequence> validatorColorMessage = [
SetStyles(Style.foreground(Color.brightRed))
];

@override
List<Sequence> defaultValueColorMessage = [SetStyles(Style.foreground(Color.brightBlack))];
List<Sequence> defaultValueColorMessage = [
SetStyles(Style.foreground(Color.brightBlack))
];

@override
List<Sequence> inputColor = [SetStyles(Style.foreground(Color.brightBlack))];
Expand All @@ -64,13 +74,16 @@ final class DefaultAskTheme implements AskTheme {
theme.errorSuffix = errorSuffix ?? theme.errorSuffix;
theme.successSuffix = successSuffix ?? theme.successSuffix;
theme.secureFormatter = secureFormatter ?? theme.secureFormatter;
theme.defaultValueFormatter = defaultValueFormatter ?? theme.defaultValueFormatter;
theme.defaultValueFormatter =
defaultValueFormatter ?? theme.defaultValueFormatter;
theme.inputFormatter = inputFormatter ?? theme.inputFormatter;
theme.successPrefixColor = successPrefixColor ?? theme.successPrefixColor;
theme.errorPrefixColor = errorPrefixColor ?? theme.errorPrefixColor;
theme.validatorColorMessage = validatorColorMessage ?? theme.validatorColorMessage;
theme.validatorColorMessage =
validatorColorMessage ?? theme.validatorColorMessage;
theme.askPrefixColor = askPrefixColor ?? theme.askPrefixColor;
theme.defaultValueColorMessage = defaultValueColorMessage ?? theme.defaultValueColorMessage;
theme.defaultValueColorMessage =
defaultValueColorMessage ?? theme.defaultValueColorMessage;
theme.inputColor = inputColor ?? theme.inputColor;

return theme;
Expand Down
38 changes: 26 additions & 12 deletions lib/src/application/themes/default_checkbox_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ final class DefaultCheckBoxTheme implements CheckboxTheme {
String unselectedIcon = '◯';

@override
String helpMessage = '(Press ↑/↓ to navigate, space to select, enter to confirm)';
String helpMessage =
'(Press ↑/↓ to navigate, space to select, enter to confirm)';

@override
String Function(String? value) placeholderFormatter = (String? value) => switch (value) {
String value => ' ($value)',
_ => '',
};
String Function(String? value) placeholderFormatter =
(String? value) => switch (value) {
String value => ' ($value)',
_ => '',
};

@override
List<Sequence> currentLineColor = [SetStyles(Style.foreground(Color.white))];
Expand All @@ -30,22 +32,32 @@ final class DefaultCheckBoxTheme implements CheckboxTheme {
List<Sequence> selectedLineColor = [SetStyles(Style.foreground(Color.white))];

@override
List<Sequence> defaultLineColor = [SetStyles(Style.foreground(Color.brightBlack))];
List<Sequence> defaultLineColor = [
SetStyles(Style.foreground(Color.brightBlack))
];

@override
List<Sequence> helpMessageColor = [SetStyles(Style.foreground(Color.brightBlack))];
List<Sequence> helpMessageColor = [
SetStyles(Style.foreground(Color.brightBlack))
];

@override
List<Sequence> successPrefixColor = [SetStyles(Style.foreground(Color.green))];
List<Sequence> successPrefixColor = [
SetStyles(Style.foreground(Color.green))
];

@override
List<Sequence> askPrefixColor = [SetStyles(Style.foreground(Color.yellow))];

@override
List<Sequence> resultMessageColor = [SetStyles(Style.foreground(Color.brightBlack))];
List<Sequence> resultMessageColor = [
SetStyles(Style.foreground(Color.brightBlack))
];

@override
List<Sequence> placeholderColorMessage = [SetStyles(Style.foreground(Color.brightBlack))];
List<Sequence> placeholderColorMessage = [
SetStyles(Style.foreground(Color.brightBlack))
];

DefaultCheckBoxTheme();

Expand All @@ -72,15 +84,17 @@ final class DefaultCheckBoxTheme implements CheckboxTheme {
theme.selectedIcon = selectedIcon ?? theme.selectedIcon;
theme.unselectedIcon = unselectedIcon ?? theme.unselectedIcon;
theme.helpMessage = helpMessage ?? theme.helpMessage;
theme.placeholderFormatter = placeholderFormatter ?? theme.placeholderFormatter;
theme.placeholderFormatter =
placeholderFormatter ?? theme.placeholderFormatter;
theme.currentLineColor = currentLineColor ?? theme.currentLineColor;
theme.selectedLineColor = selectedLineColor ?? theme.selectedLineColor;
theme.defaultLineColor = defaultLineColor ?? theme.defaultLineColor;
theme.helpMessageColor = helpMessageColor ?? theme.helpMessageColor;
theme.successPrefixColor = successPrefixColor ?? theme.successPrefixColor;
theme.askPrefixColor = askPrefixColor ?? theme.askPrefixColor;
theme.resultMessageColor = resultMessageColor ?? theme.resultMessageColor;
theme.placeholderColorMessage = placeholderColorMessage ?? theme.placeholderColorMessage;
theme.placeholderColorMessage =
placeholderColorMessage ?? theme.placeholderColorMessage;

return theme;
}
Expand Down
Loading

0 comments on commit 2375cbf

Please sign in to comment.