REPL¶
Стабильность: 2 – Стабильная
АПИ является удовлетворительным. Совместимость с NPM имеет высший приоритет и не будет нарушена кроме случаев явной необходимости.
Модуль node:repl реализует цикл Read-Eval-Print-Loop (REPL): его можно запускать отдельно или встраивать в другие приложения. Подключение:
1 | |
1 | |
Дизайн и возможности¶
Модуль node:repl экспортирует класс repl.REPLServer. Во время работы экземпляры repl.REPLServer принимают построчный ввод пользователя, вычисляют его заданной функцией оценки и выводят результат. Ввод и вывод могут идти из stdin и в stdout или подключаться к любому stream Node.js.
Экземпляры repl.REPLServer поддерживают автодополнение, предпросмотр дополнений, простое редактирование строк в стиле Emacs, многострочный ввод, reverse-i-search в духе ZSH, поиск по подстроке в истории в духе ZSH, вывод с ANSI-оформлением, сохранение и восстановление состояния сессии REPL, восстановление после ошибок и настраиваемые функции оценки. Терминалы без ANSI и без редактирования в стиле Emacs переходят на ограниченный набор функций.
Команды и специальные клавиши¶
Поддерживаются такие специальные команды:
.break: при вводе многострочного выражения команда.break(или Ctrl+C) прерывает дальнейший ввод или обработку выражения..clear: сбрасываетcontextREPL в пустой объект и очищает текущий многострочный ввод..exit: закрывает поток ввода-вывода и завершает REPL..help: показать список специальных команд..save: сохранить текущую сессию REPL в файл:> .save ./file/to/save.js.load: загрузить файл в текущую сессию REPL.> .load ./file/to/load.js.editor: режим редактора (Ctrl+D — завершить, Ctrl+C — отмена).
1 2 3 4 5 6 7 8 9 10 11 | |
Сочетания клавиш в REPL:
- Ctrl+C: одно нажатие — как команда
.break; дважды на пустой строке — как.exit. - Ctrl+D: как
.exit. - Tab на пустой строке — глобальные и локальные (область видимости) переменные; при вводе текста — варианты автодополнения.
Привязки клавиш для reverse-i-search см. в reverse-i-search. Остальные — в привязках клавиш TTY.
Оценка по умолчанию¶
По умолчанию все экземпляры repl.REPLServer используют функцию оценки, которая вычисляет выражения JavaScript и даёт доступ к встроенным модулям Node.js. Поведение можно переопределить, передав другую функцию оценки при создании repl.REPLServer.
Выражения JavaScript¶
Встроенный оценщик поддерживает прямое вычисление выражений JavaScript:
1 2 3 4 5 6 | |
Если иное не ограничено блоками или функциями, переменные, объявленные явно или через const, let, var, оказываются в глобальной области видимости.
Глобальная и локальная область¶
Встроенный оценщик даёт доступ к переменным глобальной области. Переменную можно явно вывести в REPL, присвоив её объекту context у REPLServer:
1 2 3 4 | |
1 2 3 4 | |
Свойства context в REPL выглядят как локальные:
1 2 3 | |
По умолчанию свойства context не только для чтения. Чтобы задать глобальные только для чтения, используйте Object.defineProperty():
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 | |
Доступ к встроенным модулям Node.js¶
Встроенный оценщик подгружает встроенные модули Node.js в окружение REPL по мере использования. Например, если fs не объявлен иначе, ввод fs вычисляется по требованию как global.fs = require('node:fs').
1 | |
Глобальные необработанные исключения¶
REPL использует модуль domain, чтобы перехватывать все необработанные исключения сессии.
Такое использование domain в REPL даёт такие эффекты:
- Событие
'uncaughtException'для необработанных исключений испускается только в автономном REPL. Подписка на это событие внутри REPL, встроенного в другую программу Node.js, даётERR_INVALID_REPL_INPUT.
1 2 3 4 5 6 7 8 | |
- Вызов
process.setUncaughtExceptionCaptureCallback()выбрасываетERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE.
Переменная _ (подчёркивание)¶
По умолчанию оценщик присваивает результат последнего вычисленного выражения специальной переменной _. Явное присваивание _ отключает это поведение.
1 2 3 4 5 6 7 8 9 10 11 | |
Аналогично _error ссылается на последнюю ошибку, если она была. Явное присваивание _error отключает это поведение.
1 2 3 4 | |
Ключевое слово await¶
На верхнем уровне включена поддержка await.
1 2 3 4 5 6 7 8 9 10 | |
Известное ограничение: использование await в REPL нарушает лексическую область видимости для const.
Пример:
1 2 3 4 5 6 7 8 9 | |
Флаг --no-experimental-repl-await отключает await верхнего уровня в REPL.
Обратный инкрементальный поиск¶
REPL поддерживает двунаправленный reverse-i-search в духе ZSH. Запуск: Ctrl+R — назад, Ctrl+S — вперёд.
Повторяющиеся записи истории пропускаются.
Запись принимается при нажатии любой клавиши, не относящейся к поиску. Отмена — Esc или Ctrl+C.
Смена направления сразу ищет следующую запись в новом направлении от текущей позиции.
Пользовательские функции оценки¶
При создании repl.REPLServer можно передать свою функцию оценки — например для полностью кастомного REPL.
Функция оценки принимает четыре аргумента:
code<string>Код для выполнения (например1 + 1).context<Object>Контекст выполнения — глобальный JavaScript или контекст экземпляра REPL в зависимости отuseGlobal.replResourceName<string>Идентификатор ресурса REPL для текущей оценки (удобно для отладки).callback<Function>Вызывается по завершении оценки с двумя параметрами:- объект ошибки при ошибке оценки, иначе
null/undefined; - результат оценки (не используется, если передана ошибка).
Ниже REPL возводит число в квадрат; при нечисловом вводе выводится ошибка:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Восстанавливаемые ошибки¶
При нажатии Enter текущая строка передаётся в eval. Для многострочного ввода eval может возвращать экземпляр repl.Recoverable в callback:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Настройка вывода REPL¶
По умолчанию repl.REPLServer форматирует вывод через util.inspect() перед записью в переданный поток Writable (по умолчанию process.stdout). Опция showProxy в инспекции по умолчанию true, colors зависит от useColors у REPL.
Булево useColors при создании задаёт использование ANSI для цветного вывода util.inspect().
В автономном REPL можно менять параметры инспекции изнутри через inspect.replDefaults — зеркало defaultOptions из util.inspect().
1 2 3 4 5 6 7 | |
Чтобы полностью задать вывод repl.REPLServer, передайте свою функцию в опции writer. В примере весь текст переводится в верхний регистр:
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 11 | |
Класс: REPLServer¶
options<Object>|<string>См.repl.start()- Наследует:
<readline.Interface>
Экземпляры repl.REPLServer создаются через repl.start() или напрямую оператором new.
1 2 3 4 5 6 | |
1 2 3 4 5 6 | |
Событие: 'exit'¶
Событие 'exit' испускается при выходе из REPL: команда .exit, двойное Ctrl+C (SIGINT) или Ctrl+D ('end' на потоке ввода). Обработчик вызывается без аргументов.
1 2 3 4 | |
Событие: 'reset'¶
Событие 'reset' испускается при сбросе контекста REPL — при вводе .clear, кроме случая встроенного оценщика и repl.REPLServer с useGlobal: true. Обработчику передаётся только ссылка на context.
Обычно используют для повторной инициализации контекста:
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 10 | |
После запуска глобальную 'm' можно менять, а .clear вернёт начальное значение:
1 2 3 4 5 6 7 8 9 10 11 12 | |
replServer.defineCommand(keyword, cmd)¶
keyword<string>Ключевое слово команды (без ведущей.).cmd<Object>|<Function>Функция, вызываемая при обработке команды.
replServer.defineCommand() добавляет новые команды с префиксом . в экземпляр REPL. Ввод: . и keyword. cmd — либо Function, либо Object со свойствами:
help<string>Текст для.help(необязательно).action<Function>Выполняемая функция, опционально с одним строковым аргументом.
Пример двух новых команд:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Команды можно вызывать в REPL:
1 2 3 4 | |
replServer.displayPrompt([preserveCursor])¶
preserveCursor<boolean>
replServer.displayPrompt() готовит REPL к вводу: выводит настроенный prompt на новой строке в output и возобновляет приём в input.
При многострочном вводе вместо prompt выводится '|'.
При preserveCursor: true позиция курсора не сбрасывается в 0.
Обычно вызывается из action команд, зарегистрированных через replServer.defineCommand().
replServer.clearBufferedCommand()¶
replServer.clearBufferedCommand() очищает буферизованную, но ещё не выполненную команду. Обычно вызывается из action команд replServer.defineCommand().
replServer.setupHistory(historyConfig, callback)¶
Добавлено в: v11.10.0
historyConfig<Object>|<string>Путь к файлу истории. Если строка — это путь к файлу. Если объект, возможны свойства:filePath<string>путь к файлу историиsize<number>Максимум строк истории. Чтобы отключить историю, укажите0. Имеет смысл только еслиterminalравенtrue(пользователем или проверкойoutput), иначе кэш истории не инициализируется. По умолчанию:30.removeHistoryDuplicates<boolean>Приtrueпри добавлении строки, дублирующей более старую, старая удаляется. По умолчанию:false.onHistoryFileLoaded<Function>вызывается при готовности записи истории или при ошибкеerr<Error>repl<repl.REPLServer>
callback<Function>то же (необязателен, если заданonHistoryFileLoadedвhistoryConfig)err<Error>repl<repl.REPLServer>
Инициализирует файл истории для экземпляра REPL. При запуске node с интерактивным REPL файл истории создаётся по умолчанию; при программном создании REPL — нет. Используйте этот метод для файла истории при программной работе с REPL.
repl.builtinModules¶
Стабильность: 0 – устарело или набрало много негативных отзывов
Используйте module.builtinModules вместо этого API.
- Тип:
<string[]>
Список имён части модулей Node.js, например 'http'.
Доступна автоматическая миграция (исходники):
1 | |
repl.start([options])¶
Добавлено в: v0.1.91
options<Object>|<string>prompt<string>Приглашение ввода. По умолчанию:'> '(с пробелом в конце).input<stream.Readable>ПотокReadableдля ввода REPL. По умолчанию:process.stdin.output<stream.Writable>ПотокWritableдля вывода REPL. По умолчанию:process.stdout.terminal<boolean>Приtrueвыводoutputсчитается TTY. По умолчанию: проверкаisTTYуoutputпри создании.eval<Function>Функция оценки каждой строки ввода. По умолчанию: асинхронная обёртка надeval(). Ошибка сrepl.Recoverableозначает неполный ввод и запрос дополнительных строк. См. раздел пользовательские функции вычисления.useColors<boolean>Приtrueвстроенныйwriterдобавляет ANSI-цвета к выводу. При своёмwriterне действует. По умолчанию: проверка цветов наoutput, если у реплаterminalравенtrue.useGlobal<boolean>Приtrueвстроенный оценщик использует JavaScriptglobal, а не отдельный контекст REPL. CLInodeзадаётtrue. По умолчанию:false.ignoreUndefined<boolean>Приtrueвстроенный writer не выводит результат команды, если онundefined. По умолчанию:false.writer<Function>Форматирование вывода каждой команды перед записью вoutput. По умолчанию:util.inspect().completer<Function>Необязательно: своё автодополнение по Tab. Пример —readline.InterfaceCompleter.replMode<symbol>Режим оценщика: strict или sloppy. Значения:repl.REPL_MODE_SLOPPY— нестрогий режим.repl.REPL_MODE_STRICT— строгий режим (как'use strict'перед каждой строкой).
breakEvalOnSigint<boolean>Остановить оценку текущего кода приSIGINT(Ctrl+C). Несовместимо с пользовательскимeval. По умолчанию:false.preview<boolean>Печатать ли предпросмотр автодополнения и вывода. По умолчанию:trueсо встроеннымevalиfalseс пользовательскимeval. Еслиterminalложен, предпросмотра нет,previewне влияет.handleError<Function>Настройка обработки ошибок в REPL. Первый аргумент — исключение; синхронно вернуть одно из:'print'— вывести ошибку в поток вывода (по умолчанию).'ignore'— пропустить остальную обработку ошибки.'unhandled'— считать исключение полностью необработанным; оно уйдёт в глобальные обработчики, например'uncaughtException'.'unhandled'при уже закрытомREPLServerможет быть нежелателен — зависит от задачи.
- Возвращает:
<repl.REPLServer>
repl.start() создаёт и запускает экземпляр repl.REPLServer.
Если options — строка, она задаёт приглашение:
1 2 3 4 | |
1 2 3 4 | |
REPL Node.js¶
Сам Node.js использует node:repl для интерактивного выполнения JavaScript. Запуск: бинарник node без аргументов (или с -i):
1 2 3 4 5 6 7 8 9 10 11 | |
Переменные окружения¶
Поведение REPL Node.js можно настроить переменными окружения:
NODE_REPL_HISTORY: при корректном пути история REPL сохраняется в этот файл, а не в.node_repl_historyв домашнем каталоге. Пустая строка''отключает сохранение. Пробелы по краям обрезаются. В Windows пустые значения переменных недопустимы — отключите историю одним или несколькими пробелами.NODE_REPL_HISTORY_SIZE: сколько строк истории сохранять. Должно быть положительным числом. По умолчанию:1000.NODE_REPL_MODE:'sloppy'или'strict'. По умолчанию:'sloppy'— код работает не в строгом режиме.
Постоянная история¶
По умолчанию REPL сохраняет историю между сессиями в файле .node_repl_history в домашнем каталоге. Отключение: NODE_REPL_HISTORY=''.
Продвинутые редакторы строк¶
Для внешних построчных редакторов запустите Node.js с NODE_NO_READLINE=1. Основной и отладочный REPL войдут в «канонический» режим терминала, можно использовать rlwrap.
Например, в .bashrc:
1 | |
Несколько REPL в одном процессе¶
Можно запустить несколько экземпляров REPL в одном процессе Node.js с общим global (useGlobal: true) и разными интерфейсами ввода-вывода.
Ниже — отдельные REPL на stdin, Unix-сокете и TCP-сокете с общим global:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | |
Запуск из командной строки поднимает REPL на stdin. Другие клиенты могут подключаться через Unix- или TCP-сокет: для TCP удобен telnet, для Unix и TCP — socat.
REPL на Unix-сокете позволяет подключаться к долгоживущему процессу Node.js без перезапуска.
Примеры¶
Полноценный «терминальный» REPL поверх net.Server и net.Socket¶
Пример «полноценного» терминального REPL на net.Server и net.Socket.
Скрипт поднимает сервер на порту 1337, клиенты подключаются сокетом к экземпляру REPL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Клиент ниже подключается к этому серверу на порту 1337.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
Для проверки откройте два терминала: в одном node repl-server.js, в другом node repl-client.js.
Исходный код: https://gist.github.com/TooTallNate/2209310.
REPL поверх curl¶
Пример запуска экземпляра REPL через curl().
Скрипт поднимает HTTP-сервер на порту 8000, соединение можно установить через curl().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
При работающем скрипте подключитесь командой curl --no-progress-meter -sSNT. localhost:8000.
Предупреждение: пример только для демонстрации запуска REPL с разными потоками ввода-вывода. Не используйте в продакшене и там, где важна безопасность, без дополнительных мер. В реальных приложениях учитывайте риски: защищённый ввод, закрытые сетевые интерфейсы и т.д.
Исходный код: https://gist.github.com/TooTallNate/2053342.