Spec-Zone.ru › Node.js 12 LTS

REPL

Устойчивость: 2 - Стабильно

Исходный код: lib/repl.js

Модуль repl предоставляет реализацию цикла чтения-вычисления-печати (REPL), доступную как отдельную программу, так и для включения в другие приложения. К нему можно обратиться, используя:

const repl = require('repl');

Конструкции и особенности

Модуль repl экспортирует класс repl.REPLServer. Во время работы экземпляры класса repl.REPLServer будут принимать отдельные строки пользовательского ввода, оценивать их в соответствии с определённой пользователем функцией вычисления и затем выводить результат. Ввод и вывод могут происходить из stdin и stdout, соответственно, или могут быть подключены к любому потоку stream Node.js.

Экземпляры класса repl.REPLServer поддерживают автоматическое завершение ввода, предварительный просмотр завершения, упрощённый редактирование строк в стиле Emacs, многострочный ввод, поиск по истории в стиле ZSH, поиск по подстрокам в стиле ZSH, вывод в формате ANSI, сохранение и восстановление текущего состояния REPL-сессии, восстановление после ошибок и настраиваемые функции вычисления. Терминалы, не поддерживающие стили ANSI и редактирование строк в стиле Emacs, автоматически переключаются на ограниченный набор функций.

Команды и специальные клавиши

Следующие специальные команды поддерживаются всеми экземплярами REPL:

  • .break: При вводе многострочного выражения, ввод команды .break (или нажатие комбинации клавиш <ctrl>-C ) прервёт дальнейший ввод или обработку этого выражения.
  • .clear: Сбрасывает REPL context в пустой объект и очищает любой вводимый многострочный выражение.
  • .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>: При нажатии на пустой строке отображает глобальные и локальные (область видимости) переменные. При нажатии во время ввода других данных отображает соответствующие варианты автозаполнения.

Для клавишных сочетаний, связанных с поиском в обратном порядке, см. 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, объявляются в глобальной области.

Глобальная и локальная области видимости

По умолчанию оценщик предоставляет доступ к любым переменным, существующим в глобальной области видимости. Можно явно предоставить переменную 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');

Глобальные необработанные исключения

История
Версия Изменения
v12.3.0

Событие 'uncaughtException' теперь срабатывает, если REPL используется как отдельная программа.

REPL использует модуль domain для перехвата всех необработанных исключений для этой сессии REPL.

Это использование модуля domain в REPL имеет следующие побочные эффекты:

  • Необработанные исключения вызывают только событие 'uncaughtException' в автономном REPL. Добавление обработчика этого события в REPL внутри другой программы Node.js вызывает ERR_INVALID_REPL_INPUT.
  • Попытка использовать process.setUncaughtExceptionCaptureCallback() вызывает ошибку ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE.

Как отдельная программа:

process.on('uncaughtException', () => console.log('Uncaught'));

throw new Error('foobar');
// Uncaught

При использовании в другом приложении:

process.on('uncaughtException', () => console.log('Uncaught'));
// TypeError [ERR_INVALID_REPL_INPUT]: Listeners for `uncaughtException`
// cannot be used in the REPL

throw new Error('foobar');
// Thrown:
// Error: foobar

Присвоение переменной _ (нижнее подчеркивание)

История
Версия Изменения
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');
Error: foo
> _error.message
'foo'

await ключевое слово

С опцией командной строки --experimental-repl-await включена экспериментальная поддержка ключевого слова await.

> await Promise.resolve(123)
123
> await Promise.reject(new Error('REPL await'))
Error: REPL await
    at repl:1:45
> const timeout = util.promisify(setTimeout);
undefined
> const old = Date.now(); await timeout(1000); console.log(Date.now() - old);
1002
undefined

Поиск в обратном порядке

Добавлен в: v12.17.0

REPL поддерживает двунаправленный поиск в обратном порядке, аналогичный ZSH. Он запускается нажатием <ctrl> + R для поиска назад и <ctrl> + S для поиска вперёд.

Дублированные записи истории будут пропущены.

Записи принимаются, как только нажимается любая кнопка, не связанная с обратным поиском. Отмена возможна нажатием escape или <ctrl> + C.

Изменение направления немедленно ищет следующую запись в ожидаемом направлении от текущей позиции.

Пользовательские функции вычисления

При создании нового экземпляра 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(), прежде чем записывать вывод в предоставленный поток 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
]
>

Для полной настройки вывода экземпляра 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

Добавлен в: v0.1.91
  • options <Объект> | <строка> См. repl.start()
  • Расширяет: <readline.Interface>

