repl: add replDefaults to customize the writer

So far it was not possible to modify the inspection defaults used by
the REPL from the running instance itself. This introduces a new
property on `util.inspect` which is only used inside the REPL and which
allows to modify the used inspection defaults at any point of time.

PR-URL: https://github.com/nodejs/node/pull/26375
Reviewed-By: James M Snell <jasnell@gmail.com>
pull/26510/head
Ruben Bridgewater 2019-01-19 15:34:00 +01:00 committed by Daniel Bevenius
parent 6de88015bb
commit 82f8821401
6 changed files with 82 additions and 13 deletions

View File

@ -256,13 +256,32 @@ function isRecoverableError(error) {
By default, [`repl.REPLServer`][] instances format output using the
[`util.inspect()`][] method before writing the output to the provided `Writable`
stream (`process.stdout` by default). The `useColors` boolean option can be
specified at construction to instruct the default writer to use ANSI style
codes to colorize the output from the `util.inspect()` method.
stream (`process.stdout` by default). The `showProxy` inspection option is set
to true by default and the `colors` option is set to true depending on the
REPL's `useColors` option.
It is possible to fully customize the output of a [`repl.REPLServer`][] instance
by passing a new function in using the `writer` option on construction. The
following example, for instance, simply converts any input text to upper case:
The `useColors` boolean option can be specified at construction to instruct the
default writer to use ANSI style codes to colorize the output from the
`util.inspect()` method.
If the REPL is run as standalone program, it is also possible to change the
REPL's [inspection defaults][`util.inspect()`] from inside the REPL by using the
`inspect.replDefaults` property which mirrors the `defaultOptions` from
[`util.inspect()`][].
```console
> util.inspect.replDefaults.compact = false;
false
> [1]
[
1
]
>
```
To fully customize the output of a [`repl.REPLServer`][] instance pass in a new
function for the `writer` option on construction. The following example, for
instance, simply converts any input text to upper case:
```js
const repl = require('repl');

View File

@ -1,6 +1,7 @@
'use strict';
const REPL = require('repl');
const { kStandaloneREPL } = require('internal/repl/utils');
module.exports = Object.create(REPL);
module.exports.createInternalRepl = createRepl;
@ -11,6 +12,7 @@ function createRepl(env, opts, cb) {
opts = null;
}
opts = {
[kStandaloneREPL]: true,
ignoreUndefined: false,
terminal: process.stdout.isTTY,
useGlobal: true,

View File

@ -70,5 +70,6 @@ function isRecoverableError(e, code) {
}
module.exports = {
isRecoverableError
isRecoverableError,
kStandaloneREPL: Symbol('kStandaloneREPL')
};

View File

@ -72,7 +72,10 @@ const { sendInspectorCommand } = require('internal/util/inspector');
const experimentalREPLAwait = require('internal/options').getOptionValue(
'--experimental-repl-await'
);
const { isRecoverableError } = require('internal/repl/recoverable');
const {
isRecoverableError,
kStandaloneREPL
} = require('internal/repl/utils');
const {
getOwnNonIndexProperties,
propertyFilter: {
@ -505,10 +508,25 @@ function REPLServer(prompt,
}
self.useColors = !!options.useColors;
if (self.useColors && self.writer === writer) {
// Turn on ANSI coloring.
self.writer = (obj) => util.inspect(obj, self.writer.options);
self.writer.options = { ...writer.options, colors: true };
if (self.writer === writer) {
// Conditionally turn on ANSI coloring.
writer.options.colors = self.useColors;
if (options[kStandaloneREPL]) {
Object.defineProperty(util.inspect, 'replDefaults', {
get() {
return writer.options;
},
set(options) {
if (options === null || typeof options !== 'object') {
throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
}
return Object.assign(writer.options, options);
},
enumerable: true,
configurable: true
});
}
}
function filterInternalStackFrames(structuredStack) {

View File

@ -174,7 +174,7 @@
'lib/internal/repl.js',
'lib/internal/repl/await.js',
'lib/internal/repl/history.js',
'lib/internal/repl/recoverable.js',
'lib/internal/repl/utils.js',
'lib/internal/socket_list.js',
'lib/internal/test/binding.js',
'lib/internal/test/heap.js',

View File

@ -0,0 +1,29 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const cp = require('child_process');
const child = cp.spawn(process.execPath, ['-i']);
let output = '';
child.stdout.setEncoding('utf8');
child.stdout.on('data', (data) => {
output += data;
});
child.on('exit', common.mustCall(() => {
const results = output.replace(/^> /mg, '').split('\n');
assert.deepStrictEqual(
results,
[
'[ 42, 23 ]',
'1',
'[ 42, ... 1 more item ]',
''
]
);
}));
child.stdin.write('[ 42, 23 ]\n');
child.stdin.write('util.inspect.replDefaults.maxArrayLength = 1\n');
child.stdin.write('[ 42, 23 ]\n');
child.stdin.end();