123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- /*
- * grunt
- * http://gruntjs.com/
- *
- * Copyright (c) 2014 "Cowboy" Ben Alman
- * Licensed under the MIT license.
- * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
- */
- 'use strict';
- // Requiring this here modifies the String prototype!
- require('colors');
- // The upcoming lodash 2.5+ should remove the need for underscore.string.
- var _ = require('lodash');
- _.str = require('underscore.string');
- _.mixin(_.str.exports());
- // TODO: ADD CHALK
- // Static methods.
- // Pretty-format a word list.
- exports.wordlist = function(arr, options) {
- options = _.defaults(options || {}, {
- separator: ', ',
- color: 'cyan'
- });
- return arr.map(function(item) {
- return options.color ? String(item)[options.color] : 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');
- };
|