Spec-Zone.ru › Node.js 10 LTS

REPL

Стабильность: 2 - Стабильно

Модуль repl предоставляет реализацию цикла «Чтение-Вычисление-Вывод» (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 - Сбрасывает контекст 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> - При нажатии на пустой строке отображает глобальные и локальные (области видимости) переменные. При нажатии во время ввода другого ввода отображает соответствующие варианты автодополнения.

По умолчанию

По умолчанию все экземпляры 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');

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

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

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

  • Необработанные исключения не генерируют событие 'uncaughtException'.
  • Попытка использовать 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

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

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

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

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

Событие: '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 <функция> Функция для выполнения, которая необязательно принимает один строковый аргумент.
END_OF_DOCUMENT_MARKER

Следующий пример демонстрирует две новые команды, добавленные в экземпляр 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 <boolean>

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

При вводе многострочного ввода вместо «подсказки» выводится многоточие.

Когда 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
  • keyword <string> потенциальное ключевое слово для анализа и выполнения
  • rest <any> любые параметры для команды ключевого слова
  • Возвращает: <boolean>
Уровень стабильности: 0 - Устарело.

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

repl.start([options])[src]

История
Версия Изменения
v10.0.0

Была удалена REPL_MAGIC_MODE replMode.

v5.8.0

Параметр options теперь является необязательным.

v0.1.91

Добавлено в: 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 и к нему должны быть записаны коды ANSI/VT100. По умолчанию: проверка значения свойства isTTY в потоке output при создании экземпляра.
    • eval <Function> Функция для оценки каждой строки ввода. По умолчанию: асинхронная обертка для JavaScript функции eval(). Функция eval может сообщать об ошибке с помощью repl.Recoverable для обозначения того, что вход был неполным, и запросить дополнительные строки.
    • useColors <boolean> Если true, указывает, что по умолчанию функция writer должна включать стили ANSI-цветов в вывод REPL. Если указана пользовательская функция writer, это не имеет эффекта. По умолчанию: значение terminal экземпляра REPL.
    • useGlobal <boolean> Если true, указывает, что по умолчанию функция оценки будет использовать JavaScript global в качестве контекста вместо создания нового отдельного контекста для экземпляра REPL. REPL командной строки Node устанавливает это значение в true. По умолчанию: false.
    • ignoreUndefined <boolean> Если true, указывает, что по умолчанию писатель не будет выводить возвращаемое значение команды, если оно равно undefined. По умолчанию: false.
    • writer <Function> Функция для форматирования вывода каждой команды перед записью в output. По умолчанию: util.inspect().
    • completer <Function> Необязательная функция для пользовательской автозамены Tab. См. readline.InterfaceCompleter для примера.
    • replMode <symbol> Флаг, определяющий, выполняет ли по умолчанию интерпретатор все команды JavaScript в режиме строгого соответствия или в обычном (нестрогом) режиме. Допустимые значения:

      • repl.REPL_MODE_SLOPPY — интерпретирует выражения в нестрогом режиме.
      • repl.REPL_MODE_STRICT — интерпретирует выражения в строгом режиме. Это эквивалентно добавлению 'use strict' перед каждой строкой REPL.
    • breakEvalOnSigint — Прекратить оценку текущего фрагмента кода при получении SIGINT, т.е. при нажатии Ctrl+C . Это нельзя использовать вместе с пользовательской функцией eval . По умолчанию: false.
  • Возвращает: <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 вместо stdin, можно подключиться к долго выполняющемуся процессу 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-v10.x/docs/api/repl.html

Spec-Zone.ru

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