REPL
[Stable: 2 - Stable]
Stable: 2 Stability: 2 - Stable
ソースコード: lib/repl.js
node:repl
モジュールは、スタンドアロンプログラムとして、または他のアプリケーションに含めることができる Read-Eval-Print-Loop(REPL)実装を提供します。次のようにアクセスできます。
import repl from 'node:repl'
const repl = require('node:repl')
設計と機能
node:repl
モジュールは、repl.REPLServer
クラスをエクスポートします。実行中は、repl.REPLServer
のインスタンスは、ユーザー入力の個々の行を受け取り、ユーザー定義の評価関数に従ってそれらを評価し、結果を出力します。入出力はそれぞれ stdin
と stdout
から行うことも、任意の Node.js ストリーム に接続することもできます。
repl.REPLServer
のインスタンスは、入力の自動補完、補完プレビュー、単純な Emacs スタイルの行編集、複数行入力、ZSHのような逆 i 検索、ZSHのような部分文字列ベースの履歴検索、ANSI スタイルの出力、現在の REPL セッション状態の保存と復元、エラー回復、およびカスタマイズ可能な評価関数をサポートしています。ANSI スタイルと Emacs スタイルの行編集をサポートしていない端末は、自動的に機能が限定されたセットにフォールバックします。
コマンドと特殊キー
次の特殊コマンドは、すべての REPL インスタンスでサポートされています。
.break
:複数行の式を入力している途中で、.break
コマンドを入力するか(または Ctrl + C を押す)して、その式のさらなる入力または処理を中止します。.clear
:REPLcontext
を空のオブジェクトにリセットし、入力中の複数行式をクリアします。.exit
:I/O ストリームを閉じ、REPL を終了します。.help
:この特殊コマンドのリストを表示します。.save
:現在の REPL セッションをファイルに保存します:> .save ./file/to/save.js
.load
:現在の REPL セッションにファイルを読み込みます。> .load ./file/to/load.js
.editor
:エディターモードに入ります(Ctrl + D で終了、Ctrl + C でキャンセル)。
> .editor
// エディターモードに入ります(^Dで終了、^Cでキャンセル)
function welcome(name) {
return `Hello ${name}!`;
}
welcome('Node.js User');
// ^D
'Hello Node.js User!'
>
REPL での次のキー組み合わせには、次の特殊効果があります。
- Ctrl + C:1 回押すと、
.break
コマンドと同じ効果があります。空行で 2 回押すと、.exit
コマンドと同じ効果があります。 - Ctrl + D:
.exit
コマンドと同じ効果があります。 - Tab:空行で押すと、グローバル変数とローカル変数(スコープ)が表示されます。他の入力を入力中に押すと、関連する自動補完オプションが表示されます。
逆 i 検索に関連するキーバインドについては、reverse-i-search
を参照してください。その他のキーバインドについては、TTY キーバインドを参照してください。
デフォルトの評価
デフォルトでは、repl.REPLServer
のすべてのインスタンスは、JavaScript 式を評価し、Node.js 組み込みモジュールへのアクセスを提供する評価関数を使用します。このデフォルトの動作は、repl.REPLServer
インスタンスの作成時に代替の評価関数を渡すことでオーバーライドできます。
JavaScript 式
デフォルトの評価関数は、JavaScript 式の直接的な評価をサポートします。
> 1 + 1
2
> const m = 2
undefined
> m + 1
3
ブロックまたは関数内でスコープが指定されていない限り、const
、let
、またはvar
キーワードを使用して暗黙的に宣言された変数は、グローバルスコープで宣言されます。
グローバルスコープとローカルスコープ
デフォルトの評価関数は、グローバルスコープに存在するすべての変数へのアクセスを提供します。各REPLServer
に関連付けられたcontext
オブジェクトに代入することで、変数を REPL に明示的に公開できます。
import repl from 'node:repl'
const msg = 'message'
repl.start('> ').context.m = msg
const repl = require('node:repl')
const msg = 'message'
repl.start('> ').context.m = msg
context
オブジェクトのプロパティは、REPL 内でローカルとして表示されます。
$ node repl_test.js
> m
'message'
コンテキストプロパティは、デフォルトでは読み取り専用ではありません。読み取り専用のグローバル変数を指定するには、Object.defineProperty()
を使用してコンテキストプロパティを定義する必要があります。
import repl from 'node:repl'
const msg = 'message'
const r = repl.start('> ')
Object.defineProperty(r.context, 'm', {
configurable: false,
enumerable: true,
value: msg,
})
const repl = require('node:repl')
const msg = 'message'
const r = repl.start('> ')
Object.defineProperty(r.context, 'm', {
configurable: false,
enumerable: true,
value: msg,
})
Node.js コアモジュールへのアクセス
デフォルトの評価関数は、使用時に Node.js コアモジュールを REPL 環境に自動的にロードします。例えば、グローバル変数またはスコープ変数として宣言されていない限り、入力fs
はオンデマンドでglobal.fs = require('node:fs')
として評価されます。
> fs.createReadStream('./some/file');
グローバル未キャッチ例外
[履歴]
バージョン | 変更 |
---|---|
v12.3.0 | 'uncaughtException' イベントは、REPL がスタンドアロン プログラムとして使用されている場合にトリガーされるようになりました。 |
REPL は、その REPL セッションのすべての未キャッチ例外をキャッチするために domain
モジュールを使用します。
REPL での domain
モジュールのこの使用法には、次の副作用があります。
- 未キャッチ例外は、スタンドアロン REPL でのみ
'uncaughtException'
イベントを発行します。別の Node.js プログラム内の REPL でこのイベントのリスナーを追加すると、ERR_INVALID_REPL_INPUT
が発生します。 process.setUncaughtExceptionCaptureCallback()
を使用しようとすると、ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE
エラーが発生します。
_
(アンダースコア)変数の代入
[履歴]
バージョン | 変更 |
---|---|
v9.8.0 | _error サポートを追加 |
デフォルトの評価子は、デフォルトで、最後に評価された式の結果を特別な変数 _
(アンダースコア)に代入します。_
に明示的に値を設定すると、この動作は無効になります。
> [ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
> _.length
3
> _ += 1
Expression assignment to _ now disabled.
4
> 1 + 1
2
> _
4
同様に、_error
は、存在する場合は最後に発生したエラーを参照します。_error
に明示的に値を設定すると、この動作は無効になります。
> throw new Error('foo');
Uncaught Error: foo
> _error.message
'foo'
await
キーワード
await
キーワードのサポートは、最上位レベルで有効になっています。
> await Promise.resolve(123)
123
> await Promise.reject(new Error('REPL await'))
Uncaught Error: REPL await
at REPL2:1:54
> const timeout = util.promisify(setTimeout);
undefined
> const old = Date.now(); await timeout(1000); console.log(Date.now() - old);
1002
undefined
REPL で await
キーワードを使用することの既知の制限事項の 1 つは、const
と let
キーワードの字句スコープが無効になることです。
例:
> const m = await Promise.resolve(123)
undefined
> m
123
> const m = await Promise.resolve(234)
undefined
> m
234
--no-experimental-repl-await
は、REPL で最上位レベルの await を無効にします。
逆引き検索
追加バージョン: v13.6.0, v12.17.0
REPL は、ZSHに似た双方向逆引き検索をサポートしています。 Ctrl + R
で後方検索、Ctrl + S
で前方検索が開始されます。
重複した履歴エントリはスキップされます。
逆検索に対応しないキーを押すと、エントリが確定されます。Ctrl + C
またはCtrl + R
を押すとキャンセルできます。
方向を変更すると、現在の位置から期待される方向の次のエントリがすぐに検索されます。
カスタム評価関数
新しいrepl.REPLServer
が作成されると、カスタム評価関数を指定できます。これにより、完全にカスタマイズされた REPL アプリケーションを実装できます。
以下は、与えられた数を 2 乗する REPL の例です。
import repl from 'node:repl'
function byThePowerOfTwo(number) {
return number * number
}
function myEval(cmd, context, filename, callback) {
callback(null, byThePowerOfTwo(cmd))
}
repl.start({ prompt: 'Enter a number: ', eval: myEval })
const repl = require('node:repl')
function byThePowerOfTwo(number) {
return number * number
}
function myEval(cmd, context, filename, callback) {
callback(null, byThePowerOfTwo(cmd))
}
repl.start({ prompt: 'Enter a number: ', eval: myEval })
回復可能なエラー
REPL プロンプトでCtrl + D
を押すと、現在の入力行がeval
関数に送信されます。複数行の入力をサポートするために、eval
関数はrepl.Recoverable
のインスタンスを指定されたコールバック関数に返すことができます。
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
}
REPL 出力のカスタマイズ
デフォルトでは、repl.REPLServer
インスタンスは、出力を提供されたWritable
ストリーム(デフォルトではprocess.stdout
)に書き込む前に、util.inspect()
メソッドを使用して出力をフォーマットします。showProxy
検査オプションはデフォルトで true に設定され、colors
オプションは REPL のuseColors
オプションに応じて true に設定されます。
useColors
ブールオプションは、構築時に指定して、デフォルトのライターに ANSI スタイルコードを使用してutil.inspect()
メソッドからの出力を色付けするように指示できます。
REPL がスタンドアロンプログラムとして実行される場合、util.inspect()
のdefaultOptions
を反映するinspect.replDefaults
プロパティを使用して、REPL 内から REPL の検査デフォルトを変更することもできます。
> util.inspect.replDefaults.compact = false;
false
> [1]
[
1
]
>
repl.REPLServer
インスタンスの出力を完全にカスタマイズするには、構築時にwriter
オプションに新しい関数を渡します。たとえば、次の例では、入力テキストをすべて大文字に変換します。
import repl from 'node: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()
}
const repl = require('node: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()
}
クラス: REPLServer
追加されたバージョン: v0.1.91
options
<Object> | <string>repl.start()
を参照- 継承元: <readline.Interface>
repl.REPLServer
のインスタンスは、repl.start()
メソッドを使用するか、JavaScript のnew
キーワードを使用して直接作成されます。
import repl from 'node:repl'
const options = { useColors: true }
const firstInstance = repl.start(options)
const secondInstance = new repl.REPLServer(options)
const repl = require('node:repl')
const options = { useColors: true }
const firstInstance = repl.start(options)
const secondInstance = new repl.REPLServer(options)
イベント: 'exit'
追加日: v0.7.7
'exit'
イベントは、.exit
コマンドを入力として受信した場合、ユーザーが SIGINT をシグナルするために+を 2 回押した場合、または入力ストリームで'end'をシグナルするために+を押した場合に、REPL が終了するときに発生します。リスナーコールバックは引数なしで呼び出されます。
replServer.on('exit', () => {
console.log('Received "exit" event from repl!')
process.exit()
})
イベント: 'reset'
追加日: v0.11.0
'reset'
イベントは、REPL のコンテキストがリセットされるときに発生します。これは、REPL がデフォルトの評価器を使用しておらず、repl.REPLServer
インスタンスがuseGlobal
オプションをtrue
に設定して作成されていない限り、.clear
コマンドが入力として受信されるたびに発生します。リスナーコールバックは、context
オブジェクトへの参照を引数として呼び出されます。
これは、主に REPL コンテキストを事前に定義された状態に再初期化するために使用できます。
import repl from 'node:repl'
function initializeContext(context) {
context.m = 'test'
}
const r = repl.start({ prompt: '> ' })
initializeContext(r.context)
r.on('reset', initializeContext)
const repl = require('node:repl')
function initializeContext(context) {
context.m = 'test'
}
const r = repl.start({ prompt: '> ' })
initializeContext(r.context)
r.on('reset', initializeContext)
このコードを実行すると、グローバルな'm'
変数は変更できますが、.clear
コマンドを使用して初期値にリセットできます。
$ ./node example.js
> m
'test'
> m = 1
1
> m
1
> .clear
Clearing context...
> m
'test'
>
replServer.defineCommand(keyword, cmd)
追加日: v0.3.0
keyword
<string> コマンドキーワード(先頭に.
文字はなし)。cmd
<Object> | <Function> コマンドが処理されたときに呼び出す関数。
replServer.defineCommand()
メソッドは、REPL インスタンスに新しい.
で始まるコマンドを追加するために使用されます。このようなコマンドは、.
の後にkeyword
を入力することで呼び出されます。cmd
は、次のプロパティを持つFunction
またはObject
です。
help
<string>.help
が入力されたときに表示されるヘルプテキスト(オプション)。action
<Function> 実行する関数。オプションで、単一の文字列引数を受け入れます。
次の例は、REPL インスタンスに追加された 2 つの新しいコマンドを示しています。
import repl from 'node: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()
})
const repl = require('node: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()
})
新しいコマンドは、REPL インスタンス内から使用できます。
> .sayhello Node.js User
Hello, Node.js User!
> .saybye
Goodbye!
replServer.displayPrompt([preserveCursor])
追加日時: v0.1.91
preserveCursor
<boolean>
replServer.displayPrompt()
メソッドは、REPL インスタンスを使用者からの入力待ち状態にし、設定されたprompt
をoutput
に改行して出力し、新しい入力を受け付けるようにinput
を再開します。
複数行の入力が行われている場合、「prompt」ではなく省略記号が表示されます。
preserveCursor
がtrue
の場合、カーソルの位置は0
にリセットされません。
replServer.displayPrompt
メソッドは、主にreplServer.defineCommand()
メソッドを使用して登録されたコマンドのアクション関数内から呼び出すことを目的としています。
replServer.clearBufferedCommand()
追加日時: v9.0.0
replServer.clearBufferedCommand()
メソッドは、バッファリングされているがまだ実行されていないコマンドをクリアします。このメソッドは、主にreplServer.defineCommand()
メソッドを使用して登録されたコマンドのアクション関数内から呼び出すことを目的としています。
replServer.setupHistory(historyPath, callback)
追加日時: v11.10.0
historyPath
<string> 履歴ファイルへのパスcallback
<Function> 履歴の書き込みが完了した場合、またはエラー発生時に呼び出されますerr
<Error>repl
<repl.REPLServer>
REPL インスタンスの履歴ログファイルを開始します。Node.js バイナリを実行し、コマンドライン REPL を使用する場合、履歴ファイルはデフォルトで初期化されます。ただし、プログラムで REPL を作成する場合はそうではありません。プログラムで REPL インスタンスを操作する場合は、このメソッドを使用して履歴ログファイルを開始してください。
repl.builtinModules
追加日時: v14.5.0
すべての Node.js モジュールの名前のリスト、例:「'http'
」。
repl.start([options])
[履歴]
バージョン | 変更点 |
---|---|
v13.4.0, v12.17.0 | preview オプションが利用可能になりました。 |
v12.0.0 | terminal オプションはすべての場合においてデフォルトの説明に従うようになり、useColors は利用可能な場合 hasColors() を確認するようになりました。 |
v10.0.0 | REPL_MAGIC_MODE replMode が削除されました。 |
v6.3.0 | breakEvalOnSigint オプションがサポートされるようになりました。 |
v5.8.0 | options パラメータはオプションになりました。 |
v0.1.91 | 追加:v0.1.91 |
prompt
<string> 表示する入力プロンプト。デフォルト:'\> '
(末尾にスペース付き)。input
<stream.Readable> REPL 入力を読み取るReadable
ストリーム。デフォルト:process.stdin
。output
<stream.Writable> REPL 出力を書き込むWritable
ストリーム。デフォルト:process.stdout
。terminal
<boolean>true
の場合、output
を TTY ターミナルとして扱うことを指定します。デフォルト: インスタンス化時にoutput
ストリームのisTTY
プロパティの値をチェックします。eval
<Function> 入力された各行を評価する際に使用する関数。デフォルト: JavaScript のeval()
関数の非同期ラッパー。eval
関数は、入力が不完全であることを示すrepl.Recoverable
を使用してエラーを発生させ、追加の行を要求できます。useColors
<boolean>true
の場合、デフォルトのwriter
関数が REPL 出力に ANSI カラースタイルを含めることを指定します。カスタムのwriter
関数が提供されている場合、これは効果がありません。デフォルト: REPL インスタンスのterminal
の値がtrue
の場合、output
ストリームの色サポートをチェックします。useGlobal
<boolean>true
の場合、デフォルトの評価関数が REPL インスタンスのために新しい個別のコンテキストを作成するのではなく、JavaScript のglobal
をコンテキストとして使用するように指定します。Node CLI REPL はこの値をtrue
に設定します。デフォルト:false
。ignoreUndefined
<boolean>true
の場合、デフォルトの writer は、コマンドの戻り値がundefined
に評価される場合は、その戻り値を出力しません。デフォルト:false
。writer
<Function>output
に書き込む前に、各コマンドの出力をフォーマットするために呼び出す関数。デフォルト:util.inspect()
。completer
<Function> カスタムの Tab オートコンプリートに使用されるオプションの関数。例については、readline.InterfaceCompleter
を参照してください。replMode
<symbol> デフォルトの評価子がすべての JavaScript コマンドを厳格モードで実行するか、デフォルト(非厳格)モードで実行するかを指定するフラグ。許容される値は次のとおりです。repl.REPL_MODE_SLOPPY
は、非厳格モードで式を評価します。repl.REPL_MODE_STRICT
は、厳格モードで式を評価します。これは、すべての repl ステートメントの前に'use strict'
を付けることと同じです。breakEvalOnSigint
<boolean>SIGINT
(例:+キーが押された時)を受信したときに、現在の実行中のコードの実行を停止します。これはカスタムのeval
関数と併用することはできません。デフォルト:false
。preview
<boolean> repl がオートコンプリートと出力プレビューを表示するかどうかを定義します。デフォルト: デフォルトの eval 関数ではtrue
、カスタムの eval 関数を使用する場合はfalse
。terminal
が偽の場合、プレビューはなく、preview
の値は効果がありません。
戻り値: <repl.REPLServer>
repl.start()
メソッドは、repl.REPLServer
インスタンスを作成して起動します。
options
が文字列の場合、入力プロンプトを指定します。
import repl from 'node:repl'
// Unixスタイルのプロンプト
repl.start('$ ')
const repl = require('node:repl')
// Unixスタイルのプロンプト
repl.start('$ ')
Node.js REPL
Node.js 自体はnode:repl
モジュールを使用して、JavaScript を実行するための独自のインタラクティブインターフェースを提供します。これは、引数を渡さずに Node.js バイナリを実行するか(または-i
引数を渡すことによって)使用できます。
$ node
> const a = [1, 2, 3];
undefined
> a
[ 1, 2, 3 ]
> a.forEach((v) => {
... console.log(v);
... });
1
2
3
環境変数オプション
以下の環境変数を使用して、Node.js REPL の様々な動作をカスタマイズできます。
NODE_REPL_HISTORY
: 有効なパスが指定されている場合、永続的な REPL 履歴は、ユーザーのホームディレクトリにある.node_repl_history
ではなく、指定されたファイルに保存されます。この値を''
(空文字列)に設定すると、永続的な REPL 履歴が無効になります。空白は値からトリミングされます。Windows プラットフォームでは、空の値を持つ環境変数は無効であるため、永続的な REPL 履歴を無効にするには、この変数を 1 つ以上のスペースに設定します。NODE_REPL_HISTORY_SIZE
: 履歴が利用可能な場合、保存される履歴の行数を制御します。正の数でなければなりません。デフォルト:1000
。NODE_REPL_MODE
:'sloppy'
または'strict'
のいずれかになります。デフォルト:'sloppy'
。これは、非厳格モードのコードの実行を許可します。
永続的な履歴
デフォルトでは、Node.js REPL は、ユーザーのホームディレクトリにある.node_repl_history
ファイルに入力を保存することで、node
REPL セッション間の履歴を保持します。これは、環境変数NODE_REPL_HISTORY=''
を設定することで無効にできます。
高度なラインエディタを使用した Node.js REPL
高度なラインエディタを使用するには、環境変数NODE_NO_READLINE=1
を使用して Node.js を起動します。これにより、メイン REPL とデバッガー REPL が標準的なターミナル設定で起動され、rlwrap
を使用できるようになります。
たとえば、以下を.bashrc
ファイルに追加できます。
alias node="env NODE_NO_READLINE=1 rlwrap node"
単一の実行インスタンスに対する複数の REPL インスタンスの起動
単一のグローバルオブジェクトを共有しますが、個別の I/O インターフェースを持つ、単一の実行中の Node.js インスタンスに対して、複数の REPL インスタンスを作成して実行することができます。
たとえば、次の例では、stdin
、Unix ソケット、および TCP ソケットで個別の REPL を提供します。
import net from 'node:net'
import repl from 'node:repl'
import process from 'node:process'
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)
const net = require('node:net')
const repl = require('node: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)
コマンドラインからこのアプリケーションを実行すると、stdin で REPL が起動します。他の REPL クライアントは、Unix ソケットまたは TCP ソケットを介して接続できます。たとえば、telnet
は TCP ソケットへの接続に役立ち、socat
は Unix ソケットと TCP ソケットの両方に接続するために使用できます。
stdin ではなく Unix ソケットベースのサーバーから REPL を起動することにより、再起動することなく、長期間実行されている Node.js プロセスに接続することができます。
net.Server
およびnet.Socket
インスタンスを介して「フル機能」(terminal
) REPL を実行する例については、https://gist.github.com/TooTallNate/2209310を参照してください。
curl(1)
を介して REPL インスタンスを実行する例については、https://gist.github.com/TooTallNate/2053342を参照してください。
この例は、Node.js REPL が異なる I/O ストリームを使用してどのように開始できるかを示す教育目的のためだけに意図されています。本番環境またはセキュリティが懸念される状況では、追加の保護対策なしに使用するべきではありません。実世界のアプリケーションで REPL を実装する必要がある場合は、安全な入力メカニズムの使用やオープンネットワークインターフェースの回避など、これらのリスクを軽減する代替アプローチを検討してください。