Skip to content

Commit 4285b57

Browse files
BridgeARBethGriggs
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 <[email protected]> Reviewed-By: Weijia Wang <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]>
1 parent 064511e commit 4285b57

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;
@@ -148,6 +153,23 @@ function getColorDepth(env = process.env) {
148153
return COLORS_2;
149154
}
150155

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

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;
@@ -110,6 +113,8 @@ WriteStream.prototype.isTTY = true;
110113

111114
WriteStream.prototype.getColorDepth = getColorDepth;
112115

116+
WriteStream.prototype.hasColors = hasColors;
117+
113118
WriteStream.prototype._refreshSize = function() {
114119
const oldCols = this.columns;
115120
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
@@ -11,8 +11,26 @@ const writeStream = new WriteStream(fd);
1111
const depth = writeStream.getColorDepth();
1212
assert.strictEqual(typeof depth, 'number');
1313
assert(depth >= 1 && depth <= 24);
14+
15+
const support = writeStream.hasColors();
16+
assert.strictEqual(support, depth !== 1);
1417
}
1518

19+
// Validate invalid input.
20+
[true, null, () => {}, Symbol(), 5n].forEach((input) => {
21+
assert.throws(
22+
() => writeStream.hasColors(input),
23+
{ code: 'ERR_INVALID_ARG_TYPE' }
24+
);
25+
});
26+
27+
[-1, 1].forEach((input) => {
28+
assert.throws(
29+
() => writeStream.hasColors(input),
30+
{ code: 'ERR_OUT_OF_RANGE' }
31+
);
32+
});
33+
1634
// Check different environment variables.
1735
[
1836
[{ COLORTERM: '1' }, 4],
@@ -48,6 +66,10 @@ const writeStream = new WriteStream(fd);
4866
depth,
4967
`i: ${i}, expected: ${depth}, actual: ${actual}, env: ${env}`
5068
);
69+
const colors = 2 ** actual;
70+
assert(writeStream.hasColors(colors, env));
71+
assert(!writeStream.hasColors(colors + 1, env));
72+
assert(depth >= 4 ? writeStream.hasColors(env) : !writeStream.hasColors(env));
5173
});
5274

5375
// OS settings

0 commit comments

Comments
 (0)