0
0
mirror of https://github.com/nodejs/node.git synced 2024-12-01 16:10:02 +01:00
nodejs/doc/api/repl.md

622 lines
19 KiB
Markdown
Raw Normal View History

2012-02-27 20:09:34 +01:00
# REPL
2010-10-28 14:18:16 +02:00
<!--introduced_in=v0.10.0-->
> Stability: 2 - Stable
2013-08-28 03:09:26 +02:00
The `repl` module provides a Read-Eval-Print-Loop (REPL) implementation that
is available both as a standalone program or includible in other applications.
It can be accessed using:
2010-10-28 14:18:16 +02:00
```js
const repl = require('repl');
```
## Design and Features
The `repl` module exports the `repl.REPLServer` class. While running, instances
of `repl.REPLServer` will accept individual lines of user input, evaluate those
according to a user-defined evaluation function, then output the result. Input
and output may be from `stdin` and `stdout`, respectively, or may be connected
to any Node.js [stream][].
Instances of `repl.REPLServer` support automatic completion of inputs,
simplistic Emacs-style line editing, multi-line inputs, ANSI-styled output,
saving and restoring current REPL session state, error recovery, and
customizable evaluation functions.
### Commands and Special Keys
The following special commands are supported by all REPL instances:
* `.break` - When in the process of inputting a multi-line expression, entering
the `.break` command (or pressing the `<ctrl>-C` key combination) will abort
further input or processing of that expression.
* `.clear` - Resets the REPL `context` to an empty object and clears any
multi-line expression currently being input.
* `.exit` - Close the I/O stream, causing the REPL to exit.
* `.help` - Show this list of special commands.
* `.save` - Save the current REPL session to a file:
`> .save ./file/to/save.js`
* `.load` - Load a file into the current REPL session.
`> .load ./file/to/load.js`
* `.editor` - Enter editor mode (`<ctrl>-D` to finish, `<ctrl>-C` to cancel).
<!-- eslint-skip -->
```js
> .editor
// Entering editor mode (^D to finish, ^C to cancel)
function welcome(name) {
return `Hello ${name}!`;
}
welcome('Node.js User');
// ^D
'Hello Node.js User!'
>
```
The following key combinations in the REPL have these special effects:
* `<ctrl>-C` - When pressed once, has the same effect as the `.break` command.
When pressed twice on a blank line, has the same effect as the `.exit`
command.
* `<ctrl>-D` - Has the same effect as the `.exit` command.
* `<tab>` - When pressed on a blank line, displays global and local(scope)
variables. When pressed while entering other input, displays relevant
autocompletion options.
### Default Evaluation
By default, all instances of `repl.REPLServer` use an evaluation function that
evaluates JavaScript expressions and provides access to Node.js' built-in
modules. This default behavior can be overridden by passing in an alternative
evaluation function when the `repl.REPLServer` instance is created.
#### JavaScript Expressions
The default evaluator supports direct evaluation of JavaScript expressions:
<!-- eslint-skip -->
```js
> 1 + 1
2
> const m = 2
undefined
> m + 1
3
```
2010-10-28 14:18:16 +02:00
Unless otherwise scoped within blocks or functions, variables declared
either implicitly or using the `const`, `let`, or `var` keywords
are declared at the global scope.
2010-10-28 14:18:16 +02:00
#### Global and Local Scope
2010-10-28 14:18:16 +02:00
The default evaluator provides access to any variables that exist in the global
scope. It is possible to expose a variable to the REPL explicitly by assigning
it to the `context` object associated with each `REPLServer`:
```js
const repl = require('repl');
const msg = 'message';
repl.start('> ').context.m = msg;
```
Properties in the `context` object appear as local within the REPL:
<!-- eslint-skip -->
```js
$ node repl_test.js
> m
'message'
```
Context properties are not read-only by default. To specify read-only globals,
context properties must be defined using `Object.defineProperty()`:
```js
const repl = require('repl');
const msg = 'message';
const r = repl.start('> ');
Object.defineProperty(r.context, 'm', {
configurable: false,
enumerable: true,
value: msg
});
```
#### Accessing Core Node.js Modules
The default evaluator will automatically load Node.js core modules into the
REPL environment when used. For instance, unless otherwise declared as a
global or scoped variable, the input `fs` will be evaluated on-demand as
`global.fs = require('fs')`.
<!-- eslint-skip -->
```js
> fs.createReadStream('./some/file');
```
#### Assignment of the `_` (underscore) variable
<!-- YAML
changes:
- version: v9.8.0
pr-url: https://github.com/nodejs/node/pull/18919
description: Added `_error` support.
-->
The default evaluator will, by default, assign the result of the most recently
evaluated expression to the special variable `_` (underscore).
Explicitly setting `_` to a value will disable this behavior.
<!-- eslint-skip -->
```js
> [ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
> _.length
3
> _ += 1
Expression assignment to _ now disabled.
4
> 1 + 1
2
> _
4
```
Similarly, `_error` will refer to the last seen error, if there was any.
Explicitly setting `_error` to a value will disable this behavior.
<!-- eslint-skip -->
```js
> throw new Error('foo');
Error: foo
> _error.message
'foo'
```
#### `await` keyword
With the [`--experimental-repl-await`][] command line option specified,
experimental support for the `await` keyword is enabled.
<!-- eslint-skip -->
```js
> await Promise.resolve(123)
123
> await Promise.reject(new Error('REPL await'))
Error: REPL await
at repl:1:45
> const timeout = util.promisify(setTimeout);
undefined
> const old = Date.now(); await timeout(1000); console.log(Date.now() - old);
1002
undefined
```
### Custom Evaluation Functions
When a new `repl.REPLServer` is created, a custom evaluation function may be
provided. This can be used, for instance, to implement fully customized REPL
applications.
The following illustrates a hypothetical example of a REPL that performs
translation of text from one language to another:
```js
const repl = require('repl');
const { Translator } = require('translator');
const myTranslator = new Translator('en', 'fr');
function myEval(cmd, context, filename, callback) {
callback(null, myTranslator.translate(cmd));
}
repl.start({ prompt: '> ', eval: myEval });
```
#### Recoverable Errors
As a user is typing input into the REPL prompt, pressing the `<enter>` key will
send the current line of input to the `eval` function. In order to support
multi-line input, the eval function can return an instance of `repl.Recoverable`
to the provided callback function:
```js
function myEval(cmd, context, filename, callback) {
let result;
try {
result = vm.runInThisContext(cmd);
} catch (e) {
if (isRecoverableError(e)) {
return callback(new repl.Recoverable(e));
}
}
callback(null, result);
}
function isRecoverableError(error) {
if (error.name === 'SyntaxError') {
return /^(Unexpected end of input|Unexpected token)/.test(error.message);
}
return false;
}
```
### Customizing REPL Output
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.
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:
```js
const repl = require('repl');
const r = repl.start({ prompt: '> ', eval: myEval, writer: myWriter });
function myEval(cmd, context, filename, callback) {
callback(null, cmd);
}
function myWriter(output) {
return output.toUpperCase();
}
```
## Class: REPLServer
<!-- YAML
added: v0.1.91
-->
The `repl.REPLServer` class inherits from the [`readline.Interface`][] class.
Instances of `repl.REPLServer` are created using the `repl.start()` method and
*should not* be created directly using the JavaScript `new` keyword.
### Event: 'exit'
<!-- YAML
added: v0.7.7
-->
The `'exit'` event is emitted when the REPL is exited either by receiving the
`.exit` command as input, the user pressing `<ctrl>-C` twice to signal `SIGINT`,
or by pressing `<ctrl>-D` to signal `'end'` on the input stream. The listener
callback is invoked without any arguments.
```js
replServer.on('exit', () => {
console.log('Received "exit" event from repl!');
process.exit();
});
```
### Event: 'reset'
<!-- YAML
added: v0.11.0
-->
The `'reset'` event is emitted when the REPL's context is reset. This occurs
whenever the `.clear` command is received as input *unless* the REPL is using
the default evaluator and the `repl.REPLServer` instance was created with the
`useGlobal` option set to `true`. The listener callback will be called with a
reference to the `context` object as the only argument.
This can be used primarily to re-initialize REPL context to some pre-defined
state as illustrated in the following simple example:
```js
const repl = require('repl');
function initializeContext(context) {
context.m = 'test';
}
const r = repl.start({ prompt: '> ' });
initializeContext(r.context);
r.on('reset', initializeContext);
```
When this code is executed, the global `'m'` variable can be modified but then
reset to its initial value using the `.clear` command:
<!-- eslint-skip -->
```js
$ ./node example.js
> m
'test'
> m = 1
1
> m
1
> .clear
Clearing context...
> m
'test'
>
```
### replServer.defineCommand(keyword, cmd)
<!-- YAML
added: v0.3.0
-->
* `keyword` {string} The command keyword (*without* a leading `.` character).
* `cmd` {Object|Function} The function to invoke when the command is processed.
The `replServer.defineCommand()` method is used to add new `.`-prefixed commands
to the REPL instance. Such commands are invoked by typing a `.` followed by the
`keyword`. The `cmd` is either a Function or an object with the following
properties:
* `help` {string} Help text to be displayed when `.help` is entered (Optional).
* `action` {Function} The function to execute, optionally accepting a single
string argument.
The following example shows two new commands added to the REPL instance:
```js
const repl = require('repl');
const replServer = repl.start({ prompt: '> ' });
replServer.defineCommand('sayhello', {
help: 'Say hello',
action(name) {
this.clearBufferedCommand();
console.log(`Hello, ${name}!`);
this.displayPrompt();
}
});
replServer.defineCommand('saybye', function saybye() {
console.log('Goodbye!');
this.close();
});
```
The new commands can then be used from within the REPL instance:
```txt
> .sayhello Node.js User
Hello, Node.js User!
> .saybye
Goodbye!
```
### replServer.displayPrompt([preserveCursor])
<!-- YAML
added: v0.1.91
-->
* `preserveCursor` {boolean}
The `replServer.displayPrompt()` method readies the REPL instance for input
from the user, printing the configured `prompt` to a new line in the `output`
and resuming the `input` to accept new input.
When multi-line input is being entered, an ellipsis is printed rather than the
'prompt'.
When `preserveCursor` is `true`, the cursor placement will not be reset to `0`.
The `replServer.displayPrompt` method is primarily intended to be called from
within the action function for commands registered using the
`replServer.defineCommand()` method.
### replServer.clearBufferedCommand()
<!-- YAML
2017-09-01 18:50:47 +02:00
added: v9.0.0
-->
The `replServer.clearBufferedCommand()` method clears any command that has been
buffered but not yet executed. This method is primarily intended to be
called from within the action function for commands registered using the
`replServer.defineCommand()` method.
### replServer.parseREPLKeyword(keyword, [rest])
<!-- YAML
added: v0.8.9
2017-09-01 18:50:47 +02:00
deprecated: v9.0.0
-->
* `keyword` {string} the potential keyword to parse and execute
* `rest` {any} any parameters to the keyword command
* Returns: {boolean}
> Stability: 0 - Deprecated.
An internal method used to parse and execute `REPLServer` keywords.
Returns `true` if `keyword` is a valid keyword, otherwise `false`.
## repl.start([options])
<!-- YAML
added: v0.1.91
changes:
2018-04-24, Version 10.0.0 (Current) * Assert * Calling `assert.fail()` with more than one argument is deprecated. #70dcacd710 * Calling `assert.ok()` with no arguments will now throw. #3cd7977a42 * Calling `assert.ifError()` will now throw with any argument other than `undefined` or `null`. Previously the method would throw with any truthy value. #e65a6e81ef * The `assert.rejects()` and `assert.doesNotReject()` methods have been added for working with async functions. #599337f43e * Async_hooks * Older experimental async_hooks APIs have been removed. #1cc6b993b9 * Buffer * Uses of `new Buffer()` and `Buffer()` outside of the `node_modules` directory will now emit a runtime deprecation warning. #9d4ab90117 * `Buffer.isEncoding()` now returns `undefined` for falsy values, including an empty string. #452eed956e * `Buffer.fill()` will throw if an attempt is made to fill with an empty `Buffer`. #1e802539b2 * Child Process * Undefined properties of env are ignored. #38ee25e2e2, #85739b6c5b * Console * The `console.table()` method has been added. #97ace04492 * Crypto * The `crypto.createCipher()` and `crypto.createDecipher()` methods have been deprecated. Please use `crypto.createCipheriv()` and `crypto.createDecipheriv()` instead. #81f88e30dd * The `decipher.finaltol()` method has been deprecated. #19f3927d92 * The `crypto.DEFAULT_ENCODING` property has been deprecated. #6035beea93 * The `ECDH.convertKey()` method has been added. #f2e02883e7 * The `crypto.fips` property has been deprecated. #6e7992e8b8 * Dependencies * V8 has been updated to 6.6. #9daebb48d6 * OpenSSL has been updated to 1.1.0h. #66cb29e646 * EventEmitter * The `EventEmitter.prototype.off()` method has been added as an alias for `EventEmitter.prototype.removeListener()`. #3bb6f07d52 * File System * The `fs.promises` API provides experimental promisified versions of the `fs` functions. #329fc78e49 * Invalid path errors are now thrown synchronously. #d8f73385e2 * The `fs.readFile()` method now partitions reads to avoid thread pool exhaustion. #67a4ce1c6e * HTTP * Processing of HTTP Status codes `100`, `102-199` has been improved. #baf8495078 * Multi-byte characters in URL paths are now forbidden. #b961d9fd83 * N-API * The n-api is no longer experimental. #cd7d7b15c1 * Net * The `'close'` event will be emitted after `'end'`. #9b7a6914a7 * Perf_hooks * The `PerformanceObserver` class is now an `AsyncResource` and can be monitored using `async_hooks`. #009e41826f * Trace events are now emitted for performance events. #9e509b622b * The `performance` API has been simplified. #2ec6995555 * Performance milestone marks will be emitted as trace events. #96cb4fb795 * Process * Using non-string values for `process.env` is deprecated. #5826fe4e79 * The `process.assert()` method is deprecated. #703e37cf3f * REPL * REPL now experimentally supports top-level await when using the `--experimental-repl-await` flag. #eeab7bc068 * The previously deprecated "magic mode" has been removed. #4893f70d12 * The previously deprecated `NODE_REPL_HISTORY_FILE` environment variable has been removed. #60c9ad7979 * Proxy objects are shown as Proxy objects when inspected. #90a43906ab * Streams * The `'readable'` event is now always deferred with nextTick. #1e0f3315c7 * A new `pipeline()` method has been provided for building end-to-data stream pipelines. #a5cf3feaf1 * Experimental support for async for-await has been added to `stream.Readable`. #61b4d60c5d * Timers * The `enroll()` and `unenroll()` methods have been deprecated. #68783ae0b8 * TLS * The `tls.convertNONProtocols()` method has been deprecated. #9204a0db6e * Support for NPN (next protocol negotiation) has been dropped. #5bfbe5ceae * The `ecdhCurve` default is now `'auto'`. #af78840b19 * Trace Events * A new `trace_events` top-level module allows trace event categories to be enabled/disabld at runtime. #da5d818a54 * URL * The WHATWG URL API is now a global. #312414662b * Util * `util.types.is[…]` type checks have been added. #b20af8088a * Support for bigint formatting has been added to `util.inspect()`. #39dc947409
2018-03-02 18:53:46 +01:00
- version: v10.0.0
pr-url: https://github.com/nodejs/node/pull/v10.0.0
description: The `REPL_MAGIC_MODE` replMode was removed.
- version: v5.8.0
pr-url: https://github.com/nodejs/node/pull/5388
description: The `options` parameter is optional now.
-->
2010-10-28 14:18:16 +02:00
* `options` {Object|string}
* `prompt` {string} The input prompt to display. **Default:** `'> '`
(with a trailing space).
* `input` {stream.Readable} The Readable stream from which REPL input will be
read. **Default:** `process.stdin`.
* `output` {stream.Writable} The Writable stream to which REPL output will be
written. **Default:** `process.stdout`.
* `terminal` {boolean} If `true`, specifies that the `output` should be
treated as a TTY terminal, and have ANSI/VT100 escape codes written to it.
**Default:** checking the value of the `isTTY` property on the `output`
stream upon instantiation.
* `eval` {Function} The function to be used when evaluating each given line
of input. **Default:** an async wrapper for the JavaScript `eval()`
function. An `eval` function can error with `repl.Recoverable` to indicate
the input was incomplete and prompt for additional lines.
* `useColors` {boolean} If `true`, specifies that the default `writer`
function should include ANSI color styling to REPL output. If a custom
`writer` function is provided then this has no effect. **Default:** the
REPL instances `terminal` value.
* `useGlobal` {boolean} If `true`, specifies that the default evaluation
function will use the JavaScript `global` as the context as opposed to
creating a new separate context for the REPL instance. The node CLI REPL
sets this value to `true`. **Default:** `false`.
* `ignoreUndefined` {boolean} If `true`, specifies that the default writer
will not output the return value of a command if it evaluates to
`undefined`. **Default:** `false`.
* `writer` {Function} The function to invoke to format the output of each
command before writing to `output`. **Default:** [`util.inspect()`][].
* `completer` {Function} An optional function used for custom Tab auto
completion. See [`readline.InterfaceCompleter`][] for an example.
* `replMode` {symbol} A flag that specifies whether the default evaluator
executes all JavaScript commands in strict mode or default (sloppy) mode.
Acceptable values are:
* `repl.REPL_MODE_SLOPPY` - evaluates expressions in sloppy mode.
* `repl.REPL_MODE_STRICT` - evaluates expressions in strict mode. This is
equivalent to prefacing every repl statement with `'use strict'`.
* `breakEvalOnSigint` - Stop evaluating the current piece of code when
`SIGINT` is received, i.e. `Ctrl+C` is pressed. This cannot be used together
with a custom `eval` function. **Default:** `false`.
The `repl.start()` method creates and starts a `repl.REPLServer` instance.
If `options` is a string, then it specifies the input prompt:
```js
const repl = require('repl');
// a Unix style prompt
repl.start('$ ');
```
## The Node.js REPL
Node.js itself uses the `repl` module to provide its own interactive interface
for executing JavaScript. This can be used by executing the Node.js binary
without passing any arguments (or by passing the `-i` argument):
<!-- eslint-skip -->
```js
$ node
> const a = [1, 2, 3];
undefined
> a
[ 1, 2, 3 ]
> a.forEach((v) => {
... console.log(v);
... });
1
2
3
```
### Environment Variable Options
Various behaviors of the Node.js REPL can be customized using the following
environment variables:
- `NODE_REPL_HISTORY` - When a valid path is given, persistent REPL history
will be saved to the specified file rather than `.node_repl_history` in the
user's home directory. Setting this value to `''` will disable persistent
REPL history. Whitespace will be trimmed from the value.
- `NODE_REPL_HISTORY_SIZE` - Controls how many lines of history will be
persisted if history is available. Must be a positive number.
**Default:** `1000`.
- `NODE_REPL_MODE` - May be either `'sloppy'` or `'strict'`. **Default:**
`'sloppy'`, which will allow non-strict mode code to be run.
### Persistent History
By default, the Node.js REPL will persist history between `node` REPL sessions
by saving inputs to a `.node_repl_history` file located in the user's home
directory. This can be disabled by setting the environment variable
`NODE_REPL_HISTORY=''`.
### Using the Node.js REPL with advanced line-editors
For advanced line-editors, start Node.js with the environment variable
`NODE_NO_READLINE=1`. This will start the main and debugger REPL in canonical
terminal settings, which will allow use with `rlwrap`.
For example, the following can be added to a `.bashrc` file:
```text
alias node="env NODE_NO_READLINE=1 rlwrap node"
```
2010-10-28 14:18:16 +02:00
### Starting multiple REPL instances against a single running instance
It is possible to create and run multiple REPL instances against a single
running instance of Node.js that share a single `global` object but have
separate I/O interfaces.
2010-10-28 14:18:16 +02:00
The following example, for instance, provides separate REPLs on `stdin`, a Unix
socket, and a TCP socket:
2010-10-28 14:18:16 +02:00
```js
const net = require('net');
const repl = require('repl');
let connections = 0;
repl.start({
prompt: 'Node.js via stdin> ',
input: process.stdin,
output: process.stdout
});
net.createServer((socket) => {
connections += 1;
repl.start({
prompt: 'Node.js via Unix socket> ',
input: socket,
output: socket
}).on('exit', () => {
socket.end();
});
}).listen('/tmp/node-repl-sock');
net.createServer((socket) => {
connections += 1;
repl.start({
prompt: 'Node.js via TCP socket> ',
input: socket,
output: socket
}).on('exit', () => {
socket.end();
});
}).listen(5001);
```
2010-10-28 14:18:16 +02:00
Running this application from the command line will start a REPL on stdin.
Other REPL clients may connect through the Unix socket or TCP socket. `telnet`,
for instance, is useful for connecting to TCP sockets, while `socat` can be used
to connect to both Unix and TCP sockets.
2010-10-28 14:18:16 +02:00
By starting a REPL from a Unix socket-based server instead of stdin, it is
possible to connect to a long-running Node.js process without restarting it.
2010-10-28 14:18:16 +02:00
For an example of running a "full-featured" (`terminal`) REPL over
a `net.Server` and `net.Socket` instance, see:
[https://gist.github.com/2209310](https://gist.github.com/2209310).
For an example of running a REPL instance over [curl(1)][], see:
[https://gist.github.com/2053342](https://gist.github.com/2053342).
[`--experimental-repl-await`]: cli.html#cli_experimental_repl_await
[`readline.InterfaceCompleter`]: readline.html#readline_use_of_the_completer_function
[`readline.Interface`]: readline.html#readline_class_interface
[`util.inspect()`]: util.html#util_util_inspect_object_options
[curl(1)]: https://curl.haxx.se/docs/manpage.html
[stream]: stream.html