| Leo Repp | 58b9f11 | 2021-11-22 11:57:47 +0100 | [diff] [blame^] | 1 | /* |
| 2 | * grunt |
| 3 | * http://gruntjs.com/ |
| 4 | * |
| 5 | * Copyright (c) 2016 "Cowboy" Ben Alman |
| 6 | * Licensed under the MIT license. |
| 7 | * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT |
| 8 | */ |
| 9 | |
| 10 | 'use strict'; |
| 11 | |
| 12 | var chalk = require('chalk'); |
| 13 | var _ = require('lodash'); |
| 14 | |
| 15 | // Pretty-format a word list. |
| 16 | exports.wordlist = function(arr, options) { |
| 17 | options = _.defaults(options || {}, { |
| 18 | separator: ', ', |
| 19 | color: 'cyan' |
| 20 | }); |
| 21 | return arr.map(function(item) { |
| 22 | return options.color ? chalk[options.color](item) : item; |
| 23 | }).join(options.separator); |
| 24 | }; |
| 25 | |
| 26 | // Return a string, uncolored (suitable for testing .length, etc). |
| 27 | exports.uncolor = function(str) { |
| 28 | return str.replace(/\x1B\[\d+m/g, ''); |
| 29 | }; |
| 30 | |
| 31 | // Word-wrap text to a given width, permitting ANSI color codes. |
| 32 | exports.wraptext = function(width, text) { |
| 33 | // notes to self: |
| 34 | // grab 1st character or ansi code from string |
| 35 | // if ansi code, add to array and save for later, strip from front of string |
| 36 | // if character, add to array and increment counter, strip from front of string |
| 37 | // if width + 1 is reached and current character isn't space: |
| 38 | // slice off everything after last space in array and prepend it to string |
| 39 | // etc |
| 40 | |
| 41 | // This result array will be joined on \n. |
| 42 | var result = []; |
| 43 | var matches, color, tmp; |
| 44 | var captured = []; |
| 45 | var charlen = 0; |
| 46 | |
| 47 | while (matches = text.match(/(?:(\x1B\[\d+m)|\n|(.))([\s\S]*)/)) { |
| 48 | // Updated text to be everything not matched. |
| 49 | text = matches[3]; |
| 50 | |
| 51 | // Matched a color code? |
| 52 | if (matches[1]) { |
| 53 | // Save last captured color code for later use. |
| 54 | color = matches[1]; |
| 55 | // Capture color code. |
| 56 | captured.push(matches[1]); |
| 57 | continue; |
| 58 | |
| 59 | // Matched a non-newline character? |
| 60 | } else if (matches[2]) { |
| 61 | // If this is the first character and a previous color code was set, push |
| 62 | // that onto the captured array first. |
| 63 | if (charlen === 0 && color) { captured.push(color); } |
| 64 | // Push the matched character. |
| 65 | captured.push(matches[2]); |
| 66 | // Increment the current charlen. |
| 67 | charlen++; |
| 68 | // If not yet at the width limit or a space was matched, continue. |
| 69 | if (charlen <= width || matches[2] === ' ') { continue; } |
| 70 | // The current charlen exceeds the width and a space wasn't matched. |
| 71 | // "Roll everything back" until the last space character. |
| 72 | tmp = captured.lastIndexOf(' '); |
| 73 | text = captured.slice(tmp === -1 ? tmp : tmp + 1).join('') + text; |
| 74 | captured = captured.slice(0, tmp); |
| 75 | } |
| 76 | |
| 77 | // The limit has been reached. Push captured string onto result array. |
| 78 | result.push(captured.join('')); |
| 79 | |
| 80 | // Reset captured array and charlen. |
| 81 | captured = []; |
| 82 | charlen = 0; |
| 83 | } |
| 84 | |
| 85 | result.push(captured.join('')); |
| 86 | return result.join('\n'); |
| 87 | }; |
| 88 | |
| 89 | // Format output into columns, wrapping words as-necessary. |
| 90 | exports.table = function(widths, texts) { |
| 91 | var rows = []; |
| 92 | widths.forEach(function(width, i) { |
| 93 | var lines = this.wraptext(width, texts[i]).split('\n'); |
| 94 | lines.forEach(function(line, j) { |
| 95 | var row = rows[j]; |
| 96 | if (!row) { row = rows[j] = []; } |
| 97 | row[i] = line; |
| 98 | }); |
| 99 | }, this); |
| 100 | |
| 101 | var lines = []; |
| 102 | rows.forEach(function(row) { |
| 103 | var txt = ''; |
| 104 | var column; |
| 105 | for (var i = 0; i < row.length; i++) { |
| 106 | column = row[i] || ''; |
| 107 | txt += column; |
| 108 | var diff = widths[i] - this.uncolor(column).length; |
| 109 | if (diff > 0) { txt += _.repeat(' ', diff); } |
| 110 | } |
| 111 | lines.push(txt); |
| 112 | }, this); |
| 113 | |
| 114 | return lines.join('\n'); |
| 115 | }; |