116 lines
3.4 KiB
JavaScript
116 lines
3.4 KiB
JavaScript
|
/*
|
||
|
* grunt
|
||
|
* http://gruntjs.com/
|
||
|
*
|
||
|
* Copyright (c) 2016 "Cowboy" Ben Alman
|
||
|
* Licensed under the MIT license.
|
||
|
* https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
|
||
|
*/
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
var chalk = require('chalk');
|
||
|
var _ = require('lodash');
|
||
|
|
||
|
// Pretty-format a word list.
|
||
|
exports.wordlist = function(arr, options) {
|
||
|
options = _.defaults(options || {}, {
|
||
|
separator: ', ',
|
||
|
color: 'cyan'
|
||
|
});
|
||
|
return arr.map(function(item) {
|
||
|
return options.color ? chalk[options.color](item) : item;
|
||
|
}).join(options.separator);
|
||
|
};
|
||
|
|
||
|
// Return a string, uncolored (suitable for testing .length, etc).
|
||
|
exports.uncolor = function(str) {
|
||
|
return str.replace(/\x1B\[\d+m/g, '');
|
||
|
};
|
||
|
|
||
|
// Word-wrap text to a given width, permitting ANSI color codes.
|
||
|
exports.wraptext = function(width, text) {
|
||
|
// notes to self:
|
||
|
// grab 1st character or ansi code from string
|
||
|
// if ansi code, add to array and save for later, strip from front of string
|
||
|
// if character, add to array and increment counter, strip from front of string
|
||
|
// if width + 1 is reached and current character isn't space:
|
||
|
// slice off everything after last space in array and prepend it to string
|
||
|
// etc
|
||
|
|
||
|
// This result array will be joined on \n.
|
||
|
var result = [];
|
||
|
var matches, color, tmp;
|
||
|
var captured = [];
|
||
|
var charlen = 0;
|
||
|
|
||
|
while (matches = text.match(/(?:(\x1B\[\d+m)|\n|(.))([\s\S]*)/)) {
|
||
|
// Updated text to be everything not matched.
|
||
|
text = matches[3];
|
||
|
|
||
|
// Matched a color code?
|
||
|
if (matches[1]) {
|
||
|
// Save last captured color code for later use.
|
||
|
color = matches[1];
|
||
|
// Capture color code.
|
||
|
captured.push(matches[1]);
|
||
|
continue;
|
||
|
|
||
|
// Matched a non-newline character?
|
||
|
} else if (matches[2]) {
|
||
|
// If this is the first character and a previous color code was set, push
|
||
|
// that onto the captured array first.
|
||
|
if (charlen === 0 && color) { captured.push(color); }
|
||
|
// Push the matched character.
|
||
|
captured.push(matches[2]);
|
||
|
// Increment the current charlen.
|
||
|
charlen++;
|
||
|
// If not yet at the width limit or a space was matched, continue.
|
||
|
if (charlen <= width || matches[2] === ' ') { continue; }
|
||
|
// The current charlen exceeds the width and a space wasn't matched.
|
||
|
// "Roll everything back" until the last space character.
|
||
|
tmp = captured.lastIndexOf(' ');
|
||
|
text = captured.slice(tmp === -1 ? tmp : tmp + 1).join('') + text;
|
||
|
captured = captured.slice(0, tmp);
|
||
|
}
|
||
|
|
||
|
// The limit has been reached. Push captured string onto result array.
|
||
|
result.push(captured.join(''));
|
||
|
|
||
|
// Reset captured array and charlen.
|
||
|
captured = [];
|
||
|
charlen = 0;
|
||
|
}
|
||
|
|
||
|
result.push(captured.join(''));
|
||
|
return result.join('\n');
|
||
|
};
|
||
|
|
||
|
// Format output into columns, wrapping words as-necessary.
|
||
|
exports.table = function(widths, texts) {
|
||
|
var rows = [];
|
||
|
widths.forEach(function(width, i) {
|
||
|
var lines = this.wraptext(width, texts[i]).split('\n');
|
||
|
lines.forEach(function(line, j) {
|
||
|
var row = rows[j];
|
||
|
if (!row) { row = rows[j] = []; }
|
||
|
row[i] = line;
|
||
|
});
|
||
|
}, this);
|
||
|
|
||
|
var lines = [];
|
||
|
rows.forEach(function(row) {
|
||
|
var txt = '';
|
||
|
var column;
|
||
|
for (var i = 0; i < row.length; i++) {
|
||
|
column = row[i] || '';
|
||
|
txt += column;
|
||
|
var diff = widths[i] - this.uncolor(column).length;
|
||
|
if (diff > 0) { txt += _.repeat(' ', diff); }
|
||
|
}
|
||
|
lines.push(txt);
|
||
|
}, this);
|
||
|
|
||
|
return lines.join('\n');
|
||
|
};
|