From 832290a0d425aa027c279a4a96a70550a2fdfff2 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 26 Nov 2019 00:32:16 +0100 Subject: util: add more predefined color codes to inspect.colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds most commonly used ANSI color codes to `util.inspect.colors`. PR-URL: https://github.com/nodejs/node/pull/30659 Reviewed-By: James M Snell Reviewed-By: Michaƫl Zasso Reviewed-By: Anto Aravinth --- doc/api/util.md | 67 +++++++++++++++++++++++++++-- lib/internal/util/inspect.js | 86 +++++++++++++++++++++++++++++++++----- test/parallel/test-util-inspect.js | 28 +++++++++++++ 3 files changed, 166 insertions(+), 15 deletions(-) diff --git a/doc/api/util.md b/doc/api/util.md index ac23f138ad..88e2f34b7c 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -678,13 +678,72 @@ The default styles and associated colors are: * `symbol`: `green` * `undefined`: `grey` -The predefined color codes are: `white`, `grey`, `black`, `blue`, `cyan`, -`green`, `magenta`, `red` and `yellow`. There are also `bold`, `italic`, -`underline` and `inverse` codes. - Color styling uses ANSI control codes that may not be supported on all terminals. To verify color support use [`tty.hasColors()`][]. +Predefined control codes are listed below (grouped as "Modifiers", "Foreground +colors", and "Background colors"). + +#### Modifiers + +Modifier support varies throughout different terminals. They will mostly be +ignored, if not supported. + +* `reset` - Resets all (color) modifiers to their defaults +* **bold** - Make text bold +* _italic_ - Make text italic +* underline - Make text underlined +* ~~strikethrough~~ - Puts a horizontal line through the center of the text + (Alias: `strikeThrough`, `crossedout`, `crossedOut`) +* `hidden` - Prints the text, but makes it invisible (Alias: conceal) +* dim - Decreased color intensity (Alias: + `faint`) +* overlined - Make text overlined +* blink - Hides and shows the text in an interval +* inverse - Swap foreground and + background colors (Alias: `swapcolors`, `swapColors`) +* doubleunderline - Make text + double underlined (Alias: `doubleUnderline`) +* framed - Draw a frame around the text + +#### Foreground colors + +* `black` +* `red` +* `green` +* `yellow` +* `blue` +* `magenta` +* `cyan` +* `white` +* `gray` (alias: `grey`, `blackBright`) +* `redBright` +* `greenBright` +* `yellowBright` +* `blueBright` +* `magentaBright` +* `cyanBright` +* `whiteBright` + +#### Background colors + +* `bgBlack` +* `bgRed` +* `bgGreen` +* `bgYellow` +* `bgBlue` +* `bgMagenta` +* `bgCyan` +* `bgWhite` +* `bgGray` (alias: `bgGrey`, `bgBlackBright`) +* `bgRedBright` +* `bgGreenBright` +* `bgYellowBright` +* `bgBlueBright` +* `bgMagentaBright` +* `bgCyanBright` +* `bgWhiteBright` + ### Custom inspection functions on Objects diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 3664c15484..7005911621 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -269,23 +269,86 @@ ObjectDefineProperty(inspect, 'defaultOptions', { } }); -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +// Set Graphics Rendition http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +// Each color consists of an array with the color code as first entry and the +// reset code as second entry. +const defaultFG = 39; +const defaultBG = 49; inspect.colors = ObjectAssign(ObjectCreate(null), { + reset: [0, 0], bold: [1, 22], + dim: [2, 22], // Alias: faint italic: [3, 23], underline: [4, 24], - inverse: [7, 27], - white: [37, 39], - grey: [90, 39], - black: [30, 39], - blue: [34, 39], - cyan: [36, 39], - green: [32, 39], - magenta: [35, 39], - red: [31, 39], - yellow: [33, 39] + blink: [5, 25], + // Swap forground and background colors + inverse: [7, 27], // Alias: swapcolors, swapColors + hidden: [8, 28], // Alias: conceal + strikethrough: [9, 29], // Alias: strikeThrough, crossedout, crossedOut + doubleunderline: [21, 24], // Alias: doubleUnderline + black: [30, defaultFG], + red: [31, defaultFG], + green: [32, defaultFG], + yellow: [33, defaultFG], + blue: [34, defaultFG], + magenta: [35, defaultFG], + cyan: [36, defaultFG], + white: [37, defaultFG], + bgBlack: [40, defaultBG], + bgRed: [41, defaultBG], + bgGreen: [42, defaultBG], + bgYellow: [43, defaultBG], + bgBlue: [44, defaultBG], + bgMagenta: [45, defaultBG], + bgCyan: [46, defaultBG], + bgWhite: [47, defaultBG], + framed: [51, 54], + overlined: [53, 55], + gray: [90, defaultFG], // Alias: grey, blackBright + redBright: [91, defaultFG], + greenBright: [92, defaultFG], + yellowBright: [93, defaultFG], + blueBright: [94, defaultFG], + magentaBright: [95, defaultFG], + cyanBright: [96, defaultFG], + whiteBright: [97, defaultFG], + bgGray: [100, defaultBG], // Alias: bgGrey, bgBlackBright + bgRedBright: [101, defaultBG], + bgGreenBright: [102, defaultBG], + bgYellowBright: [103, defaultBG], + bgBlueBright: [104, defaultBG], + bgMagentaBright: [105, defaultBG], + bgCyanBright: [106, defaultBG], + bgWhiteBright: [107, defaultBG], }); +function defineColorAlias(target, alias) { + ObjectDefineProperty(inspect.colors, alias, { + get() { + return this[target]; + }, + set(value) { + this[target] = value; + }, + configurable: true, + enumerable: false + }); +} + +defineColorAlias('gray', 'grey'); +defineColorAlias('gray', 'blackBright'); +defineColorAlias('bgGray', 'bgGrey'); +defineColorAlias('bgGray', 'bgBlackBright'); +defineColorAlias('dim', 'faint'); +defineColorAlias('strikethrough', 'crossedout'); +defineColorAlias('strikethrough', 'strikeThrough'); +defineColorAlias('strikethrough', 'crossedOut'); +defineColorAlias('hidden', 'conceal'); +defineColorAlias('inverse', 'swapColors'); +defineColorAlias('inverse', 'swapcolors'); +defineColorAlias('doubleunderline', 'doubleUnderline'); + +// TODO(BridgeAR): Add function style support for more complex styles. // Don't use 'blue' not visible on cmd.exe inspect.styles = ObjectAssign(ObjectCreate(null), { special: 'cyan', @@ -298,6 +361,7 @@ inspect.styles = ObjectAssign(ObjectCreate(null), { symbol: 'green', date: 'magenta', // "name": intentionally not styling + // TODO(BridgeAR): Highlight regular expressions properly. regexp: 'red', module: 'underline' }); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 0d905b1e72..3f4a3a8a15 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -2076,6 +2076,34 @@ assert.strictEqual(inspect(new BigUint64Array([0n])), 'BigUint64Array [ 0n ]'); `\u001b[${string[0]}m'Oh no!'\u001b[${string[1]}m }` ); rejection.catch(() => {}); + + // Verify that aliases do not show up as key while checking `inspect.colors`. + const colors = Object.keys(inspect.colors); + const aliases = Object.getOwnPropertyNames(inspect.colors) + .filter((c) => !colors.includes(c)); + assert(!colors.includes('grey')); + assert(colors.includes('gray')); + // Verify that all aliases are correctly mapped. + for (const alias of aliases) { + assert(Array.isArray(inspect.colors[alias])); + } + // Check consistent naming. + [ + 'black', + 'red', + 'green', + 'yellow', + 'blue', + 'magenta', + 'cyan', + 'white' + ].forEach((color, i) => { + assert.deepStrictEqual(inspect.colors[color], [30 + i, 39]); + assert.deepStrictEqual(inspect.colors[`${color}Bright`], [90 + i, 39]); + const bgColor = `bg${color[0].toUpperCase()}${color.slice(1)}`; + assert.deepStrictEqual(inspect.colors[bgColor], [40 + i, 49]); + assert.deepStrictEqual(inspect.colors[`${bgColor}Bright`], [100 + i, 49]); + }); } assert.strictEqual( -- cgit v1.2.3