tty: improve color detection

1) Using `process.env.TERM = 'dumb'` should never return any colors.
2) `process.env.TERM = 'terminator'` supports 24 bit colors.
3) Add support for `process.env.TERM = 'rxvt-unicode-24bit'`
4) `Hyper` does not support true colors anymore. It should fall back
   to the xterm settings in regular cases.
5) `process.env.COLORTERM = 'truecolor'` should return 24 bit colors.

PR-URL: https://github.com/nodejs/node/pull/26264
Refs: https://github.com/nodejs/node/pull/26261
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Ruben Bridgewater 2019-02-22 19:15:07 +01:00
parent 7f2d2cdc0c
commit f871c80a6d
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
2 changed files with 35 additions and 26 deletions

View File

@ -36,22 +36,25 @@ const COLORS_16m = 24;
// Copyright (C) 1996-2016 Free Software Foundation, Inc. Copying and // Copyright (C) 1996-2016 Free Software Foundation, Inc. Copying and
// distribution of this file, with or without modification, are permitted // distribution of this file, with or without modification, are permitted
// provided the copyright notice and this notice are preserved. // provided the copyright notice and this notice are preserved.
const TERM_ENVS = [ const TERM_ENVS = {
'eterm', 'eterm': COLORS_16,
'cons25', 'cons25': COLORS_16,
'console', 'console': COLORS_16,
'cygwin', 'cygwin': COLORS_16,
'dtterm', 'dtterm': COLORS_16,
'gnome', 'gnome': COLORS_16,
'hurd', 'hurd': COLORS_16,
'jfbterm', 'jfbterm': COLORS_16,
'konsole', 'konsole': COLORS_16,
'kterm', 'kterm': COLORS_16,
'mlterm', 'mlterm': COLORS_16,
'putty', 'putty': COLORS_16,
'st', 'st': COLORS_16,
'terminator' // https://github.com/da-x/rxvt-unicode/tree/v9.22-with-24bit-color
]; 'rxvt-unicode-24bit': COLORS_16m,
// https://gist.github.com/XVilka/8346728#gistcomment-2823421
'terminator': COLORS_16m
};
const TERM_ENVS_REG_EXP = [ const TERM_ENVS_REG_EXP = [
/ansi/, /ansi/,
@ -68,7 +71,7 @@ const TERM_ENVS_REG_EXP = [
// https://github.com/chalk/supports-color, // https://github.com/chalk/supports-color,
// https://github.com/isaacs/color-support. // https://github.com/isaacs/color-support.
function getColorDepth(env = process.env) { function getColorDepth(env = process.env) {
if (env.NODE_DISABLE_COLORS || env.TERM === 'dumb' && !env.COLORTERM) { if (env.NODE_DISABLE_COLORS || env.TERM === 'dumb') {
return COLORS_2; return COLORS_2;
} }
@ -117,7 +120,6 @@ function getColorDepth(env = process.env) {
} }
return COLORS_16m; return COLORS_16m;
case 'HyperTerm': case 'HyperTerm':
case 'Hyper':
case 'MacTerm': case 'MacTerm':
return COLORS_16m; return COLORS_16m;
case 'Apple_Terminal': case 'Apple_Terminal':
@ -130,10 +132,8 @@ function getColorDepth(env = process.env) {
const termEnv = env.TERM.toLowerCase(); const termEnv = env.TERM.toLowerCase();
for (const term of TERM_ENVS) { if (TERM_ENVS[termEnv]) {
if (termEnv === term) { return TERM_ENVS[termEnv];
return COLORS_16;
}
} }
for (const term of TERM_ENVS_REG_EXP) { for (const term of TERM_ENVS_REG_EXP) {
if (term.test(termEnv)) { if (term.test(termEnv)) {
@ -142,8 +142,11 @@ function getColorDepth(env = process.env) {
} }
} }
if (env.COLORTERM) if (env.COLORTERM) {
if (env.COLORTERM === 'truecolor' || env.COLORTERM === '24bit')
return COLORS_16m;
return COLORS_16; return COLORS_16;
}
return COLORS_2; return COLORS_2;
} }

View File

@ -3,6 +3,7 @@
const common = require('../common'); const common = require('../common');
const assert = require('assert').strict; const assert = require('assert').strict;
const { WriteStream } = require('tty'); const { WriteStream } = require('tty');
const { inspect } = require('util');
const fd = common.getTTYfd(); const fd = common.getTTYfd();
const writeStream = new WriteStream(fd); const writeStream = new WriteStream(fd);
@ -16,6 +17,8 @@ const writeStream = new WriteStream(fd);
// Check different environment variables. // Check different environment variables.
[ [
[{ COLORTERM: '1' }, 4], [{ COLORTERM: '1' }, 4],
[{ COLORTERM: 'truecolor' }, 24],
[{ COLORTERM: '24bit' }, 24],
[{ TMUX: '1' }, 8], [{ TMUX: '1' }, 8],
[{ CI: '1' }, 1], [{ CI: '1' }, 1],
[{ CI: '1', TRAVIS: '1' }, 8], [{ CI: '1', TRAVIS: '1' }, 8],
@ -29,7 +32,7 @@ const writeStream = new WriteStream(fd);
[{ TERM_PROGRAM: 'iTerm.app', TERM_PROGRAM_VERSION: '3.0' }, 24], [{ TERM_PROGRAM: 'iTerm.app', TERM_PROGRAM_VERSION: '3.0' }, 24],
[{ TERM_PROGRAM: 'iTerm.app', TERM_PROGRAM_VERSION: '2.0' }, 8], [{ TERM_PROGRAM: 'iTerm.app', TERM_PROGRAM_VERSION: '2.0' }, 8],
[{ TERM_PROGRAM: 'HyperTerm' }, 24], [{ TERM_PROGRAM: 'HyperTerm' }, 24],
[{ TERM_PROGRAM: 'Hyper' }, 24], [{ TERM_PROGRAM: 'Hyper' }, 1],
[{ TERM_PROGRAM: 'MacTerm' }, 24], [{ TERM_PROGRAM: 'MacTerm' }, 24],
[{ TERM_PROGRAM: 'Apple_Terminal' }, 8], [{ TERM_PROGRAM: 'Apple_Terminal' }, 8],
[{ TERM: 'xterm-256' }, 8], [{ TERM: 'xterm-256' }, 8],
@ -40,13 +43,16 @@ const writeStream = new WriteStream(fd);
[{ TERM: 'fail' }, 1], [{ TERM: 'fail' }, 1],
[{ NODE_DISABLE_COLORS: '1' }, 1], [{ NODE_DISABLE_COLORS: '1' }, 1],
[{ TERM: 'dumb' }, 1], [{ TERM: 'dumb' }, 1],
[{ TERM: 'dumb', COLORTERM: '1' }, 4], [{ TERM: 'dumb', COLORTERM: '1' }, 1],
[{ TERM: 'terminator' }, 24],
[{ TERM: 'console' }, 4]
].forEach(([env, depth], i) => { ].forEach(([env, depth], i) => {
const actual = writeStream.getColorDepth(env); const actual = writeStream.getColorDepth(env);
assert.strictEqual( assert.strictEqual(
actual, actual,
depth, depth,
`i: ${i}, expected: ${depth}, actual: ${actual}, env: ${env}` `i: ${i}, expected: ${depth}, ` +
`actual: ${actual}, env: ${inspect(env)}`
); );
}); });