OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Message logging. | 5 /// Message logging. |
6 import 'dart:async'; | 6 import 'dart:async'; |
7 import 'dart:convert'; | 7 import 'dart:convert'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 | 9 |
10 import 'package:args/command_runner.dart'; | 10 import 'package:args/command_runner.dart'; |
(...skipping 11 matching lines...) Expand all Loading... |
22 /// | 22 /// |
23 /// log.json.error(...); | 23 /// log.json.error(...); |
24 final json = new _JsonLogger(); | 24 final json = new _JsonLogger(); |
25 | 25 |
26 /// The current logging verbosity. | 26 /// The current logging verbosity. |
27 Verbosity verbosity = Verbosity.NORMAL; | 27 Verbosity verbosity = Verbosity.NORMAL; |
28 | 28 |
29 /// Whether or not to log entries with prejudice. | 29 /// Whether or not to log entries with prejudice. |
30 bool withPrejudice = false; | 30 bool withPrejudice = false; |
31 | 31 |
| 32 /// Whether or not to log entries sparklily. |
| 33 bool sparkle = false; |
| 34 |
32 /// In cases where there's a ton of log spew, make sure we don't eat infinite | 35 /// In cases where there's a ton of log spew, make sure we don't eat infinite |
33 /// memory. | 36 /// memory. |
34 /// | 37 /// |
35 /// This can occur when the backtracking solver stumbles into a pathological | 38 /// This can occur when the backtracking solver stumbles into a pathological |
36 /// dependency graph. It generally will find a solution, but it may log | 39 /// dependency graph. It generally will find a solution, but it may log |
37 /// thousands and thousands of entries to get there. | 40 /// thousands and thousands of entries to get there. |
38 const _MAX_TRANSCRIPT = 10000; | 41 const _MAX_TRANSCRIPT = 10000; |
39 | 42 |
40 /// The list of recorded log messages. Will only be recorded if | 43 /// The list of recorded log messages. Will only be recorded if |
41 /// [recordTranscript()] is called. | 44 /// [recordTranscript()] is called. |
42 Transcript<Entry> _transcript; | 45 Transcript<Entry> _transcript; |
43 | 46 |
44 /// The currently-animated progress indicator, if any. | 47 /// The currently-animated progress indicator, if any. |
45 /// | 48 /// |
46 /// This will also be in [_progresses]. | 49 /// This will also be in [_progresses]. |
47 Progress _animatedProgress; | 50 Progress _animatedProgress; |
48 | 51 |
49 _Collapser _collapser; | 52 _Collapser _collapser; |
50 | 53 |
51 final _cyan = getSpecial('\u001b[36m'); | 54 final _cyan = getSpecial('\u001b[36m'); |
52 final _green = getSpecial('\u001b[32m'); | 55 final _green = getSpecial('\u001b[32m'); |
53 final _magenta = getSpecial('\u001b[35m'); | 56 final _magenta = getSpecial('\u001b[35m'); |
54 final _red = getSpecial('\u001b[31m'); | 57 final _red = getSpecial('\u001b[31m'); |
55 final _yellow = getSpecial('\u001b[33m'); | 58 final _yellow = getSpecial('\u001b[33m'); |
| 59 final _blue = getSpecial('\u001b[34m'); |
56 final _gray = getSpecial('\u001b[1;30m'); | 60 final _gray = getSpecial('\u001b[1;30m'); |
57 final _none = getSpecial('\u001b[0m'); | 61 final _none = getSpecial('\u001b[0m'); |
58 final _noColor = getSpecial('\u001b[39m'); | 62 final _noColor = getSpecial('\u001b[39m'); |
59 final _bold = getSpecial('\u001b[1m'); | 63 final _bold = getSpecial('\u001b[1m'); |
60 | 64 |
| 65 /// All color codees. |
| 66 var _allColors = [_cyan, _green, _magenta, _red, _yellow, _blue, '']; |
| 67 |
61 /// An enum type for defining the different logging levels a given message can | 68 /// An enum type for defining the different logging levels a given message can |
62 /// be associated with. | 69 /// be associated with. |
63 /// | 70 /// |
64 /// By default, [ERROR] and [WARNING] messages are printed to sterr. [MESSAGE] | 71 /// By default, [ERROR] and [WARNING] messages are printed to sterr. [MESSAGE] |
65 /// messages are printed to stdout, and others are ignored. | 72 /// messages are printed to stdout, and others are ignored. |
66 class Level { | 73 class Level { |
67 /// An error occurred and an operation could not be completed. | 74 /// An error occurred and an operation could not be completed. |
68 /// | 75 /// |
69 /// Usually shown to the user on stderr. | 76 /// Usually shown to the user on stderr. |
70 static const ERROR = const Level._("ERR "); | 77 static const ERROR = const Level._("ERR "); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 var logFn = verbosity._loggers[level]; | 243 var logFn = verbosity._loggers[level]; |
237 if (logFn != null) logFn(entry); | 244 if (logFn != null) logFn(entry); |
238 | 245 |
239 if (_transcript != null) _transcript.add(entry); | 246 if (_transcript != null) _transcript.add(entry); |
240 } | 247 } |
241 | 248 |
242 final _capitalizedAnsiEscape = new RegExp(r'\u001b\[\d+(;\d+)?M'); | 249 final _capitalizedAnsiEscape = new RegExp(r'\u001b\[\d+(;\d+)?M'); |
243 | 250 |
244 /// Returns [string] formatted as it would be if it were logged. | 251 /// Returns [string] formatted as it would be if it were logged. |
245 String format(String string) { | 252 String format(String string) { |
246 if (!withPrejudice) return string; | 253 if (sparkle) { |
| 254 string = string.replaceAllMapped(new RegExp(r'.'), (match) { |
| 255 var char = "${choose(_allColors)}${match[0]}$_noColor"; |
| 256 return (withPrejudice || random.nextBool()) ? char : "$_bold$char$_none"; |
| 257 }); |
| 258 } |
247 | 259 |
248 // [toUpperCase] can corrupt terminal colorings, so fix them up using | 260 if (withPrejudice) { |
249 // [replaceAllMapped]. | 261 // [toUpperCase] can corrupt terminal colorings, so fix them up using |
250 string = string.toUpperCase().replaceAllMapped(_capitalizedAnsiEscape, | 262 // [replaceAllMapped]. |
251 (match) => match[0].toLowerCase()); | 263 string = string.toUpperCase().replaceAllMapped(_capitalizedAnsiEscape, |
| 264 (match) => match[0].toLowerCase()); |
252 | 265 |
253 // Don't use [bold] because it's disabled under [withPrejudice]. | 266 // Don't use [bold] because it's disabled under [withPrejudice]. |
254 return "$_bold$string$_none"; | 267 string = "$_bold$string$_none"; |
| 268 } |
| 269 |
| 270 return string; |
255 } | 271 } |
256 | 272 |
257 /// Logs an asynchronous IO operation. | 273 /// Logs an asynchronous IO operation. |
258 /// | 274 /// |
259 /// Logs [startMessage] before the operation starts, then when [operation] | 275 /// Logs [startMessage] before the operation starts, then when [operation] |
260 /// completes, invokes [endMessage] with the completion value and logs the | 276 /// completes, invokes [endMessage] with the completion value and logs the |
261 /// result of that. Returns a future that completes after the logging is done. | 277 /// result of that. Returns a future that completes after the logging is done. |
262 /// | 278 /// |
263 /// If [endMessage] is omitted, then logs "Begin [startMessage]" before the | 279 /// If [endMessage] is omitted, then logs "Begin [startMessage]" before the |
264 /// operation and "End [startMessage]" after it. | 280 /// operation and "End [startMessage]" after it. |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 } | 463 } |
448 } | 464 } |
449 | 465 |
450 /// Wraps [text] in the ANSI escape codes to make it bold when on a platform | 466 /// Wraps [text] in the ANSI escape codes to make it bold when on a platform |
451 /// that supports that. | 467 /// that supports that. |
452 /// | 468 /// |
453 /// Use this to highlight the most important piece of a long chunk of text. | 469 /// Use this to highlight the most important piece of a long chunk of text. |
454 /// | 470 /// |
455 /// This is disabled under [withPrejudice] since all text is bold with | 471 /// This is disabled under [withPrejudice] since all text is bold with |
456 /// prejudice. | 472 /// prejudice. |
457 String bold(text) => withPrejudice ? text : "$_bold$text$_none"; | 473 String bold(text) => (withPrejudice || sparkle) ? "$text" : "$_bold$text$_none"; |
458 | 474 |
459 /// Wraps [text] in the ANSI escape codes to make it gray when on a platform | 475 /// Wraps [text] in the ANSI escape codes to make it gray when on a platform |
460 /// that supports that. | 476 /// that supports that. |
461 /// | 477 /// |
462 /// Use this for text that's less important than the text around it. | 478 /// Use this for text that's less important than the text around it. |
463 /// | 479 /// |
464 /// The gray marker also enables bold, so it needs to be handled specially with | 480 /// The gray marker also enables bold, so it needs to be handled specially with |
465 /// [withPrejudice] to avoid disabling bolding entirely. | 481 /// [withPrejudice] to avoid disabling bolding entirely. |
466 String gray(text) => | 482 String gray(text) { |
467 withPrejudice ? "$_gray$text$_noColor" : "$_gray$text$_none"; | 483 if (sparkle) return "$text"; |
| 484 if (withPrejudice) return "$_gray$text$_noColor"; |
| 485 return "$_gray$text$_none"; |
| 486 } |
468 | 487 |
469 /// Wraps [text] in the ANSI escape codes to color it cyan when on a platform | 488 /// Wraps [text] in the ANSI escape codes to color it cyan when on a platform |
470 /// that supports that. | 489 /// that supports that. |
471 /// | 490 /// |
472 /// Use this to highlight something interesting but neither good nor bad. | 491 /// Use this to highlight something interesting but neither good nor bad. |
473 String cyan(text) => "$_cyan$text$_noColor"; | 492 String cyan(text) => sparkle ? "$text" : "$_cyan$text$_noColor"; |
474 | 493 |
475 /// Wraps [text] in the ANSI escape codes to color it green when on a platform | 494 /// Wraps [text] in the ANSI escape codes to color it green when on a platform |
476 /// that supports that. | 495 /// that supports that. |
477 /// | 496 /// |
478 /// Use this to highlight something successful or otherwise positive. | 497 /// Use this to highlight something successful or otherwise positive. |
479 String green(text) => "$_green$text$_noColor"; | 498 String green(text) => sparkle ? "$text" : "$_green$text$_noColor"; |
480 | 499 |
481 /// Wraps [text] in the ANSI escape codes to color it magenta when on a | 500 /// Wraps [text] in the ANSI escape codes to color it magenta when on a |
482 /// platform that supports that. | 501 /// platform that supports that. |
483 /// | 502 /// |
484 /// Use this to highlight something risky that the user should be aware of but | 503 /// Use this to highlight something risky that the user should be aware of but |
485 /// may intend to do. | 504 /// may intend to do. |
486 String magenta(text) => "$_magenta$text$_noColor"; | 505 String magenta(text) => sparkle ? "$text" : "$_magenta$text$_noColor"; |
487 | 506 |
488 /// Wraps [text] in the ANSI escape codes to color it red when on a platform | 507 /// Wraps [text] in the ANSI escape codes to color it red when on a platform |
489 /// that supports that. | 508 /// that supports that. |
490 /// | 509 /// |
491 /// Use this to highlight unequivocal errors, problems, or failures. | 510 /// Use this to highlight unequivocal errors, problems, or failures. |
492 String red(text) => "$_red$text$_noColor"; | 511 String red(text) => sparkle ? "$text" : "$_red$text$_noColor"; |
493 | 512 |
494 /// Wraps [text] in the ANSI escape codes to color it yellow when on a platform | 513 /// Wraps [text] in the ANSI escape codes to color it yellow when on a platform |
495 /// that supports that. | 514 /// that supports that. |
496 /// | 515 /// |
497 /// Use this to highlight warnings, cautions or other things that are bad but | 516 /// Use this to highlight warnings, cautions or other things that are bad but |
498 /// do not prevent the user's goal from being reached. | 517 /// do not prevent the user's goal from being reached. |
499 String yellow(text) => "$_yellow$text$_noColor"; | 518 String yellow(text) => sparkle ? "$text" : "$_yellow$text$_noColor"; |
500 | 519 |
501 /// Log function that prints the message to stdout. | 520 /// Log function that prints the message to stdout. |
502 void _logToStdout(Entry entry) { | 521 void _logToStdout(Entry entry) { |
503 _logToStream(stdout, entry, showLabel: false); | 522 _logToStream(stdout, entry, showLabel: false); |
504 } | 523 } |
505 | 524 |
506 /// Log function that prints the message to stdout with the level name. | 525 /// Log function that prints the message to stdout with the level name. |
507 void _logToStdoutWithLabel(Entry entry) { | 526 void _logToStdoutWithLabel(Entry entry) { |
508 _logToStream(stdout, entry, showLabel: true); | 527 _logToStream(stdout, entry, showLabel: true); |
509 } | 528 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 message(_firstMessage); | 652 message(_firstMessage); |
634 } else { | 653 } else { |
635 message(_template.replaceAll("##", _count.toString())); | 654 message(_template.replaceAll("##", _count.toString())); |
636 } | 655 } |
637 } | 656 } |
638 | 657 |
639 void _initTimer() { | 658 void _initTimer() { |
640 _timer = new Timer(_window, end); | 659 _timer = new Timer(_window, end); |
641 } | 660 } |
642 } | 661 } |
OLD | NEW |