Экземпляры repl.REPLServer создаются с помощью метода repl.start() или непосредственно с помощью ключевого слова JavaScript new.

const repl = require('repl');

const options = { useColors: true };

const firstInstance = repl.start(options);
const secondInstance = new repl.REPLServer(options);

Событие: 'exit'

Добавлен в: v0.7.7

Событие 'exit' генерируется при выходе из REPL, либо в результате ввода команды .exit, либо при нажатии пользователем клавиши <ctrl>-C дважды для сигнализации о SIGINT, либо при нажатии клавиши <ctrl>-D для сигнализации о 'end' в потоке ввода. Функция-обработчик вызывается без аргументов.

replServer.on('exit', () => {
  console.log('Received "exit" event from repl!');
  process.exit();
});

Событие: 'reset'

Добавлен в: v0.11.0

Событие '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)

Added in: v0.3.0
  • keyword <строка> Ключевое слово команды (без ведущего символа .).
  • cmd <Объект> | <Функция> Функция, которая вызывается при обработке команды.

Метод replServer.defineCommand() используется для добавления новых команд, начинающихся с префикса ., в экземпляр REPL. Такие команды вызываются набором символов . за которым следует keyword. Значение cmd является либо Function, либо Object со следующими свойствами:

  • help <строка> Текст справки, который отображается при вводе .help (Необязательно).
  • action <Функция> Функция для выполнения, которая может принимать один строковый аргумент.

Следующий пример демонстрирует добавление двух новых команд в экземпляр REPL:

const repl = require('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])

Added in: v0.1.91
  • preserveCursor <логическое значение>

Метод replServer.displayPrompt() подготавливает экземпляр REPL для ввода пользователем, выводит на новую строку в output сконфигурированный prompt и возобновляет input для приема нового ввода.

При вводе многострочного ввода вместо 'prompt' выводится многоточие.

Если preserveCursor равно true, позиция курсора не будет сброшена до 0.

Метод replServer.displayPrompt предназначен для вызова из функции действия для команд, зарегистрированных с помощью метода replServer.defineCommand().

replServer.clearBufferedCommand()

Added in: v9.0.0

Метод replServer.clearBufferedCommand() очищает любую команду, которая была буферизована, но еще не выполнена. Этот метод предназначен для вызова из функции действия для команд, зарегистрированных с помощью метода replServer.defineCommand().

replServer.parseREPLKeyword(keyword[, rest])

Added in: v0.8.9Deprecated since: v9.0.0
Устойчивость: 0 - Устарело.
  • keyword <строка> потенциальное ключевое слово для разбора и выполнения
  • rest <любое> любые параметры для команды ключевого слова
  • Возвращает: <логическое значение>

Внутренний метод, используемый для разбора и выполнения ключевых слов REPLServer. Возвращает true, если keyword является допустимым ключевым словом, в противном случае false.

replServer.setupHistory(historyPath, callback)

Added in: v11.10.0
  • historyPath <строка> путь к файлу истории
  • callback <Функция> вызывается при готовности записи истории или при ошибке
    • err <Ошибка>
    • repl <repl.REPLServer>

Инициализирует файл журнала истории для экземпляра REPL. При выполнении двоичного файла Node.js и использовании REPL командной строки файл истории инициализируется по умолчанию. Однако это не так при программатическом создании REPL. Используйте этот метод для инициализации файла журнала истории при программатической работе с экземплярами REPL.

repl.start([options])

История изменений
Версия Изменения
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

  • options <Объект> | <строка>
    • prompt <строка> Приглашение для ввода. По умолчанию: '> ' (с trailing space).
    • 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, указывает, что функция оценки по умолчанию будет использовать JavaScript global в качестве контекста, а не создавать новый отдельный контекст для экземпляра REPL. REPL командной строки Node устанавливает это значение в 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('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. Пробелы будут удалены из значения. В Windows пустые значения переменных среды недопустимы, поэтому установите эту переменную в одно или несколько пробелов, чтобы отключить сохранение истории REPL.
  • NODE_REPL_HISTORY_SIZE: Управляет тем, сколько строк истории будет сохранено, если история доступна. Должно быть положительным числом. По умолчанию: 1000.
  • NODE_REPL_MODE: Может быть либо 'sloppy', либо 'strict'. По умолчанию: 'sloppy', что позволит запускать код без строгого режима.

Постоянная история

По умолчанию, интерпретатор команд Node.js сохранит историю между сеансами REPL, сохраняя ввод в файл .node_repl_history в домашнем каталоге пользователя. Это можно отключить, установив переменную среды 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/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-v12.x/docs/api/repl.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API