Skip to content
Permalink
Browse files

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: #26375
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information...
BridgeAR authored and danbev committed Jan 19, 2019
1 parent 6de8801 commit 82f882140120f4ce074fe0de01e380cb3c7c9fc3
@@ -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');
@@ -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,
@@ -70,5 +70,6 @@ function isRecoverableError(e, code) {
}

module.exports = {
isRecoverableError
isRecoverableError,
kStandaloneREPL: Symbol('kStandaloneREPL')
};
@@ -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) {
@@ -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',
@@ -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();

0 comments on commit 82f8821

Please sign in to comment.
You can’t perform that action at this time.