diff --git a/packages/mason_logger/lib/src/progress.dart b/packages/mason_logger/lib/src/progress.dart index e662eaafd..bf747f3b4 100644 --- a/packages/mason_logger/lib/src/progress.dart +++ b/packages/mason_logger/lib/src/progress.dart @@ -5,10 +5,17 @@ part of 'mason_logger.dart'; /// {@endtemplate} class ProgressOptions { /// {@macro progress_options} - const ProgressOptions({this.animation = const ProgressAnimation()}); + const ProgressOptions({ + this.animation = const ProgressAnimation(), + this.trailing = '...', + }); /// The progress animation configuration. final ProgressAnimation animation; + + /// The trailing string following progress messages. + /// Defaults to "..." + final String trailing; } /// {@template progress_animation} @@ -58,7 +65,7 @@ class Progress { final frames = _options.animation.frames; final char = frames.isEmpty ? '' : frames.first; final prefix = char.isEmpty ? char : '${lightGreen.wrap(char)} '; - _write('$prefix$_message...'); + _write('$prefix$_message${_options.trailing}'); return; } @@ -130,7 +137,7 @@ class Progress { final char = frames.isEmpty ? '' : frames[_index % frames.length]; final prefix = char.isEmpty ? char : '${lightGreen.wrap(char)} '; - _write('$_clearLine$prefix$_message... $_time'); + _write('$_clearLine$prefix$_message${_options.trailing} $_time'); } void _write(String object) { diff --git a/packages/mason_logger/test/src/progress_test.dart b/packages/mason_logger/test/src/progress_test.dart index d4fb6339f..40baaf99c 100644 --- a/packages/mason_logger/test/src/progress_test.dart +++ b/packages/mason_logger/test/src/progress_test.dart @@ -55,6 +55,33 @@ void main() { ); }); + test( + 'writes static message when stdioType is not terminal w/custom trailing', + () async { + const progressOptions = ProgressOptions(trailing: '!!!'); + when(() => stdout.hasTerminal).thenReturn(false); + await _runZoned( + () async { + const message = 'test message'; + final done = Logger(progressOptions: progressOptions).progress( + message, + ); + await Future.delayed(const Duration(milliseconds: 400)); + done.complete(); + verifyInOrder([ + () => stdout.write('${lightGreen.wrap('⠋')} $message!!!'), + () { + stdout.write( + '''\u001b[2K\r${lightGreen.wrap('✓')} $message ${darkGray.wrap('(0.4s)')}\n''', + ); + }, + ]); + }, + stdout: () => stdout, + zoneValues: {AnsiCode: true}, + ); + }); + test('writes custom progress animation to stdout', () async { await _runZoned( () async { @@ -133,6 +160,47 @@ void main() { ); }); + test('writes custom progress animation to stdout w/custom trailing', + () async { + await _runZoned( + () async { + const time = '(0.Xs)'; + const message = 'test message'; + const progressOptions = ProgressOptions( + animation: ProgressAnimation(frames: ['+', 'x', '*']), + trailing: '!!!', + ); + final done = Logger().progress(message, options: progressOptions); + await Future.delayed(const Duration(milliseconds: 400)); + done.complete(); + verifyInOrder([ + () { + stdout.write( + '''${lightGreen.wrap('\b${'\b' * (message.length + 4 + time.length)}+')} $message!!! ${darkGray.wrap('(0.1s)')}''', + ); + }, + () { + stdout.write( + '''${lightGreen.wrap('\b${'\b' * (message.length + 4 + time.length)}x')} $message!!! ${darkGray.wrap('(0.2s)')}''', + ); + }, + () { + stdout.write( + '''${lightGreen.wrap('\b${'\b' * (message.length + 4 + time.length)}*')} $message!!! ${darkGray.wrap('(0.3s)')}''', + ); + }, + () { + stdout.write( + '''\b${'\b' * (message.length + 4 + time.length)}\u001b[2K${lightGreen.wrap('✓')} $message ${darkGray.wrap('(0.4s)')}\n''', + ); + }, + ]); + }, + stdout: () => stdout, + stdin: () => stdin, + ); + }); + group('.complete', () { test('writes lines to stdout', () async { await _runZoned(