Skip to content

Commit c2211c4

Browse files
tty: add raw-vt and io raw modes
1 parent 74567b2 commit c2211c4

5 files changed

Lines changed: 81 additions & 10 deletions

File tree

doc/api/tty.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,18 @@ A `boolean` that is always `true` for `tty.ReadStream` instances.
6969

7070
<!-- YAML
7171
added: v0.7.7
72+
changes:
73+
- version: REPLACEME
74+
pr-url: https://github.com/nodejs/node/pull/REPLACEME
75+
description: The `mode` argument supports `'raw-vt'` and `'io'`.
7276
-->
7377

74-
* `mode` {boolean} If `true`, configures the `tty.ReadStream` to operate as a
75-
raw device. If `false`, configures the `tty.ReadStream` to operate in its
76-
default mode. The `readStream.isRaw` property will be set to the resulting
77-
mode.
78+
* `mode` {boolean|string} If `true` or `'raw-vt'`, configures the
79+
`tty.ReadStream` to operate as a raw device. If `'io'`, configures the
80+
`tty.ReadStream` to operate in binary-safe I/O mode. If `false`, configures
81+
the `tty.ReadStream` to operate in its default mode. The `readStream.isRaw`
82+
property will be set to whether the stream is in raw mode, and the
83+
`readStream.rawMode` property will be set to the resulting mode.
7884
* Returns: {this} The read stream instance.
7985

8086
Allows configuration of `tty.ReadStream` so that it operates as a raw device.
@@ -86,6 +92,22 @@ characters. <kbd>Ctrl</kbd>+<kbd>C</kbd> will no longer cause a `SIGINT` when
8692
in this mode. This mode does not affect terminal output processing, such as
8793
newline translation on Unix terminals.
8894

95+
When in binary-safe I/O mode, terminal output processing is also disabled.
96+
This corresponds to libuv's `UV_TTY_MODE_IO` mode and is not supported on
97+
Windows.
98+
99+
### `readStream.rawMode`
100+
101+
<!-- YAML
102+
added: REPLACEME
103+
-->
104+
105+
* {boolean|string}
106+
107+
The current raw mode for the `tty.ReadStream`. This is `false` when the stream
108+
is in its default mode, `'raw-vt'` when raw input mode is enabled, and `'io'`
109+
when binary-safe I/O mode is enabled.
110+
89111
## Class: `tty.WriteStream`
90112

91113
<!-- YAML

lib/tty.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,23 @@ function ReadStream(fd, options) {
6868
});
6969

7070
this.isRaw = false;
71+
this.rawMode = false;
7172
this.isTTY = true;
7273
}
7374

7475
ObjectSetPrototypeOf(ReadStream.prototype, net.Socket.prototype);
7576
ObjectSetPrototypeOf(ReadStream, net.Socket);
7677

77-
ReadStream.prototype.setRawMode = function(flag) {
78-
flag = !!flag;
79-
const err = this._handle?.setRawMode(flag);
78+
ReadStream.prototype.setRawMode = function(mode) {
79+
const flag = !!mode;
80+
const isIOMode = mode === 'io';
81+
const err = this._handle?.setRawMode(flag, isIOMode);
8082
if (err) {
8183
this.emit('error', new ErrnoException(err, 'setRawMode'));
8284
return this;
8385
}
8486
this.isRaw = flag;
87+
this.rawMode = flag ? (isIOMode ? 'io' : 'raw-vt') : false;
8588
return this;
8689
};
8790

src/tty_wrap.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,15 @@ void TTYWrap::SetRawMode(const FunctionCallbackInfo<Value>& args) {
124124
// sequences at all on Windows, such as bracketed paste mode.
125125
// The Node.js readline implementation handles differences between
126126
// these modes.
127-
int err = uv_tty_set_mode(
128-
&wrap->handle_,
129-
args[0]->IsTrue() ? UV_TTY_MODE_RAW_VT : UV_TTY_MODE_NORMAL);
127+
uv_tty_mode_t mode;
128+
if (!args[0]->IsTrue()) {
129+
mode = UV_TTY_MODE_NORMAL;
130+
} else if (args[1]->IsTrue()) {
131+
mode = UV_TTY_MODE_IO;
132+
} else {
133+
mode = UV_TTY_MODE_RAW_VT;
134+
}
135+
int err = uv_tty_set_mode(&wrap->handle_, mode);
130136
args.GetReturnValue().Set(err);
131137
}
132138

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const { spawnSync } = require('child_process');
5+
6+
function isOnlcrEnabled() {
7+
const { stdout, status } = spawnSync('stty', ['-a'], {
8+
encoding: 'utf8',
9+
stdio: ['inherit', 'pipe', 'inherit'],
10+
});
11+
12+
assert.strictEqual(status, 0);
13+
return /(?:^|[\s;])onlcr(?:[\s;]|$)/.test(stdout);
14+
}
15+
16+
process.stdin.setRawMode(true);
17+
console.log(`raw=${isOnlcrEnabled()}`);
18+
assert.strictEqual(process.stdin.isRaw, true);
19+
assert.strictEqual(process.stdin.rawMode, 'raw-vt');
20+
21+
process.stdin.setRawMode(false);
22+
console.log(`normal=${process.stdin.isRaw}`);
23+
assert.strictEqual(process.stdin.rawMode, false);
24+
25+
process.stdin.setRawMode('raw-vt');
26+
console.log(`raw-vt=${isOnlcrEnabled()}`);
27+
assert.strictEqual(process.stdin.isRaw, true);
28+
assert.strictEqual(process.stdin.rawMode, 'raw-vt');
29+
30+
process.stdin.setRawMode(false);
31+
process.stdin.setRawMode('io');
32+
console.log(`io=${isOnlcrEnabled()}`);
33+
assert.strictEqual(process.stdin.isRaw, true);
34+
assert.strictEqual(process.stdin.rawMode, 'io');
35+
36+
process.stdin.setRawMode(false);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
raw=true
2+
normal=false
3+
raw-vt=true
4+
io=false

0 commit comments

Comments
 (0)