Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1024)

Side by Side Diff: packages/cli_util/lib/cli_logging.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « packages/cli_util/example/main.dart ('k') | packages/cli_util/lib/cli_util.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
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.
4
5 /// This library contains functionality to help command-line utilities to easily
6 /// create aesthetic output.
7 library cli_logging;
8
9 import 'dart:async';
10 import 'dart:io' as io;
11
12 /// A small utility class to make it easier to work with common ANSI escape
13 /// sequences.
14 class Ansi {
15 /// Return whether the current stdout terminal supports ANSI escape sequences.
16 static bool get terminalSupportsAnsi {
17 return io.stdout.supportsAnsiEscapes &&
18 io.stdioType(io.stdout) == io.StdioType.TERMINAL;
19 }
20
21 final bool useAnsi;
22
23 Ansi(this.useAnsi);
24
25 String get cyan => _code('\u001b[36m');
26 String get green => _code('\u001b[32m');
27 String get magenta => _code('\u001b[35m');
28 String get red => _code('\u001b[31m');
29 String get yellow => _code('\u001b[33m');
30 String get blue => _code('\u001b[34m');
31 String get gray => _code('\u001b[1;30m');
32 String get noColor => _code('\u001b[39m');
33
34 String get none => _code('\u001b[0m');
35
36 String get bold => _code('\u001b[1m');
37
38 String get backspace => '\b';
39
40 String get bullet => io.stdout.supportsAnsiEscapes ? '•' : '-';
41
42 /// Display [message] in an emphasized format.
43 String emphasized(String message) => '$bold$message$none';
44
45 /// Display [message] in an subtle (gray) format.
46 String subtle(String message) => '$gray$message$none';
47
48 /// Display [message] in an error (red) format.
49 String error(String message) => '$red$message$none';
50
51 String _code(String ansiCode) => useAnsi ? ansiCode : '';
52 }
53
54 /// An abstract representation of a [Logger] - used to pretty print errors,
55 /// standard status messages, trace level output, and indeterminate progress.
56 abstract class Logger {
57 /// Create a normal [Logger]; this logger will not display trace level output.
58 factory Logger.standard({Ansi ansi}) => new _StandardLogger(ansi: ansi);
59
60 /// Create a [Logger] that will display trace level output.
61 factory Logger.verbose({Ansi ansi}) => new _VerboseLogger(ansi: ansi);
62
63 Ansi get ansi;
64
65 bool get isVerbose;
66
67 /// Print an error message.
68 void stderr(String message);
69
70 /// Print a standard status message.
71 void stdout(String message);
72
73 /// Print trace output.
74 void trace(String message);
75
76 /// Start an indeterminate progress display.
77 Progress progress(String message);
78 void _progressFinished(Progress progress);
79
80 /// Flush any un-written output.
81 void flush();
82 }
83
84 /// A handle to an indeterminate progress display.
85 abstract class Progress {
86 final String message;
87 final Stopwatch _stopwatch;
88
89 Progress._(this.message) : _stopwatch = new Stopwatch()..start();
90
91 Duration get elapsed => _stopwatch.elapsed;
92
93 /// Finish the indeterminate progress display.
94 void finish({String message, bool showTiming});
95
96 /// Cancel the indeterminate progress display.
97 void cancel();
98 }
99
100 class _StandardLogger implements Logger {
101 Ansi ansi;
102
103 _StandardLogger({this.ansi}) {
104 ansi ??= new Ansi(Ansi.terminalSupportsAnsi);
105 }
106
107 bool get isVerbose => false;
108
109 Progress _currentProgress;
110
111 void stderr(String message) {
112 io.stderr.writeln(message);
113 _currentProgress?.cancel();
114 _currentProgress = null;
115 }
116
117 void stdout(String message) {
118 print(message);
119 _currentProgress?.cancel();
120 _currentProgress = null;
121 }
122
123 void trace(String message) {}
124
125 Progress progress(String message) {
126 _currentProgress?.cancel();
127 _currentProgress = null;
128
129 Progress progress = ansi.useAnsi
130 ? new _AnsiProgress(this, ansi, message)
131 : new _SimpleProgress(this, message);
132 _currentProgress = progress;
133 return progress;
134 }
135
136 void _progressFinished(Progress progress) {
137 if (_currentProgress == progress) {
138 _currentProgress = null;
139 }
140 }
141
142 void flush() {}
143 }
144
145 class _SimpleProgress extends Progress {
146 final Logger logger;
147
148 _SimpleProgress(this.logger, String message) : super._(message) {
149 logger.stdout('$message...');
150 }
151
152 @override
153 void cancel() {
154 logger._progressFinished(this);
155 }
156
157 @override
158 void finish({String message, bool showTiming}) {
159 logger._progressFinished(this);
160 }
161 }
162
163 class _AnsiProgress extends Progress {
164 static const List<String> kAnimationItems = const ['/', '-', '\\', '|'];
165
166 final Logger logger;
167 final Ansi ansi;
168
169 int _index = 0;
170 Timer _timer;
171
172 _AnsiProgress(this.logger, this.ansi, String message) : super._(message) {
173 io.stdout.write('${message}... '.padRight(40));
174
175 _timer = new Timer.periodic(new Duration(milliseconds: 80), (t) {
176 _index++;
177 _updateDisplay();
178 });
179
180 _updateDisplay();
181 }
182
183 @override
184 void cancel() {
185 if (_timer.isActive) {
186 _timer.cancel();
187 _updateDisplay(cancelled: true);
188 logger._progressFinished(this);
189 }
190 }
191
192 @override
193 void finish({String message, bool showTiming: false}) {
194 if (_timer.isActive) {
195 _timer.cancel();
196 _updateDisplay(isFinal: true, message: message, showTiming: showTiming);
197 logger._progressFinished(this);
198 }
199 }
200
201 void _updateDisplay(
202 {bool isFinal: false,
203 bool cancelled: false,
204 String message,
205 bool showTiming: false}) {
206 String char = kAnimationItems[_index % kAnimationItems.length];
207 if (isFinal || cancelled) {
208 char = '';
209 }
210 io.stdout.write('${ansi.backspace}${char}');
211 if (isFinal || cancelled) {
212 if (message != null) {
213 io.stdout.write(message.isEmpty ? ' ' : message);
214 } else if (showTiming) {
215 String time = (elapsed.inMilliseconds / 1000.0).toStringAsFixed(1);
216 io.stdout.write('${time}s');
217 } else {
218 io.stdout.write(' ');
219 }
220 io.stdout.writeln();
221 }
222 }
223 }
224
225 class _VerboseLogger implements Logger {
226 Ansi ansi;
227 Stopwatch _timer;
228
229 String _previousErr;
230 String _previousMsg;
231
232 _VerboseLogger({this.ansi}) {
233 ansi ??= new Ansi(Ansi.terminalSupportsAnsi);
234 _timer = new Stopwatch()..start();
235 }
236
237 bool get isVerbose => true;
238
239 void stderr(String message) {
240 flush();
241 _previousErr = '${ansi.red}$message${ansi.none}';
242 }
243
244 void stdout(String message) {
245 flush();
246 _previousMsg = message;
247 }
248
249 void trace(String message) {
250 flush();
251 _previousMsg = '${ansi.gray}$message${ansi.none}';
252 }
253
254 Progress progress(String message) => new _SimpleProgress(this, message);
255
256 void _progressFinished(Progress progress) {}
257
258 void flush() {
259 if (_previousErr != null) {
260 io.stderr.writeln('${_createTag()} $_previousErr');
261 _previousErr = null;
262 } else if (_previousMsg != null) {
263 io.stdout.writeln('${_createTag()} $_previousMsg');
264 _previousMsg = null;
265 }
266 }
267
268 String _createTag() {
269 int millis = _timer.elapsedMilliseconds;
270 _timer.reset();
271 return '[${millis.toString().padLeft(4)} ms]';
272 }
273 }
OLDNEW
« no previous file with comments | « packages/cli_util/example/main.dart ('k') | packages/cli_util/lib/cli_util.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698