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