UNPKG

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