From cb7e51461c92f71a387475ab687c0f82e591a8dc Mon Sep 17 00:00:00 2001 From: Elijah Luckey Date: Thu, 15 Sep 2022 13:36:38 -0400 Subject: [PATCH 1/8] Adds `linkWrap` and test --- packages/mason_logger/lib/mason_logger.dart | 1 + packages/mason_logger/lib/src/link_wrap.dart | 8 +++++ .../mason_logger/test/src/link_wrap_test.dart | 32 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 packages/mason_logger/lib/src/link_wrap.dart create mode 100644 packages/mason_logger/test/src/link_wrap_test.dart diff --git a/packages/mason_logger/lib/mason_logger.dart b/packages/mason_logger/lib/mason_logger.dart index d1ed485f9..7238415ae 100644 --- a/packages/mason_logger/lib/mason_logger.dart +++ b/packages/mason_logger/lib/mason_logger.dart @@ -2,4 +2,5 @@ library mason_logger; export 'src/io.dart'; export 'src/level.dart'; +export 'src/link_wrap.dart'; export 'src/mason_logger.dart' show Logger, Progress; diff --git a/packages/mason_logger/lib/src/link_wrap.dart b/packages/mason_logger/lib/src/link_wrap.dart new file mode 100644 index 000000000..05a3019df --- /dev/null +++ b/packages/mason_logger/lib/src/link_wrap.dart @@ -0,0 +1,8 @@ +/// Helper function for "wrapping" an message optional message with link. +String linkWrap(String? message, Uri uri) { + const lead = '\x1B]8;;'; + const trail = '\x1B\\'; + + final encoded = '$lead$uri$trail${message ?? uri}$lead$trail'; + return encoded; +} diff --git a/packages/mason_logger/test/src/link_wrap_test.dart b/packages/mason_logger/test/src/link_wrap_test.dart new file mode 100644 index 000000000..fe41fefee --- /dev/null +++ b/packages/mason_logger/test/src/link_wrap_test.dart @@ -0,0 +1,32 @@ +import 'package:mason_logger/mason_logger.dart'; +import 'package:test/test.dart'; + +void main() { + group('linkWrap', () { + final uri = Uri.parse('https://github.com/felangel/mason/issues/'); + const lead = '\x1B]8;;'; + const trail = '\x1B\\'; + test( + 'builds output with correct encodings: ' r'\x1B]8;;' ' and ' r'\x1B\\', + () { + const message = 'message'; + + final output = linkWrap(message, uri); + final matcher = stringContainsInOrder( + [lead, '$uri', trail, message, lead, trail], + ); + + expect(output, matcher); + }, + ); + + test('builds String with Uri when message is null: ', () { + final output = linkWrap(null, uri); + final matcher = stringContainsInOrder( + [lead, '$uri', trail, '$uri', lead, trail], + ); + + expect(output, matcher); + }); + }); +} From f67dec8685b3122a900289ea6f47794de35343c9 Mon Sep 17 00:00:00 2001 From: Elijah Luckey Date: Thu, 15 Sep 2022 13:36:54 -0400 Subject: [PATCH 2/8] Adds `Logger.link`writer --- .../mason_logger/lib/src/mason_logger.dart | 18 ++++++++ .../test/src/mason_logger_test.dart | 41 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/packages/mason_logger/lib/src/mason_logger.dart b/packages/mason_logger/lib/src/mason_logger.dart index eb5f594c7..8636c9db2 100644 --- a/packages/mason_logger/lib/src/mason_logger.dart +++ b/packages/mason_logger/lib/src/mason_logger.dart @@ -6,6 +6,9 @@ import 'package:mason_logger/mason_logger.dart'; part 'progress.dart'; +/// Callback for writing to `stdout` or `stderr`. +typedef StdoutWriter = void Function(String?); + /// {@template logger} /// A basic Logger which wraps `stdio` and applies various styles. /// {@endtemplate} @@ -49,6 +52,21 @@ class Logger { _stdout.writeln(message); } + /// Writes a message with a clickable link. + /// By default writes to `stdout` with [info], but any [StdoutWriter] works. + /// + /// **NOTE**: Only works on supported terminal emulators. Please see this + /// [link on what is supported](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#supporting-apps). + void link( + String? message, + Uri uri, [ + StdoutWriter? writer, + ]) { + final _writer = writer ?? info; + final _message = linkWrap(message, uri); + _writer(_message); + } + /// Writes delayed message to stdout. void delayed(String? message) => _queue.add(message); diff --git a/packages/mason_logger/test/src/mason_logger_test.dart b/packages/mason_logger/test/src/mason_logger_test.dart index 13d21c9d7..c94106d9a 100644 --- a/packages/mason_logger/test/src/mason_logger_test.dart +++ b/packages/mason_logger/test/src/mason_logger_test.dart @@ -22,6 +22,47 @@ void main() { when(() => stdout.supportsAnsiEscapes).thenReturn(true); }); + group('.link', () { + final uri = Uri.parse('https://github.com/felangel/mason/issues/'); + + test( + 'writes to stdout', + () { + IOOverrides.runZoned( + () { + const message = 'test message'; + const lead = '\x1B]8;;'; + const trail = '\x1B\\'; + + Logger().link(message, uri); + verify( + () => stdout.writeln('$lead$uri$trail$message$lead$trail'), + ).called(1); + }, + stdout: () => stdout, + ); + }, + ); + + test( + 'writes with the provided writer', + () { + IOOverrides.runZoned( + () { + const message = 'test message'; + const lead = '\x1B]8;;'; + const trail = '\x1B\\'; + Logger().link(message, uri, stdout.write); + verify( + () => stdout.write('$lead$uri$trail$message$lead$trail'), + ).called(1); + }, + stdout: () => stdout, + ); + }, + ); + }); + group('level', () { test('is mutable', () { final logger = Logger(); From 4f1e63939c566457c1b85bedddf15ebb9243e679 Mon Sep 17 00:00:00 2001 From: Elijah Luckey Date: Thu, 15 Sep 2022 13:40:02 -0400 Subject: [PATCH 3/8] fixes doc typo --- packages/mason_logger/lib/src/link_wrap.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mason_logger/lib/src/link_wrap.dart b/packages/mason_logger/lib/src/link_wrap.dart index 05a3019df..32931f77b 100644 --- a/packages/mason_logger/lib/src/link_wrap.dart +++ b/packages/mason_logger/lib/src/link_wrap.dart @@ -1,4 +1,4 @@ -/// Helper function for "wrapping" an message optional message with link. +/// Helper function for "wrapping" an optional message with link. String linkWrap(String? message, Uri uri) { const lead = '\x1B]8;;'; const trail = '\x1B\\'; From c306604790bd3339599992c668ff000734bad6de Mon Sep 17 00:00:00 2001 From: Elijah Luckey Date: Thu, 15 Sep 2022 14:48:38 -0400 Subject: [PATCH 4/8] remove Logger.link --- .../mason_logger/lib/src/mason_logger.dart | 15 ------- .../test/src/mason_logger_test.dart | 41 ------------------- 2 files changed, 56 deletions(-) diff --git a/packages/mason_logger/lib/src/mason_logger.dart b/packages/mason_logger/lib/src/mason_logger.dart index 8636c9db2..7515e5111 100644 --- a/packages/mason_logger/lib/src/mason_logger.dart +++ b/packages/mason_logger/lib/src/mason_logger.dart @@ -52,21 +52,6 @@ class Logger { _stdout.writeln(message); } - /// Writes a message with a clickable link. - /// By default writes to `stdout` with [info], but any [StdoutWriter] works. - /// - /// **NOTE**: Only works on supported terminal emulators. Please see this - /// [link on what is supported](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#supporting-apps). - void link( - String? message, - Uri uri, [ - StdoutWriter? writer, - ]) { - final _writer = writer ?? info; - final _message = linkWrap(message, uri); - _writer(_message); - } - /// Writes delayed message to stdout. void delayed(String? message) => _queue.add(message); diff --git a/packages/mason_logger/test/src/mason_logger_test.dart b/packages/mason_logger/test/src/mason_logger_test.dart index c94106d9a..13d21c9d7 100644 --- a/packages/mason_logger/test/src/mason_logger_test.dart +++ b/packages/mason_logger/test/src/mason_logger_test.dart @@ -22,47 +22,6 @@ void main() { when(() => stdout.supportsAnsiEscapes).thenReturn(true); }); - group('.link', () { - final uri = Uri.parse('https://github.com/felangel/mason/issues/'); - - test( - 'writes to stdout', - () { - IOOverrides.runZoned( - () { - const message = 'test message'; - const lead = '\x1B]8;;'; - const trail = '\x1B\\'; - - Logger().link(message, uri); - verify( - () => stdout.writeln('$lead$uri$trail$message$lead$trail'), - ).called(1); - }, - stdout: () => stdout, - ); - }, - ); - - test( - 'writes with the provided writer', - () { - IOOverrides.runZoned( - () { - const message = 'test message'; - const lead = '\x1B]8;;'; - const trail = '\x1B\\'; - Logger().link(message, uri, stdout.write); - verify( - () => stdout.write('$lead$uri$trail$message$lead$trail'), - ).called(1); - }, - stdout: () => stdout, - ); - }, - ); - }); - group('level', () { test('is mutable', () { final logger = Logger(); From c6f29206cd1088e33006540690675f94f1064cfb Mon Sep 17 00:00:00 2001 From: Elijah Luckey Date: Thu, 15 Sep 2022 14:50:27 -0400 Subject: [PATCH 5/8] Remove typedef --- packages/mason_logger/lib/src/mason_logger.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/mason_logger/lib/src/mason_logger.dart b/packages/mason_logger/lib/src/mason_logger.dart index 7515e5111..eb5f594c7 100644 --- a/packages/mason_logger/lib/src/mason_logger.dart +++ b/packages/mason_logger/lib/src/mason_logger.dart @@ -6,9 +6,6 @@ import 'package:mason_logger/mason_logger.dart'; part 'progress.dart'; -/// Callback for writing to `stdout` or `stderr`. -typedef StdoutWriter = void Function(String?); - /// {@template logger} /// A basic Logger which wraps `stdio` and applies various styles. /// {@endtemplate} From 7a005cf39b2d8efeef5ee4cfedd1c9e1ad722764 Mon Sep 17 00:00:00 2001 From: Elijah Luckey Date: Thu, 15 Sep 2022 14:53:48 -0400 Subject: [PATCH 6/8] updates interface for `link` --- packages/mason_logger/lib/mason_logger.dart | 2 +- .../mason_logger/lib/src/{link_wrap.dart => link.dart} | 7 +++++-- .../test/src/{link_wrap_test.dart => link_test.dart} | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) rename packages/mason_logger/lib/src/{link_wrap.dart => link.dart} (53%) rename packages/mason_logger/test/src/{link_wrap_test.dart => link_test.dart} (89%) diff --git a/packages/mason_logger/lib/mason_logger.dart b/packages/mason_logger/lib/mason_logger.dart index 7238415ae..89f86da1c 100644 --- a/packages/mason_logger/lib/mason_logger.dart +++ b/packages/mason_logger/lib/mason_logger.dart @@ -2,5 +2,5 @@ library mason_logger; export 'src/io.dart'; export 'src/level.dart'; -export 'src/link_wrap.dart'; +export 'src/link.dart'; export 'src/mason_logger.dart' show Logger, Progress; diff --git a/packages/mason_logger/lib/src/link_wrap.dart b/packages/mason_logger/lib/src/link.dart similarity index 53% rename from packages/mason_logger/lib/src/link_wrap.dart rename to packages/mason_logger/lib/src/link.dart index 32931f77b..36bd12676 100644 --- a/packages/mason_logger/lib/src/link_wrap.dart +++ b/packages/mason_logger/lib/src/link.dart @@ -1,5 +1,8 @@ -/// Helper function for "wrapping" an optional message with link. -String linkWrap(String? message, Uri uri) { +/// Helper function for "encoding" an optional message with link. +String link({ + required Uri uri, + String? message, +}) { const lead = '\x1B]8;;'; const trail = '\x1B\\'; diff --git a/packages/mason_logger/test/src/link_wrap_test.dart b/packages/mason_logger/test/src/link_test.dart similarity index 89% rename from packages/mason_logger/test/src/link_wrap_test.dart rename to packages/mason_logger/test/src/link_test.dart index fe41fefee..7f3fec118 100644 --- a/packages/mason_logger/test/src/link_wrap_test.dart +++ b/packages/mason_logger/test/src/link_test.dart @@ -11,7 +11,7 @@ void main() { () { const message = 'message'; - final output = linkWrap(message, uri); + final output = link(message: message, uri: uri); final matcher = stringContainsInOrder( [lead, '$uri', trail, message, lead, trail], ); @@ -21,7 +21,7 @@ void main() { ); test('builds String with Uri when message is null: ', () { - final output = linkWrap(null, uri); + final output = link(uri: uri); final matcher = stringContainsInOrder( [lead, '$uri', trail, '$uri', lead, trail], ); From 96824abc82821001f02d831b2874d67f543b7953 Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Fri, 16 Sep 2022 10:59:36 -0500 Subject: [PATCH 7/8] minor tweaks --- packages/mason_logger/example/main.dart | 7 +++++- packages/mason_logger/lib/src/link.dart | 24 ++++++++++++------- packages/mason_logger/test/src/link_test.dart | 4 ++-- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/mason_logger/example/main.dart b/packages/mason_logger/example/main.dart index d852bf592..0cd4547eb 100644 --- a/packages/mason_logger/example/main.dart +++ b/packages/mason_logger/example/main.dart @@ -46,5 +46,10 @@ Future main() async { final canceling = logger.progress('Trying to cancel now!'); await Future.delayed(const Duration(seconds: 1)); canceling.cancel(); - logger.info('Done!'); + + final repoLink = link( + message: 'GitHub Repository', + uri: Uri.parse('https://github.com/felangel/mason'), + ); + logger.info('To learn more, visit the $repoLink.'); } diff --git a/packages/mason_logger/lib/src/link.dart b/packages/mason_logger/lib/src/link.dart index 36bd12676..a461ba0ed 100644 --- a/packages/mason_logger/lib/src/link.dart +++ b/packages/mason_logger/lib/src/link.dart @@ -1,11 +1,17 @@ -/// Helper function for "encoding" an optional message with link. -String link({ - required Uri uri, - String? message, -}) { - const lead = '\x1B]8;;'; - const trail = '\x1B\\'; +/// Wraps [uri] with an escape sequence so it's recognized as a hyperlink. +/// An optional message can be used in place of the [uri]. +/// If no [message] is provided, the text content will be the full [uri]. +/// +/// ```dart +/// final plainLink = link(Uri.parse('https://dart.dev')); +/// print(plainLink); // Equivalent to `[https://dart.dev](https://dart.dev)` in markdown +/// +/// final richLink = link(Uri.parse('https://dart.dev'), message: 'The Dart Website'); +/// print(richLink); // Equivalent to `[The Dart Website](https://dart.dev)` in markdown +/// ``` +String link({required Uri uri, String? message}) { + const leading = '\x1B]8;;'; + const trailing = '\x1B\\'; - final encoded = '$lead$uri$trail${message ?? uri}$lead$trail'; - return encoded; + return '$leading$uri$trailing${message ?? uri}$leading$trailing'; } diff --git a/packages/mason_logger/test/src/link_test.dart b/packages/mason_logger/test/src/link_test.dart index 7f3fec118..38a11adaf 100644 --- a/packages/mason_logger/test/src/link_test.dart +++ b/packages/mason_logger/test/src/link_test.dart @@ -2,15 +2,15 @@ import 'package:mason_logger/mason_logger.dart'; import 'package:test/test.dart'; void main() { - group('linkWrap', () { + group('link', () { final uri = Uri.parse('https://github.com/felangel/mason/issues/'); const lead = '\x1B]8;;'; const trail = '\x1B\\'; + test( 'builds output with correct encodings: ' r'\x1B]8;;' ' and ' r'\x1B\\', () { const message = 'message'; - final output = link(message: message, uri: uri); final matcher = stringContainsInOrder( [lead, '$uri', trail, message, lead, trail], From 3fd7075f4407d69fb7015f9b1d171b1b3a7feeca Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Fri, 16 Sep 2022 11:03:09 -0500 Subject: [PATCH 8/8] fix typo in docs --- packages/mason_logger/lib/src/link.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mason_logger/lib/src/link.dart b/packages/mason_logger/lib/src/link.dart index a461ba0ed..47bdb64fb 100644 --- a/packages/mason_logger/lib/src/link.dart +++ b/packages/mason_logger/lib/src/link.dart @@ -3,10 +3,10 @@ /// If no [message] is provided, the text content will be the full [uri]. /// /// ```dart -/// final plainLink = link(Uri.parse('https://dart.dev')); +/// final plainLink = link(uri: Uri.parse('https://dart.dev')); /// print(plainLink); // Equivalent to `[https://dart.dev](https://dart.dev)` in markdown /// -/// final richLink = link(Uri.parse('https://dart.dev'), message: 'The Dart Website'); +/// final richLink = link(uri: Uri.parse('https://dart.dev'), message: 'The Dart Website'); /// print(richLink); // Equivalent to `[The Dart Website](https://dart.dev)` in markdown /// ``` String link({required Uri uri, String? message}) {