REPL
Модуль repl предоставляет реализацию Read-Eval-Print-Loop (REPL), доступную как самостоятельную программу или для включения в другие приложения. К нему можно обратиться, используя:
const repl = require('repl');
Архитектура и возможности
Модуль repl экспортирует класс repl.REPLServer. Во время работы экземпляры repl.REPLServer будут принимать отдельные строки пользовательского ввода, оценивать их согласно пользовательской функции оценки и затем выводить результат. Ввод и вывод могут происходить из stdin и stdout, соответственно, или могут быть подключены к любому потоку Node.js stream.
Экземпляры repl.REPLServer поддерживают автоматическое завершение ввода, простую редактирование строк в стиле Emacs, многострочный ввод, вывод в стиле ANSI, сохранение и восстановление текущего состояния REPL, восстановление после ошибок и настраиваемые функции оценки.
Команды и специальные клавиши
Следующие специальные команды поддерживаются всеми экземплярами 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!'
>
Следующие комбинации клавиш в REPL имеют следующие эффекты:
-
<ctrl>-C- При нажатии один раз, имеет тот же эффект, что и команда.break. При двойном нажатии на пустой строке, имеет тот же эффект, что и команда.exit. -
<ctrl>-D- Имеет тот же эффект, что и команда.exit. -
<tab>- При нажатии на пустой строке отображает глобальные и локальные (в области видимости) переменные. При нажатии во время ввода другого ввода отображает соответствующие варианты автозаполнения.
По умолчанию оценка
По умолчанию все экземпляры repl.REPLServer используют функцию оценки, которая оценивает выражения JavaScript и предоставляет доступ к встроенным модулям Node.js. Это поведение по умолчанию может быть переопределено путем передачи альтернативной функции оценки при создании экземпляра repl.REPLServer.
Выражения JavaScript
По умолчанию интерпретатор поддерживает непосредственную оценку выражений JavaScript:
> 1 + 1 2 > const m = 2 undefined > m + 1 3
Если не указано иное в пределах блоков или функций, переменные, объявленные неявно или с использованием ключевых слов const, let, или var, объявляются на глобальном уровне.
Глобальная и локальная область видимости
По умолчанию интерпретатор предоставляет доступ к любым переменным, которые существуют в глобальной области видимости. Можно явно предоставить переменную для REPL, назначив её объекту context, связанному с каждым REPLServer. Например:
const repl = require('repl');
const msg = 'message';
repl.start('> ').context.m = msg;
Свойства объекта context появляются как локальные в REPL:
$ node repl_test.js > m 'message'
Свойства контекста по умолчанию не являются неизменяемыми. Чтобы указать неизменяемые глобальные свойства, свойства контекста должны быть определены с помощью Object.defineProperty():
const repl = require('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('fs')
> fs.createReadStream('./some/file');
Назначение переменной _ (ничего)
По умолчанию интерпретатор назначает результат последнего оцененного выражения специальной переменной _ (ничего). Явное задание _ значению отключит это поведение.
> [ 'a', 'b', 'c' ] [ 'a', 'b', 'c' ] > _.length 3 > _ += 1 Expression assignment to _ now disabled. 4 > 1 + 1 2 > _ 4
Пользовательские функции оценки
При создании нового repl.REPLServer может быть предоставлена пользовательская функция оценки. Это можно использовать, например, для реализации полностью настраиваемых приложений REPL.
Ниже приведен гипотетический пример REPL, который выполняет перевод текста с одного языка на другой:
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 });
Восстановимые ошибки
Пока пользователь вводит данные в приглашении 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;
}
Настройка вывода REPL
По умолчанию экземпляры repl.REPLServer форматируют вывод, используя метод util.inspect(), прежде чем записывать вывод в предоставленный поток записи (process.stdout по умолчанию). Параметр useColors типа boolean, при указании в момент создания, указывает дефолтному записывателю использовать коды ANSI для окраски вывода метода util.inspect().
Можно полностью настроить вывод экземпляра repl.REPLServer путем передачи новой функции с помощью опции writer при создании. Например, следующий пример просто преобразует любой вводимый текст в верхний регистр:
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();
}
Класс: REPLServer
Класс repl.REPLServer наследуется от класса readline.Interface. Экземпляры repl.REPLServer создаются с помощью метода repl.start() и не должны создаваться напрямую с помощью ключевого слова JavaScript new.
Событие: 'exit'
Событие 'exit' генерируется при выходе из REPL, либо при вводе команды .exit, либо при двойном нажатии пользователем на клавишу <ctrl>-C для сигнализации о SIGINT, или при нажатии <ctrl>-D для сигнализации о 'end' в потоке ввода. Функция обратного вызова вызывается без аргументов.
replServer.on('exit', () => {
console.log('Received "exit" event from repl!');
process.exit();
});
Событие: 'reset'
Событие 'reset' генерируется при сбросе контекста REPL. Это происходит всякий раз, когда ввод команды .clear за исключением случая, когда REPL использует интерпретатор по умолчанию и экземпляр repl.REPLServer был создан с опцией useGlobal установленной в true. Функция обратного вызова вызывается со ссылкой на объект context в качестве единственного аргумента.
Это можно использовать в первую очередь для повторной инициализации контекста REPL до некоторого предопределённого состояния, как показано в следующем простом примере:
const repl = require('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)
-
keyword<строка> Ключевое слово команды (без ведущего символа.). -
cmd<Объект> | <Функция> Функция, которая вызывается при обработке команды.
Метод replServer.defineCommand() используется для добавления новых команд, начинающихся с ., в экземпляр REPL. Такие команды вызываются написанием . за которым следует keyword. cmd — это либо функция, либо объект со следующими свойствами:
-
help<строка> Текст справки, который отображается при вводе.help(необязательно). -
action<Функция> Функция для выполнения, которая по желанию может принимать один строковый аргумент.
Следующий пример демонстрирует две новые команды, добавленные в экземпляр REPL:
const repl = require('repl');
const replServer = repl.start({ prompt: '> ' });
replServer.defineCommand('sayhello', {
help: 'Say hello',
action(name) {
this.bufferedCommand = '';
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])
-
preserveCursor<логическое значение>
Метод replServer.displayPrompt() подготавливает экземпляр REPL для ввода данных пользователем, печатая на новой строке в output конфигурированное значение prompt и возобновляя input для принятия нового ввода.
При вводе многострочного ввода вместо 'prompt' печатается многоточие.
Когда preserveCursor равно true, позиция курсора не будет сброшена к 0.
Метод replServer.displayPrompt предназначен в первую очередь для вызова из функции действия команд, зарегистрированных с помощью метода replServer.defineCommand().
repl.start([options])
-
options<Объект> | <строка>-
prompt<строка> Приглашение для ввода. По умолчанию:>. (с trailing пробелом). -
input<stream.Readable> Поток Readable для считывания ввода REPL. По умолчанию:process.stdin. -
output<stream.Writable> Поток Writable для записи вывода REPL. По умолчанию:process.stdout. -
terminal<логическое значение> Еслиtrue, указывает, чтоoutputдолжно обрабатываться как терминал TTY, и к нему должны записываться коды ANSI/VT100. По умолчанию: проверка значения свойстваisTTYв потокеoutputпри инициализации. -
eval<Функция> Функция, используемая для обработки каждой строки ввода. По умолчанию: асинхронная оболочка для JavaScript функцииeval(). Функцияevalможет возвращать ошибку сrepl.Recoverable, чтобы указать, что ввод был неполным, и запросить дополнительные строки. -
useColors<логическое значение> Еслиtrue, указывает, что функция по умолчанию дляwriterдолжна включать стили ANSI-цветов в вывод REPL. Если предоставлена пользовательская функцияwriter, это не повлияет. По умолчанию: значениеterminalэкземпляра REPL. -
useGlobal<логическое значение> Еслиtrue, указывает, что функция оценки по умолчанию будет использовать JavaScriptglobalв качестве контекста, а не создавать новый отдельный контекст для экземпляра REPL. Командная строка Node CLI устанавливает это значение в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. -
repl.REPL_MODE_MAGIC- Это значение устарело, так как улучшенное соответствие спецификации в V8 сделало магический режим ненужным. Теперь он эквивалентенrepl.REPL_MODE_SLOPPY(описано выше).
-
-
breakEvalOnSigint- Прекращение оценки текущего кода при полученииSIGINT, т.е. нажатииCtrl+C. Нельзя использовать вместе с пользовательской функциейeval. По умолчанию:false.
-
Метод repl.start() создаёт и запускает экземпляр repl.REPLServer.
Если options является строкой, то она задаёт приглашение для ввода:
const repl = require('repl');
// a Unix style prompt
repl.start('$ ');
Интерактивная оболочка Node.js
Сам Node.js использует модуль 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 можно настроить с помощью следующих переменных окружения:
-
NODE_REPL_HISTORY- Если задан допустимый путь, постоянная история REPL будет сохранена в указанном файле вместо.node_repl_historyв домашней папке пользователя. Установка этого значения в''отключит сохранение истории REPL. Пробелы будут удалены из значения. -
NODE_REPL_HISTORY_SIZE- Управляет количеством строк истории, которые будут сохранены, если история доступна. Должно быть положительным числом. По умолчанию:1000. -
NODE_REPL_MODE- Может быть любым изsloppy,strict, илиmagic.magicустарело и считается псевдонимомsloppy. По умолчанию:sloppy, что позволит запускать код без строгого режима.
Сохранение истории
По умолчанию, интерактивная оболочка Node.js будет сохранять историю между сессиями REPL, сохраняя ввод в файл .node_repl_history в домашней папке пользователя. Это можно отключить, задав переменную окружения NODE_REPL_HISTORY="".
NODE_REPL_HISTORY_FILE
NODE_REPL_HISTORY вместо него.Ранее в Node.js/io.js v2.x история REPL контролировалась с помощью переменной окружения NODE_REPL_HISTORY_FILE, и история сохранялась в формате JSON. Эта переменная теперь устарела, и старый файл истории REPL в формате JSON будет автоматически преобразован в упрощённый текстовый формат. Этот новый файл будет сохранён либо в домашней папке пользователя, либо в каталоге, определённом переменной NODE_REPL_HISTORY, как описано в разделе Параметры переменных окружения.
Использование интерактивной оболочки Node.js с расширенными редакторами строк
Для расширенных редакторов строк запустите Node.js с переменной окружения NODE_NO_READLINE=1. Это запустит основную и отладочную интерактивные оболочки в канонических терминальных настройках, что позволит использовать их с rlwrap.
Например, следующее можно добавить в файл .bashrc:
alias node="env NODE_NO_READLINE=1 rlwrap node"
Запуск нескольких экземпляров REPL для одного запущенного экземпляра
Возможен запуск и выполнение нескольких экземпляров REPL для одного работающего экземпляра Node.js, которые используют один и тот же объект global, но имеют отдельные интерфейсы ввода-вывода.
Например, следующий пример предоставляет отдельные REPL на stdin, сокете Unix и сокете TCP:
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);
Запуск этого приложения из командной строки запустит интерактивную оболочку на стандартном вводе. Другие клиенты REPL могут подключиться через сокет Unix или сокет TCP. telnet, например, полезен для подключения к сокетам TCP, а socat можно использовать для подключения к сокетам Unix и TCP.
Запустив интерактивную оболочку с сервера на основе сокета Unix вместо стандартного ввода, можно подключиться к долгоживущему процессу Node.js без его перезапуска.
Для примера запуска "полноценной" (terminal) интерактивной оболочки через net.Server и net.Socket экземпляр, см.: https://gist.github.com/2209310
Для примера запуска экземпляра интерактивной оболочки через curl(1), см.: https://gist.github.com/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-v8.x/docs/api/repl.html