Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50660 views
1
/*
2
* cliff.js: CLI output formatting tools: "Your CLI Formatting Friend".
3
*
4
* (C) 2010, Nodejitsu Inc.
5
*
6
*/
7
8
var colors = require('colors'),
9
eyes = require('eyes'),
10
winston = require('winston');
11
12
var cliff = exports,
13
logger;
14
15
cliff.__defineGetter__('logger', function () {
16
delete cliff.logger;
17
return cliff.logger = logger;
18
});
19
20
cliff.__defineSetter__('logger', function (val) {
21
logger = val;
22
23
//
24
// Setup winston to use the `cli` formats
25
//
26
if (logger.cli) {
27
logger.cli();
28
}
29
});
30
31
//
32
// Set the default logger for cliff.
33
//
34
cliff.logger = new winston.Logger({
35
transports: [new winston.transports.Console()]
36
});
37
38
//
39
// Expose a default `eyes` inspector.
40
//
41
cliff.inspector = eyes.inspector;
42
cliff.inspect = eyes.inspector({ stream: null,
43
styles: { // Styles applied to stdout
44
all: null, // Overall style applied to everything
45
label: 'underline', // Inspection labels, like 'array' in `array: [1, 2, 3]`
46
other: 'inverted', // Objects which don't have a literal representation, such as functions
47
key: 'grey', // The keys in object literals, like 'a' in `{a: 1}`
48
special: 'grey', // null, undefined...
49
number: 'blue', // 0, 1, 2...
50
bool: 'magenta', // true false
51
regexp: 'green' // /\d+/
52
}
53
});
54
55
//
56
// ### function extractFrom (obj, properties)
57
// #### @obj {Object} Object to extract properties from.
58
// #### @properties {Array} List of properties to output.
59
// Creates an array representing the values for `properties` in `obj`.
60
//
61
cliff.extractFrom = function (obj, properties) {
62
return properties.map(function (p) {
63
return obj[p];
64
});
65
};
66
67
//
68
// ### function columnMajor (rows)
69
// #### @rows {ArrayxArray} Row-major Matrix to transpose
70
// Transposes the row-major Matrix, represented as an array of rows,
71
// into column major form (i.e. an array of columns).
72
//
73
cliff.columnMajor = function (rows) {
74
var columns = [];
75
76
rows.forEach(function (row) {
77
for (var i = 0; i < row.length; i += 1) {
78
if (!columns[i]) {
79
columns[i] = [];
80
}
81
82
columns[i].push(row[i]);
83
}
84
});
85
86
return columns;
87
};
88
89
//
90
// ### arrayLengths (arrs)
91
// #### @arrs {ArrayxArray} Arrays to calculate lengths for
92
// Creates an array with values each representing the length
93
// of an array in the set provided.
94
//
95
cliff.arrayLengths = function (arrs) {
96
var i, lengths = [];
97
for (i = 0; i < arrs.length; i += 1) {
98
lengths.push(longestElement(arrs[i].map(cliff.stringifyLiteral)));
99
}
100
return lengths;
101
};
102
103
//
104
// ### function stringifyRows (rows, colors)
105
// #### @rows {ArrayxArray} Matrix of properties to output in row major form
106
// #### @colors {Array} Set of colors to use for the headers
107
// Outputs the specified `rows` as fixed-width columns, adding
108
// colorized headers if `colors` are supplied.
109
//
110
cliff.stringifyRows = function (rows, colors) {
111
var lengths, columns, output = [], headers;
112
113
columns = cliff.columnMajor(rows);
114
lengths = cliff.arrayLengths(columns);
115
116
function stringifyRow(row, colorize) {
117
var rowtext = '', padding, item, i, length;
118
for (i = 0; i < row.length; i += 1) {
119
item = cliff.stringifyLiteral(row[i]);
120
item = colorize ? item[colors[i]] : item;
121
length = realLength(item);
122
padding = length < lengths[i] ? lengths[i] - length + 2 : 2;
123
rowtext += item + new Array(padding).join(' ');
124
}
125
126
output.push(rowtext);
127
}
128
129
// If we were passed colors, then assume the first row
130
// is the headers for the rows
131
if (colors) {
132
headers = rows.splice(0, 1)[0];
133
stringifyRow(headers, true);
134
}
135
136
rows.forEach(function (row) {
137
stringifyRow(row, false);
138
});
139
140
return output.join('\n');
141
};
142
143
//
144
// ### function rowifyObjects (objs, properties, colors)
145
// #### @objs {Array} List of objects to create output for
146
// #### @properties {Array} List of properties to output
147
// #### @colors {Array} Set of colors to use for the headers
148
// Extracts the lists of `properties` from the specified `objs`
149
// and formats them according to `cliff.stringifyRows`.
150
//
151
cliff.stringifyObjectRows = cliff.rowifyObjects = function (objs, properties, colors) {
152
var rows = [properties].concat(objs.map(function (obj) {
153
return cliff.extractFrom(obj, properties);
154
}));
155
156
return cliff.stringifyRows(rows, colors);
157
};
158
159
//
160
// ### function putRows (level, rows, colors)
161
// #### @level {String} Log-level to use
162
// #### @rows {Array} Array of rows to log at the specified level
163
// #### @colors {Array} Set of colors to use for the specified row(s) headers.
164
// Logs the stringified table result from `rows` at the appropriate `level` using
165
// `cliff.logger`. If `colors` are supplied then use those when stringifying `rows`.
166
//
167
cliff.putRows = function (level, rows, colors) {
168
cliff.stringifyRows(rows, colors).split('\n').forEach(function (str) {
169
logger.log(level, str);
170
});
171
};
172
173
//
174
// ### function putObjectRows (level, rows, colors)
175
// #### @level {String} Log-level to use
176
// #### @objs {Array} List of objects to create output for
177
// #### @properties {Array} List of properties to output
178
// #### @colors {Array} Set of colors to use for the headers
179
// Logs the stringified table result from `objs` at the appropriate `level` using
180
// `cliff.logger`. If `colors` are supplied then use those when stringifying `objs`.
181
//
182
cliff.putObjectRows = function (level, objs, properties, colors) {
183
cliff.rowifyObjects(objs, properties, colors).split('\n').forEach(function (str) {
184
logger.log(level, str);
185
});
186
};
187
188
//
189
// ### function putObject (obj, [rewriters, padding])
190
// #### @obj {Object} Object to log to the command line
191
// #### @rewriters {Object} **Optional** Set of methods to rewrite certain object keys
192
// #### @padding {Number} **Optional** Length of padding to put around the output.
193
// Inspects the object `obj` on the command line rewriting any properties which match
194
// keys in `rewriters` if any. Adds additional `padding` if supplied.
195
//
196
cliff.putObject = function (/*obj, [rewriters, padding] */) {
197
var args = Array.prototype.slice.call(arguments),
198
obj = args.shift(),
199
padding = typeof args[args.length - 1] === 'number' && args.pop(),
200
rewriters = typeof args[args.length -1] === 'object' && args.pop(),
201
keys = Object.keys(obj).sort(),
202
sorted = {},
203
matchers = {},
204
inspected;
205
206
padding = padding || 0;
207
rewriters = rewriters || {};
208
209
function pad () {
210
for (var i = 0; i < padding / 2; i++) {
211
logger.data('');
212
}
213
}
214
215
keys.forEach(function (key) {
216
sorted[key] = obj[key];
217
});
218
219
inspected = cliff.inspect(sorted);
220
221
Object.keys(rewriters).forEach(function (key) {
222
matchers[key] = new RegExp(key);
223
});
224
225
pad();
226
inspected.split('\n').forEach(function (line) {
227
Object.keys(rewriters).forEach(function (key) {
228
if (matchers[key].test(line)) {
229
line = rewriters[key](line);
230
}
231
});
232
logger.data(line);
233
});
234
pad();
235
};
236
237
cliff.stringifyLiteral = function stringifyLiteral (literal) {
238
switch (cliff.typeOf(literal)) {
239
case 'number' : return literal + '';
240
case 'null' : return 'null';
241
case 'undefined': return 'undefined';
242
case 'boolean' : return literal + '';
243
default : return literal;
244
}
245
};
246
247
cliff.typeOf = function typeOf(value) {
248
var s = typeof(value),
249
types = [Object, Array, String, RegExp, Number, Function, Boolean, Date];
250
251
if (s === 'object' || s === 'function') {
252
if (value) {
253
types.forEach(function (t) {
254
if (value instanceof t) {
255
s = t.name.toLowerCase();
256
}
257
});
258
} else {
259
s = 'null';
260
}
261
}
262
263
return s;
264
};
265
266
function realLength(str) {
267
return ("" + str).replace(/\u001b\[\d+m/g,'').length;
268
}
269
270
function longestElement(a) {
271
var l = 0;
272
for (var i = 0; i < a.length; i++) {
273
var new_l = realLength(a[i]);
274
if (l < new_l) {
275
l = new_l;
276
}
277
}
278
279
return l;
280
}
281
282