/* * 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'); };