Skip to content

Commit 070faf0

Browse files
BridgeARtargos
authored andcommitted
tty: add hasColors function
This adds a small wrapper around the `getColorDepth` function to check if the stream supports at least a specific amount of colors. This is convenient as the other API is not as straight forward and most use cases likely only want to know if a specific amount of colors is supported or not. PR-URL: #26247 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Weijia Wang <starkwang@126.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
1 parent 9ce08c8 commit 070faf0

File tree

5 files changed

+81
-2
lines changed

5 files changed

+81
-2
lines changed

doc/api/tty.md

+30
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,35 @@ corresponding to this `WriteStream`. The array is of the type
176176
`[numColumns, numRows]` where `numColumns` and `numRows` represent the number
177177
of columns and rows in the corresponding [TTY](tty.html).
178178

179+
### writeStream.hasColors([count][, env])
180+
<!-- YAML
181+
added: REPLACEME
182+
-->
183+
184+
* `count` {integer} The number of colors that are requested (minimum 2).
185+
**Default:** 16.
186+
* `env` {Object} An object containing the environment variables to check. This
187+
enables simulating the usage of a specific terminal. **Default:**
188+
`process.env`.
189+
* Returns: {boolean}
190+
191+
Returns `true` if the `writeStream` supports at least as many colors as provided
192+
in `count`. Minimum support is 2 (black and white).
193+
194+
This has the same false positives and negatives as described in
195+
[`writeStream.getColorDepth()`][].
196+
197+
```js
198+
process.stdout.hasColors();
199+
// Returns true or false depending on if `stdout` supports at least 16 colors.
200+
process.stdout.hasColors(256);
201+
// Returns true or false depending on if `stdout` supports at least 256 colors.
202+
process.stdout.hasColors({ TMUX: '1' });
203+
// Returns true.
204+
process.stdout.hasColors(2 ** 24, { TMUX: '1' });
205+
// Returns false (the environment setting pretends to support 2 ** 8 colors).
206+
```
207+
179208
### writeStream.isTTY
180209
<!-- YAML
181210
added: v0.5.8
@@ -217,3 +246,4 @@ integer.
217246
[`process.stderr`]: process.html#process_process_stderr
218247
[`process.stdin`]: process.html#process_process_stdin
219248
[`process.stdout`]: process.html#process_process_stdout
249+
[`writeStream.getColorDepth()`]: #tty_writestream_getcolordepth_env

lib/internal/tty.js

+23-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222

2323
'use strict';
2424

25+
const {
26+
ERR_INVALID_ARG_TYPE,
27+
ERR_OUT_OF_RANGE
28+
} = require('internal/errors').codes;
29+
2530
let OSRelease;
2631

2732
const COLORS_2 = 1;
@@ -151,6 +156,23 @@ function getColorDepth(env = process.env) {
151156
return COLORS_2;
152157
}
153158

159+
function hasColors(count, env) {
160+
if (env === undefined &&
161+
(count === undefined || typeof count === 'object' && count !== null)) {
162+
env = count;
163+
count = 16;
164+
} else {
165+
if (typeof count !== 'number') {
166+
throw new ERR_INVALID_ARG_TYPE('count', 'number', count);
167+
}
168+
if (count < 2) {
169+
throw new ERR_OUT_OF_RANGE('count', '>= 2', count);
170+
}
171+
}
172+
return count <= 2 ** getColorDepth(env);
173+
}
174+
154175
module.exports = {
155-
getColorDepth
176+
getColorDepth,
177+
hasColors
156178
};

lib/tty.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ const net = require('net');
2626
const { TTY, isTTY } = internalBinding('tty_wrap');
2727
const errors = require('internal/errors');
2828
const { ERR_INVALID_FD, ERR_TTY_INIT_FAILED } = errors.codes;
29-
const { getColorDepth } = require('internal/tty');
29+
const {
30+
getColorDepth,
31+
hasColors
32+
} = require('internal/tty');
3033

3134
// Lazy loaded for startup performance.
3235
let readline;
@@ -109,6 +112,8 @@ WriteStream.prototype.isTTY = true;
109112

110113
WriteStream.prototype.getColorDepth = getColorDepth;
111114

115+
WriteStream.prototype.hasColors = hasColors;
116+
112117
WriteStream.prototype._refreshSize = function() {
113118
const oldCols = this.columns;
114119
const oldRows = this.rows;

test/pseudo-tty/test-tty-get-color-depth.js test/pseudo-tty/test-tty-color-support.js

+22
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,26 @@ const writeStream = new WriteStream(fd);
1212
const depth = writeStream.getColorDepth();
1313
assert.strictEqual(typeof depth, 'number');
1414
assert(depth >= 1 && depth <= 24);
15+
16+
const support = writeStream.hasColors();
17+
assert.strictEqual(support, depth !== 1);
1518
}
1619

20+
// Validate invalid input.
21+
[true, null, () => {}, Symbol(), 5n].forEach((input) => {
22+
assert.throws(
23+
() => writeStream.hasColors(input),
24+
{ code: 'ERR_INVALID_ARG_TYPE' }
25+
);
26+
});
27+
28+
[-1, 1].forEach((input) => {
29+
assert.throws(
30+
() => writeStream.hasColors(input),
31+
{ code: 'ERR_OUT_OF_RANGE' }
32+
);
33+
});
34+
1735
// Check different environment variables.
1836
[
1937
[{ COLORTERM: '1' }, 4],
@@ -54,6 +72,10 @@ const writeStream = new WriteStream(fd);
5472
`i: ${i}, expected: ${depth}, ` +
5573
`actual: ${actual}, env: ${inspect(env)}`
5674
);
75+
const colors = 2 ** actual;
76+
assert(writeStream.hasColors(colors, env));
77+
assert(!writeStream.hasColors(colors + 1, env));
78+
assert(depth >= 4 ? writeStream.hasColors(env) : !writeStream.hasColors(env));
5779
});
5880

5981
// OS settings

0 commit comments

Comments
 (0)