REPL
Исходный код: lib/repl.js
Модуль node:repl предоставляет реализацию цикла «чтение-вычисление-печать-цикл» (REPL), доступную как самостоятельную программу, так и для включения в другие приложения. К нему можно получить доступ с помощью:
const repl = require('node:repl'); copy Архитектура и возможности
Модуль node:repl экспортирует класс repl.REPLServer. Во время работы экземпляры класса repl.REPLServer будут принимать отдельные строки пользовательского ввода, оценивать их в соответствии с определённой пользователем функцией оценки и затем выводить результат. Ввод и вывод могут происходить из stdin и stdout, соответственно, или могут быть подключены к любому потоку Node.js stream.
Экземпляры класса repl.REPLServer поддерживают автоматическое дополнение ввода, предварительный просмотр дополнений, простую редактирование строк в стиле Emacs, многострочный ввод, поиск по истории в стиле ZSH, поиск по подстрокам в стиле ZSH, вывод в стиле ANSI, сохранение и восстановление текущего состояния сессии REPL, восстановление после ошибок и настраиваемые функции оценки. Терминалы, которые не поддерживают стили ANSI и редактирование строк в стиле Emacs, автоматически переключаются на ограниченный набор функций.
Команды и специальные клавиши
Следующие специальные команды поддерживаются всеми экземплярами REPL:
-
.break: При вводе многострочного выражения, введите команду.break(или нажмите Ctrl+C), чтобы прервать дальнейший ввод или обработку этого выражения. -
.clear: Сбрасывает состояние REPLcontextв пустой объект и очищает любое вводимое многострочное выражение. -
.exit: Закрывает поток ввода-вывода, что приводит к завершению работы REPL. -
.help: Отображает этот список специальных команд. -
.save: Сохранить текущую сессию REPL в файл:> .save ./file/to/save.js -
.load: Загрузить файл в текущую сессию REPL.> .load ./file/to/load.js -
.editor: Перейти в режим редактирования (Ctrl+D для завершения, Ctrl+C для отмены).
> .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!'
> copy Следующие комбинации клавиш в REPL имеют следующие эффекты:
-
Ctrl+C: При нажатии один раз имеет тот же эффект, что и команда
.break. При нажатии дважды на пустой строке имеет тот же эффект, что и команда.exit. -
Ctrl+D: Имеет тот же эффект, что и команда
.exit. - Tab: При нажатии на пустой строке отображает глобальные и локальные (область видимости) переменные. При нажатии во время ввода другого ввода отображает соответствующие варианты автодополнения.
Для сочетаний клавиш, связанных с поиском по истории, см. reverse-i-search. Для всех других сочетаний клавиш см. Сочетания клавиш TTY.
По умолчанию
По умолчанию все экземпляры repl.REPLServer используют функцию оценки, которая оценивает выражения JavaScript и предоставляет доступ к встроенным модулям Node.js. Это поведение по умолчанию может быть переопределено путём передачи альтернативной функции оценки при создании экземпляра repl.REPLServer.
Выражения JavaScript
По умолчанию модуль оценки поддерживает непосредственную оценку выражений JavaScript:
> 1 + 1 2 > const m = 2 undefined > m + 1 3 copy
Если явно не указано иное в блоках или функциях, переменные, объявленные неявно или с использованием ключевых слов const, let, или var, объявляются на глобальном уровне.
Глобальная и локальная область видимости
По умолчанию модуль оценки предоставляет доступ к любым переменным, существующим в глобальной области видимости. Можно явно предоставить переменную для REPL, присвоив её объекту context , связанному с каждым экземпляром REPLServer:
const repl = require('node:repl');
const msg = 'message';
repl.start('> ').context.m = msg; copy Свойства объекта context появляются как локальные в REPL:
$ node repl_test.js > m 'message' copy
Свойства контекста по умолчанию не являются только для чтения. Для указания глобальных свойств только для чтения свойства контекста должны быть определены с помощью Object.defineProperty():
const repl = require('node:repl');
const msg = 'message';
const r = repl.start('> ');
Object.defineProperty(r.context, 'm', {
configurable: false,
enumerable: true,
value: msg,
}); copy Доступ к основным модулям Node.js
По умолчанию модуль оценки автоматически загрузит основные модули Node.js в среду REPL при использовании. Например, выражение fs будет вычисляться по требованию как global.fs = require('node:fs').
> fs.createReadStream('./some/file'); copy Глобальные необработанные исключения
REPL использует модуль domain для перехвата всех необработанных исключений для этой сессии REPL.
Это использование модуля domain в REPL имеет следующие побочные эффекты:
-
Необработанные исключения излучают только событие
'uncaughtException'в самостоятельном REPL. Добавление слушателя для этого события в REPL внутри другой программы Node.js приводит к ошибкеERR_INVALID_REPL_INPUT.const r = repl.start(); r.write('process.on("uncaughtException", () => console.log("Foobar"));\n'); // Output stream includes: // TypeError [ERR_INVALID_REPL_INPUT]: Listeners for `uncaughtException` // cannot be used in the REPL r.close(); copy -
Попытка использования
process.setUncaughtExceptionCaptureCallback()вызовет ошибкуERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE.
Присвоение переменной _ (подчёркивание)
По умолчанию модуль оценки присваивает результат последнего вычисленного выражения специальной переменной _ (подчёркивание). Явное присвоение значению _ отключит это поведение.
> [ 'a', 'b', 'c' ] [ 'a', 'b', 'c' ] > _.length 3 > _ += 1 Expression assignment to _ now disabled. 4 > 1 + 1 2 > _ 4 copy
Аналогично, _error будет ссылаться на последнюю ошибку, если она была.
> throw new Error('foo');
Uncaught Error: foo
> _error.message
'foo' copy Ключевое слово 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 copy Одно известное ограничение использования ключевого слова await в REPL заключается в том, что оно аннулирует лексическую область видимости ключевых слов const и let.
Например:
> const m = await Promise.resolve(123) undefined > m 123 > const m = await Promise.resolve(234) undefined > m 234 copy
--no-experimental-repl-await отключит поддержку ключевого слова `await` на верхнем уровне в REPL.
Поиск по истории
REPL поддерживает двунаправленный поиск по истории, аналогичный ZSH. Он активируется нажатием Ctrl+R для поиска назад и Ctrl+S для поиска вперёд.
Дублированные записи истории будут пропущены.
Записи принимаются, как только нажимается любая клавиша, не связанная с поиском по истории. Отмена возможна путём нажатия Esc или Ctrl+C.
Изменение направления немедленно выполняет поиск следующей записи в соответствующем направлении от текущей позиции.
Настраиваемые функции оценки
При создании нового экземпляра repl.REPLServer можно указать настраиваемую функцию оценки. Это можно использовать, например, для создания полностью настраиваемых приложений REPL.
Следующий пример иллюстрирует гипотетический пример REPL, который выполняет перевод текста с одного языка на другой:
const repl = require('node: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 }); copy Восстанавливаемые ошибки
В приглашении REPL нажатие Enter отправляет текущую строку ввода функции 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;
} copy Настройка вывода REPL
По умолчанию экземпляры repl.REPLServer форматируют вывод, используя метод util.inspect(), прежде чем записать вывод в предоставленный поток Writable (process.stdout по умолчанию). Опция проверки showProxy установлена в true по умолчанию, а опция colors установлена в true в зависимости от опции useColors REPL.
Логическое значение useColors можно указать при создании, чтобы направить стандартный писатель использовать коды стиля ANSI для раскрашивания вывода из метода util.inspect().
Если REPL запущен как автономная программа, то можно изменить значения по умолчанию проверки REPL изнутри REPL, используя свойство inspect.replDefaults, которое отражает свойство defaultOptions из util.inspect().
> util.inspect.replDefaults.compact = false; false > [1] [ 1 ] > copy
Для полной настройки вывода экземпляра repl.REPLServer передайте новую функцию в опцию writer при создании. В следующем примере, например, любой текст ввода просто преобразуется в верхний регистр:
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();
} copy Класс: REPLServer
-
options<Объект> | <строка> См.repl.start() - Расширяет: <readline.Interface>
Экземпляры repl.REPLServer создаются с помощью метода repl.start() или напрямую с использованием ключевого слова JavaScript new.
const repl = require('node:repl');
const options = { useColors: true };
const firstInstance = repl.start(options);
const secondInstance = new repl.REPLServer(options); copy Событие: 'exit'
Событие 'exit' генерируется при выходе из REPL, либо путем ввода команды .exit, либо при нажатии пользователем Ctrl+C дважды для сигнализации о SIGINT, или нажатием Ctrl+D для сигнализации о 'end' на потоке ввода. Обработчик события вызывается без аргументов.
replServer.on('exit', () => {
console.log('Received "exit" event from repl!');
process.exit();
}); copy Событие: 'reset'
Событие 'reset' генерируется при сбросе контекста REPL. Это происходит всякий раз, когда вводится команда .clear за исключением случаев, когда REPL использует стандартный оценщик и экземпляр repl.REPLServer был создан с параметром useGlobal установленным в значение true. Обработчик события вызывается с ссылкой на объект context в качестве единственного аргумента.
Это преимущественно используется для повторной инициализации контекста REPL до некоторого предварительно определённого состояния:
const repl = require('node:repl');
function initializeContext(context) {
context.m = 'test';
}
const r = repl.start({ prompt: '> ' });
initializeContext(r.context);
r.on('reset', initializeContext); copy При выполнении этого кода, глобальная переменная 'm' может быть изменена, но затем сброшена до своего начального значения с помощью команды .clear:
$ ./node example.js > m 'test' > m = 1 1 > m 1 > .clear Clearing context... > m 'test' > copy
replServer.defineCommand(keyword, cmd)
-
keyword<строка> Ключевое слово команды (без ведущего символа.). -
cmd<Объект> | <Функция> Функция, которая вызывается при обработке команды.
Метод replServer.defineCommand() используется для добавления новых команд, начинающихся с ., к экземпляру REPL. Такие команды вызываются набором символов . и последующего keyword. cmd это либо Function, либо Object с такими свойствами:
-
help<строка> Текст справки, который будет показан при вводе.help(Необязательно). -
action<Функция> Функция для выполнения, которая необязательно принимает один строковый аргумент.
Следующий пример показывает две новые команды, добавленные к экземпляру REPL:
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();
}); copy Новые команды затем могут быть использованы внутри экземпляра REPL:
> .sayhello Node.js User Hello, Node.js User! > .saybye Goodbye! copy
replServer.displayPrompt([preserveCursor])
-
preserveCursor<логическое значение>
Метод replServer.displayPrompt() подготавливает экземпляр REPL для ввода пользователя, выводя на новую строку в output конфигурируемый prompt и возобновляет input для приема нового ввода.
При вводе многострочного ввода вместо "prompt" выводится многоточие.
Когда preserveCursor имеет значение true, позиция курсора не будет сброшена к 0.
Метод replServer.displayPrompt предназначен в основном для вызова из функции действия команд, зарегистрированных с помощью метода replServer.defineCommand().
replServer.clearBufferedCommand()
Метод replServer.clearBufferedCommand() очищает любую буферизованную, но еще не выполненную команду. Этот метод предназначен в основном для вызова из функции обработки команд, зарегистрированных с помощью метода replServer.defineCommand().
replServer.parseREPLKeyword(keyword[, rest])
-
keyword<строка> потенциальное ключевое слово для обработки и выполнения -
rest<любое> любые параметры для команды ключевого слова - Возвращает: <логическое значение>
Внутренний метод, используемый для обработки и выполнения ключевых слов REPLServer . Возвращает true если keyword является допустимым ключевым словом, в противном случае false.
replServer.setupHistory(historyPath, callback)
-
historyPath<строка> путь к файлу истории -
callback<Функция> вызывается, когда операции записи истории завершены или при возникновении ошибки-
err<Ошибка> -
repl<repl.REPLServer>
-
Инициализирует файл журнала истории для экземпляра REPL. При выполнении бинарника Node.js и использовании командной строки REPL, файл истории инициализируется по умолчанию. Однако это не происходит при программированном создании REPL. Используйте этот метод для инициализации файла журнала истории при программированном работе с экземплярами REPL.
repl.builtinModules
Список имён всех модулей Node.js, например, 'http'.
repl.start([options])
-
options<Объект> | <строка>-
prompt<строка> Приглашение для ввода. По умолчанию:'> '(с trailing пробелом). -
input<stream.Readable> ПотокReadableдля чтения входных данных REPL. По умолчанию:process.stdin. -
output<stream.Writable> ПотокWritableдля записи вывода REPL. По умолчанию:process.stdout. -
terminal<логическое_значение> Еслиtrue, указывает, чтоoutputдолжен обрабатываться как терминал TTY. По умолчанию: проверка значения свойстваisTTYв потокеoutputпри создании. -
eval<Функция> Функция для вычисления каждой строки ввода. По умолчанию: асинхронная обертка для JavaScript-функцииeval(). Функцияevalможет возвращать ошибкуrepl.Recoverableдля указания неполного ввода и запроса дополнительных строк. -
useColors<логическое_значение> Еслиtrue, указывает, что функция по умолчаниюwriterдолжна включать форматирование ANSI-цветов для вывода REPL. Если предоставлена пользовательская функцияwriter, то это не имеет эффекта. По умолчанию: проверка поддержки цвета в потокеoutputесли значениеterminalэкземпляра REPL равноtrue. -
useGlobal<логическое_значение> Еслиtrue, указывает, что функция вычисления по умолчанию будет использовать JavaScriptglobalв качестве контекста вместо создания нового отдельного контекста для экземпляра REPL. Node CLI REPL устанавливает это значение вtrue. По умолчанию:false. -
ignoreUndefined<логическое_значение> Еслиtrue, указывает, что функция вывода по умолчанию не будет выводить результат команды, если он равенundefined. По умолчанию:false. -
writer<Функция> Функция для форматирования вывода каждой команды перед записью вoutput. По умолчанию:util.inspect(). -
completer<Функция> Необязательная функция для пользовательской автодополнения Tab. См.readline.InterfaceCompleterдля примера. -
replMode<символ> Флаг, указывающий, выполняет ли функция вычисления по умолчанию все команды JavaScript в строгом режиме или по умолчанию (нестрогом). Допустимые значения:-
repl.REPL_MODE_SLOPPYдля вычисления выражений в нестрогом режиме. -
repl.REPL_MODE_STRICTдля вычисления выражений в строгом режиме. Это эквивалентно добавлению префикса'use strict'к каждой строке REPL.
-
-
breakEvalOnSigint<логическое_значение> Останавливает вычисление текущего блока кода при полученииSIGINT, например, при нажатии Ctrl+C. Не может использоваться вместе с пользовательской функциейeval. По умолчанию:false. -
preview<логическое_значение> Определяет, будет ли REPL выводить подсказки автодополнения и предварительные просмотры вывода или нет. По умолчанию:trueдля функции вычисления по умолчанию иfalseв случае использования пользовательской функции вычисления. Еслиterminalложно, то предварительные просмотры отсутствуют, и значениеpreviewне имеет эффекта.
-
- Возвращает: <repl.REPLServer>
Метод repl.start() создает и запускает экземпляр repl.REPLServer.
Если options является строкой, то это указывает приглашение для ввода:
const repl = require('node:repl');
// a Unix style prompt
repl.start('$ '); copy Интерактивная оболочка 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 copy Настройки переменных среды
Различные параметры поведения интерактивной оболочки Node.js (REPL) можно настроить с помощью следующих переменных среды:
-
NODE_REPL_HISTORY: Если задан допустимый путь, постоянная история REPL будет сохранена в указанном файле вместо.node_repl_historyв домашней директории пользователя. Установка этого значения в''(пустая строка) отключит постоянную историю REPL. Пробелы в значении будут удалены. В Windows переменные среды с пустыми значениями недопустимы, поэтому установите это значение как один или несколько пробелов, чтобы отключить постоянную историю REPL. -
NODE_REPL_HISTORY_SIZE: Управляет тем, сколько строк истории будет сохранено, если история доступна. Должно быть положительным числом. По умолчанию:1000. -
NODE_REPL_MODE: Может быть либо'sloppy', либо'strict'. По умолчанию:'sloppy', что позволит запускать код в нестрогом режиме.
Постоянная история
По умолчанию интерактивная оболочка Node.js (REPL) сохранит историю между сеансами REPL, сохраняя ввод в файл .node_repl_history в домашней директории пользователя. Это можно отключить, установив переменную среды NODE_REPL_HISTORY=''.
Использование интерактивной оболочки Node.js (REPL) с расширенными редакторами строк
Для работы с расширенными редакторами строк запустите Node.js с переменной среды NODE_NO_READLINE=1. Это запустит основную и отладочную интерактивные оболочки (REPL) в стандартных терминальных настройках, что позволит использовать их с rlwrap.
Например, следующее можно добавить в файл .bashrc:
alias node="env NODE_NO_READLINE=1 rlwrap node" copy
Запуск нескольких экземпляров REPL на одном работающем экземпляре
Возможна создание и запуск нескольких экземпляров REPL на одном работающем экземпляре Node.js, которые используют один объект global, но имеют отдельные интерфейсы ввода-вывода.
Например, следующий пример предоставляет отдельные REPL на stdin, сокете Unix и сокете TCP:
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); copy Запуск этого приложения из командной строки запустит REPL на стандартном потоке ввода. Другие клиенты REPL могут подключиться через сокет Unix или сокет TCP. telnet, например, полезен для подключения к сокетам TCP, в то время как socat можно использовать для подключения к сокетам Unix и TCP.
Запуская REPL из сервера на основе сокета Unix вместо стандартного потока ввода, можно подключиться к долгоработающему процессу Node.js без его перезапуска.
Для примера запуска "полноценного" (terminal) REPL по net.Server и экземпляру net.Socket, см.: https://gist.github.com/TooTallNate/2209310.
Для примера запуска экземпляра REPL по curl(1), см.: https://gist.github.com/TooTallNate/2053342.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v20.x/docs/api/repl.html