GeezerVison is showing github.com — tty: add raw-vt and io raw modes · nodejs/node@cf39500
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/tty.md +26-4Lines changed: 26 additions & 4 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -69,12 +69,18 @@ A `boolean` that is always `true` for `tty.ReadStream` instances. | 69 | 69 |
| 70 | 70 | <!-- YAML | 71 | 71 | added: v0.7.7 | | 72 | +changes: | | 73 | + - version: REPLACEME | | 74 | + pr-url: https://github.com/nodejs/node/pull/64140 | | 75 | + description: The `mode` argument supports `'raw'` and `'io'`. | 72 | 76 | --> | 73 | 77 |
| 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'`, 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. | 78 | 84 | * Returns: {this} The read stream instance. | 79 | 85 |
| 80 | 86 | Allows configuration of `tty.ReadStream` so that it operates as a raw device. | @@ -91,6 +97,22 @@ buffer. When opening `"\\\\.\\CONIN$"` with the [`fs.open()`][] family of APIs | 91 | 97 | (for passing into `new tty.ReadStream()`), be sure to use a read/write flag | 92 | 98 | such as `'r+'`. | 93 | 99 |
| | 100 | +When in binary-safe I/O mode, terminal output processing is also disabled. | | 101 | +This corresponds to libuv's `UV_TTY_MODE_IO` mode and is not supported on | | 102 | +Windows. | | 103 | + | | 104 | +### `readStream.rawMode` | | 105 | + | | 106 | +<!-- YAML | | 107 | +added: REPLACEME | | 108 | +--> | | 109 | + | | 110 | +* {boolean|string} | | 111 | + | | 112 | +The current raw mode for the `tty.ReadStream`. This is `false` when the stream | | 113 | +is in its default mode, `'raw'` when raw input mode is enabled, and `'io'` when | | 114 | +binary-safe I/O mode is enabled. | | 115 | + | 94 | 116 | ## Class: `tty.WriteStream` | 95 | 117 |
| 96 | 118 | <!-- YAML | |
Collapse file Copy file name to clipboardExpand all lines: lib/tty.js +28-5Lines changed: 28 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -27,10 +27,17 @@ const { | 27 | 27 | } = primordials; | 28 | 28 |
| 29 | 29 | const net = require('net'); | 30 | | -const { TTY, isTTY } = internalBinding('tty_wrap'); | | 30 | +const { | | 31 | + TTY, | | 32 | + UV_TTY_MODE_IO, | | 33 | + UV_TTY_MODE_NORMAL, | | 34 | + UV_TTY_MODE_RAW_VT, | | 35 | + isTTY, | | 36 | +} = internalBinding('tty_wrap'); | 31 | 37 | const { | 32 | 38 | ErrnoException, | 33 | 39 | codes: { | | 40 | + ERR_INVALID_ARG_VALUE, | 34 | 41 | ERR_INVALID_FD, | 35 | 42 | ERR_TTY_INIT_FAILED, | 36 | 43 | }, | @@ -68,20 +75,36 @@ function ReadStream(fd, options) { | 68 | 75 | }); | 69 | 76 |
| 70 | 77 | this.isRaw = false; | | 78 | + this.rawMode = false; | 71 | 79 | this.isTTY = true; | 72 | 80 | } | 73 | 81 |
| 74 | 82 | ObjectSetPrototypeOf(ReadStream.prototype, net.Socket.prototype); | 75 | 83 | ObjectSetPrototypeOf(ReadStream, net.Socket); | 76 | 84 |
| 77 | | -ReadStream.prototype.setRawMode = function(flag) { | 78 | | - flag = !!flag; | 79 | | - const err = this._handle?.setRawMode(flag); | | 85 | +ReadStream.prototype.setRawMode = function(mode) { | | 86 | + let rawMode; | | 87 | + if (mode === 'io' || mode === 'raw') { | | 88 | + rawMode = mode; | | 89 | + } else if (typeof mode === 'string') { | | 90 | + throw new ERR_INVALID_ARG_VALUE( | | 91 | + 'mode', mode, "must be true, false, 'raw', or 'io'"); | | 92 | + } else { | | 93 | + rawMode = mode ? 'raw' : false; | | 94 | + } | | 95 | + let ttyMode = UV_TTY_MODE_NORMAL; | | 96 | + if (rawMode === 'io') { | | 97 | + ttyMode = UV_TTY_MODE_IO; | | 98 | + } else if (rawMode === 'raw') { | | 99 | + ttyMode = UV_TTY_MODE_RAW_VT; | | 100 | + } | | 101 | + const err = this._handle?.setRawMode(ttyMode); | 80 | 102 | if (err) { | 81 | 103 | this.emit('error', new ErrnoException(err, 'setRawMode')); | 82 | 104 | return this; | 83 | 105 | } | 84 | | - this.isRaw = flag; | | 106 | + this.isRaw = rawMode !== false; | | 107 | + this.rawMode = rawMode; | 85 | 108 | return this; | 86 | 109 | }; | 87 | 110 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/tty_wrap.cc +7-3Lines changed: 7 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -68,6 +68,9 @@ void TTYWrap::Initialize(Local<Object> target, | 68 | 68 | SetProtoMethod(isolate, t, "setRawMode", SetRawMode); | 69 | 69 |
| 70 | 70 | SetMethodNoSideEffect(context, target, "isTTY", IsTTY); | | 71 | + NODE_DEFINE_CONSTANT(target, UV_TTY_MODE_NORMAL); | | 72 | + NODE_DEFINE_CONSTANT(target, UV_TTY_MODE_IO); | | 73 | + NODE_DEFINE_CONSTANT(target, UV_TTY_MODE_RAW_VT); | 71 | 74 |
| 72 | 75 | Local<Value> func; | 73 | 76 | if (t->GetFunction(context).ToLocal(&func) && | @@ -124,9 +127,10 @@ void TTYWrap::SetRawMode(const FunctionCallbackInfo<Value>& args) { | 124 | 127 | // sequences at all on Windows, such as bracketed paste mode. | 125 | 128 | // The Node.js readline implementation handles differences between | 126 | 129 | // 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); | | 130 | + Environment* env = Environment::GetCurrent(args); | | 131 | + int mode; | | 132 | + if (!args[0]->Int32Value(env->context()).To(&mode)) return; | | 133 | + int err = uv_tty_set_mode(&wrap->handle_, static_cast<uv_tty_mode_t>(mode)); | 130 | 134 | args.GetReturnValue().Set(err); | 131 | 135 | } | 132 | 136 |
| |
Collapse file Copy file name to clipboard +43Lines changed: 43 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | +require('../common'); | | 3 | +const assert = require('assert'); | | 4 | +const { spawnSync } = require('child_process'); | | 5 | + | | 6 | +function isOnlcrEnabled() { | | 7 | + const { stdout, stderr, status } = spawnSync('stty', ['-a'], { | | 8 | + encoding: 'utf8', | | 9 | + stdio: ['inherit', 'pipe', 'pipe'], | | 10 | + }); | | 11 | + | | 12 | + assert.strictEqual(status, 0, stderr); | | 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'); | | 20 | + | | 21 | +process.stdin.setRawMode(false); | | 22 | +console.log(`normal=${process.stdin.isRaw}`); | | 23 | +assert.strictEqual(process.stdin.rawMode, false); | | 24 | +assert.throws( | | 25 | + () => process.stdin.setRawMode('raw-vt'), | | 26 | + { | | 27 | + code: 'ERR_INVALID_ARG_VALUE', | | 28 | + name: 'TypeError', | | 29 | + }); | | 30 | +assert.strictEqual(process.stdin.rawMode, false); | | 31 | + | | 32 | +process.stdin.setRawMode('raw'); | | 33 | +console.log(`raw-string=${isOnlcrEnabled()}`); | | 34 | +assert.strictEqual(process.stdin.isRaw, true); | | 35 | +assert.strictEqual(process.stdin.rawMode, 'raw'); | | 36 | + | | 37 | +process.stdin.setRawMode(false); | | 38 | +process.stdin.setRawMode('io'); | | 39 | +console.log(`io=${isOnlcrEnabled()}`); | | 40 | +assert.strictEqual(process.stdin.isRaw, true); | | 41 | +assert.strictEqual(process.stdin.rawMode, 'io'); | | 42 | + | | 43 | +process.stdin.setRawMode(false); |
Collapse file Copy file name to clipboard +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +raw=true | | 2 | +normal=false | | 3 | +raw-string=true | | 4 | +io=false |
|