REPL
Модуль repl предоставляет реализацию цикла "чтение-вычисление-печать-цикл" (REPL), доступную как отдельную программу, или для включения в другие приложения. К нему можно обратиться используя:
const repl = require('repl');
Конструкции и возможности
Модуль repl экспортирует класс repl.REPLServer. Во время работы экземпляры repl.REPLServer принимают отдельные строки пользовательского ввода, обрабатывают их согласно заданной пользовательской функции вычисления, а затем выводят результат. Ввод и вывод могут происходить из stdin и stdout, соответственно, или могут быть подключены к любому Node.js потоку.
Экземпляры 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 > var m = 2 undefined > m + 1 3
Если не указано иное в пределах блоков (например, { ... }) или функций, переменные, объявленные неявно или с помощью ключевого слова var, объявляются на уровне global области видимости.
Глобальная и локальная область видимости
По умолчанию, интерпретатор предоставляет доступ к любым переменным, которые существуют в глобальной области видимости. Можно явно предоставить переменную в 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 4
Явное присвоение значению _ отключит это поведение.
Настраиваемые функции вычисления
При создании нового repl.REPLServer, можно указать пользовательскую функцию вычисления. Это позволяет, например, реализовать полностью настраиваемые приложения REPL.
Ниже приведен гипотетический пример REPL, который выполняет перевод текста с одного языка на другой:
const repl = require('repl');
const Translator = require('translator').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 eval(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: function(name) {
this.lineParser.reset();
this.bufferedCommand = '';
console.log(`Hello, ${name}!`);
this.displayPrompt();
}
});
replServer.defineCommand('saybye', function() {
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 для принятия нового ввода.
При вводе многострочного ввода, вместо приглашения печатается многоточие.
Когда preserveCursor равно true, позиция курсора не будет сброшена до 0.
Метод replServer.displayPrompt предназначен для вызова из функции обработки команд, зарегистрированных с помощью метода replServer.defineCommand().
repl.start([options])
-
options<Объект> | <строка>-
prompt<строка> Приглашение для ввода, отображаемое по умолчанию. По умолчанию>. -
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(). Функция может возвращать ошибкуrepl.Recoverable, чтобы указать, что ввод был неполным, и запросить дополнительные строки. -
useColors<булево> Еслиtrue, указывает, что в функцию вывода по умолчанию должно добавляться ANSI-стилизация цвета вывода REPL. Если предоставлена пользовательская функцияwriter, это не влияет. По умолчанию устанавливается значениеterminalэкземпляра REPL. -
useGlobal<булево> Еслиtrue, указывает, что функция оценки по умолчанию будет использовать JavaScriptglobalкак контекст вместо создания нового отдельного контекста для экземпляра REPL. По умолчаниюfalse. -
ignoreUndefined<булево> Еслиtrue, указывает, что функция вывода по умолчанию не будет выводить результат команды, если он равенundefined. По умолчаниюfalse. -
writer<Функция> Функция форматирования вывода каждой команды перед записью вoutput. По умолчаниюutil.inspect(). -
completer<Функция> Необязательная функция для пользовательской автозамены Tab. См.readline.InterfaceCompleterдля примера. -
replMode- Флаг, определяющий, выполняет ли функция оценки по умолчанию все JavaScript-команды в строгом режиме, обычном режиме или гибридном режиме ("магический" режим). Допустимые значения:-
repl.REPL_MODE_SLOPPY- выполняет выражения в нестрогом режиме. -
repl.REPL_MODE_STRICT- выполняет выражения в строгом режиме. Эквивалентно предложению каждой команды repl с'use strict'. -
repl.REPL_MODE_MAGIC- пытается выполнить выражения в обычном режиме. Если выражения не могут быть обработаны, повторная попытка в строгом режиме.
-
-
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
> a = [1, 2, 3];
[ 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, что автоматически выполнит команды в строгом режиме, если они имеют соответствующий синтаксис.
Постоянная история
По умолчанию, интерпретатор команд 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. Это запустит основной и отладчик REPL в стандартных терминальных настройках, что позволит использовать их с 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 на стандартном вводе. Другие клиенты REPL могут подключиться через сокет Unix или сокет TCP. telnet, например, полезно для подключения к сокетам TCP, в то время как socat можно использовать для подключения к сокетам Unix и TCP.
Запуск REPL с сервера на основе сокета Unix вместо стандартного ввода позволяет подключиться к долгоработающему процессу Node.js без перезапуска.
Для примера работы «полнофункционального» (terminal) REPL через net.Server и net.Socket экземпляр, см.: https://gist.github.com/2209310
Для примера работы экземпляра REPL через 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-v6.x/docs/api/repl.html