Spec-Zone.ru › Node.js 14 LTS

Взаимодействие с интерпретатором (REPL)

Уровень стабильности: 2 - Стабильно

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

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

const repl = require('repl');

Архитектура и возможности

Модуль 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: Сбрасывает состояние 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.

    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();
  • Попытка использовать process.setUncaughtExceptionCaptureCallback() вызывает ошибку ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE.

Присвоение переменной _ (подчёркивание)
История
Версия Изменения
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

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

Добавлен в: v13.6.0

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

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

Записи принимаются как только нажата любая клавиша, не соответствующая поиску в обратном порядке. Отмена возможна нажатием Esc или 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.Интерфейс>

Экземпляры 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)

Добавлен в: 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])

Добавлен в: v0.1.91
  • preserveCursor <логическое>

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

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

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

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

replServer.clearBufferedCommand()

Добавлен в: v9.0.0

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

replServer.parseREPLKeyword(keyword[, rest])

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

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

replServer.setupHistory(historyPath, callback)

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

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

repl.builtinModules

Добавлен в: v14.5.0
  • <массив строк>

Список имен всех модулей Node.js, например, 'http'.

repl.start([options])

История
Версия Изменения
v13.4.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 <строка> Приглашение для ввода. По умолчанию: '> ' (с последующим пробелом).
    • 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. Командная строка 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.
    • 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 REPL

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 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"

Запуск нескольких экземпляров 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-v14.x/docs/api/repl.html

Spec-Zone.ru

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