UNPKG

4.08 kBJavaScriptView Raw
1var util = require('util');
2
3var stream = require('stream-wrapper');
4var noansi = require('ansi-stripper');
5
6require('colors');
7
8var PROGRESS_BAR_LENGTH = 50;
9var TABLE_CELL_PADDING = 2;
10var OUTPUT_PADDING = 10;
11
12var bar = function(percent) {
13 percent = Math.min(percent, 100);
14
15 var bar = '';
16 var limit = Math.floor(percent / 100 * PROGRESS_BAR_LENGTH);
17 var i;
18
19 for(i = 0; i < limit; i++) {
20 bar += '=';
21 }
22 if(limit < PROGRESS_BAR_LENGTH) {
23 bar += '>';
24 limit++;
25 }
26 for(i = limit; i < PROGRESS_BAR_LENGTH; i++) {
27 bar += ' ';
28 }
29
30 return '[' + bar.bold.cyan + ']';
31};
32
33var table = function(table) {
34 var columnLengths = [];
35
36 var each = function(fn) {
37 for(var i = 0; i < table.length; i++) {
38 var row = table[i];
39
40 for(var j = 0; j < row.length; j++) {
41 fn(i, j, row[j]);
42 }
43 }
44 };
45 var padding = function(padding) {
46 var result = '';
47
48 for(var i = 0; i < padding; i++) {
49 result += ' ';
50 }
51
52 return result;
53 };
54 var length = function(obj) {
55 return noansi(obj.toString()).length;
56 };
57
58 each(function(i, j, value) {
59 columnLengths[j] = Math.max(columnLengths[j] || 0, length(value));
60 });
61
62 each(function(i, j, value) {
63 table[i][j] = value + padding(columnLengths[j] - length(value) + TABLE_CELL_PADDING);
64 });
65
66 return table.map(function(row) {
67 return row.join(padding(TABLE_CELL_PADDING * 2));
68 });
69};
70
71var time = function(time) {
72 var hours = Math.floor(time / 3600);
73 var minutes = Math.floor((time - (hours * 3600)) / 60);
74 var seconds = Math.floor(time - (hours * 3600) - (minutes * 60));
75
76 var pad = function(n) {
77 if(n < 10) {
78 return '0' + n;
79 }
80
81 return n;
82 };
83
84 return pad(hours) + 'h ' + pad(minutes) + 'm ' + pad(seconds) + 's';
85};
86
87var sign = function(number) {
88 if(!number) {
89 return ' 0';
90 }
91
92 return number < 0 ? number.toString() : ('+' + number);
93};
94
95var capture = function(delta) {
96 var current = Number.MIN_VALUE;
97
98 return function(v) {
99 if(Math.abs(current - v) > delta) {
100 current = v;
101 return v;
102 }
103
104 return current;
105 };
106};
107
108var progress = function(options) {
109 var output = [];
110 var eta = capture(30);
111 var speed = capture(10);
112
113 var outputProgress = function(output, count, total, progress) {
114 output.push('Progress: '.grey + bar(progress) + ' ' + count + '/' + total + ' ' + progress.toFixed(1) + '%');
115 output.push('Patch: '.grey + options.patch);
116 };
117
118 var outputDiff = function(output, diff) {
119 diff = Object.keys(diff || {}).map(function(key) {
120 return [
121 key,
122 sign(diff[key].added).green,
123 diff[key].updated.toString().yellow,
124 sign(-diff[key].removed).red
125 ];
126 });
127
128 diff = diff.length ? diff : [[ '(No changes)' ]];
129 diff.forEach(function(row) {
130 row.unshift('');
131 });
132
133 diff.unshift(['Diff: '.grey, '', 'added'.grey, 'updated'.grey, 'removed'.grey]);
134 Array.prototype.push.apply(output, table(diff));
135 };
136
137 var outputStats = function(output, modified, count, t, e, s) {
138 var summary = table([
139 ['Summary:'.grey, 'Time', time(t)],
140 ['', 'ETA', time(eta(e)), util.format('(speed %s)', Math.round(speed(s)))],
141 ['', 'Modified', modified, util.format('(rest %s)', count - modified)]
142 ]);
143
144 Array.prototype.push.apply(output, summary);
145 };
146
147 var logOutput = function(output) {
148 console.log(output.join('\n'));
149 };
150
151 outputProgress(output, 0, 0, options.total === 0 ? 100 : 0);
152 logOutput(output);
153
154 return stream.transform({ objectMode: true }, function(patch, enc, callback) {
155 var progress = patch.progress;
156
157 process.stdout.moveCursor(0, -output.length);
158 output = [];
159
160 outputProgress(output, progress.count, progress.total, progress.percentage);
161
162 output.push('');
163
164 outputStats(output, progress.modified, progress.count, progress.time, progress.eta, progress.speed);
165 outputDiff(output, progress.diff);
166
167 if(output.length > process.stdout.rows - OUTPUT_PADDING) {
168 output = output.slice(0, process.stdout.rows - OUTPUT_PADDING);
169 output.push(' ...');
170 }
171
172 logOutput(output);
173
174 callback(null, patch);
175 }, function(callback) {
176 console.log('\n DONE'.green);
177 callback();
178 });
179};
180
181module.exports = progress;