OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library pub.progress; | |
6 | |
7 import 'dart:async'; | |
8 import 'dart:io'; | |
9 | |
10 import 'log.dart' as log; | |
11 import 'utils.dart'; | |
12 | |
13 /// A live-updating progress indicator for long-running log entries. | |
14 class Progress { | |
15 /// The timer used to write "..." during a progress log. | |
16 Timer _timer; | |
17 | |
18 /// The [Stopwatch] used to track how long a progress log has been running. | |
19 final _stopwatch = new Stopwatch(); | |
20 | |
21 /// The progress message as it's being incrementally appended. | |
22 /// | |
23 /// When the progress is done, a single entry will be added to the log for it. | |
24 final String _message; | |
25 | |
26 /// Gets the current progress time as a parenthesized, formatted string. | |
27 String get _time => "(${niceDuration(_stopwatch.elapsed)})"; | |
28 | |
29 /// Creates a new progress indicator. | |
30 /// | |
31 /// If [fine] is passed, this will log progress messages on [log.Level.FINE] | |
32 /// as opposed to [log.Level.MESSAGE]. | |
33 Progress(this._message, {bool fine: false}) { | |
34 _stopwatch.start(); | |
35 | |
36 var level = fine ? log.Level.FINE : log.Level.MESSAGE; | |
37 | |
38 // The animation is only shown when it would be meaningful to a human. | |
39 // That means we're writing a visible message to a TTY at normal log levels | |
40 // with non-JSON output. | |
41 if (stdioType(stdout) != StdioType.TERMINAL || | |
42 !log.verbosity.isLevelVisible(level) || | |
43 log.json.enabled || fine || | |
44 log.verbosity.isLevelVisible(log.Level.FINE)) { | |
45 // Not animating, so just log the start and wait until the task is | |
46 // completed. | |
47 log.write(level, "$_message..."); | |
48 return; | |
49 } | |
50 | |
51 _timer = new Timer.periodic(new Duration(milliseconds: 100), (_) { | |
52 _update(); | |
53 }); | |
54 | |
55 _update(); | |
56 } | |
57 | |
58 /// Stops the progress indicator. | |
59 void stop() { | |
60 _stopwatch.stop(); | |
61 | |
62 // Always log the final time as [log.fine] because for the most part normal | |
63 // users don't care about the precise time information beyond what's shown | |
64 // in the animation. | |
65 log.fine("$_message finished $_time."); | |
66 | |
67 // If we were animating, print one final update to show the user the final | |
68 // time. | |
69 if (_timer == null) return; | |
70 _timer.cancel(); | |
71 _timer = null; | |
72 _update(); | |
73 stdout.writeln(); | |
74 } | |
75 | |
76 /// Stop animating the progress indicator. | |
77 /// | |
78 /// This will continue running the stopwatch so that the full time can be | |
79 /// logged in [stop]. | |
80 void stopAnimating() { | |
81 if (_timer == null) return; | |
82 | |
83 // Print a final message without a time indicator so that we don't leave a | |
84 // misleading half-complete time indicator on the console. | |
85 stdout.writeln(log.format("\r$_message...")); | |
86 _timer.cancel(); | |
87 _timer = null; | |
88 } | |
89 | |
90 /// Refreshes the progress line. | |
91 void _update() { | |
92 if (log.isMuted) return; | |
93 | |
94 stdout.write(log.format("\r$_message... ")); | |
95 | |
96 // Show the time only once it gets noticeably long. | |
97 if (_stopwatch.elapsed.inSeconds > 0) stdout.write("${log.gray(_time)} "); | |
98 } | |
99 } | |
OLD | NEW |