REPL¶
АПИ является удовлетворительным. Совместимость с NPM имеет высший приоритет и не будет нарушена кроме случаев явной необходимости.
Модуль node:repl предоставляет реализацию Read-Eval-Print-Loop (REPL), которая доступна как отдельная программа или может быть включена в другие приложения. Доступ к нему можно получить, используя:
const repl = require('node:repl');
Дизайн и особенности¶
Модуль node:repl экспортирует класс repl.REPLServer . Во время работы экземпляры repl.REPLServer будут принимать отдельные строки пользовательского ввода, оценивать их в соответствии с заданной пользователем функцией оценки, а затем выводить результат. Вход и выход могут быть из stdin и stdout , соответственно, или могут быть подключены к любому Node.js stream.
Экземпляры repl.REPLServer поддерживают автоматическое завершение ввода, предварительный просмотр завершения, упрощенное редактирование строк в стиле Emacs, многострочный ввод, ZSH-подобный reverse-i-search, ZSH-подобный substring-based history search, вывод в стиле 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 для отмены).
1 2 3 4 5 6 7 8 9 10 11
> .editor // Entering editor mode (^D to finish, ^C to cancel) function welcome(name) return `Hello $!`; > welcome('Node.js User'); // ^D 'Hello Node.js User!' >
Следующие комбинации клавиш в REPL имеют такие специальные эффекты:
- Ctrl+C: При однократном нажатии имеет тот же эффект, что и команда .break . При двойном нажатии на пустой строке имеет тот же эффект, что и команда .exit .
- Ctrl+D: имеет тот же эффект, что и команда .exit .
- Tab: При нажатии на пустой строке отображает глобальные и локальные (область видимости) переменные. При нажатии во время ввода других данных отображает соответствующие опции автозавершения.
Связки клавиш, связанные с обратным поиском, см. в reverse-i-search . Обо всех остальных привязках клавиш см. в TTY keybindings.
Оценка по умолчанию¶
По умолчанию все экземпляры repl.REPLServer используют функцию оценки, которая оценивает выражения JavaScript и предоставляет доступ к встроенным модулям Node.js. Это поведение по умолчанию можно отменить, передав альтернативную функцию оценки при создании экземпляра repl.REPLServer .
Выражения JavaScript¶
Оценщик по умолчанию поддерживает прямую оценку выражений JavaScript:
1 2 3 4 5 6
> 1 + 1 2 > const m = 2 undefined > m + 1 3
Если в блоках или функциях нет другой области видимости, переменные, объявленные неявно или с помощью ключевых слов const , let или var , объявляются в глобальной области видимости.
Глобальная и локальная область видимости¶
Оценщик по умолчанию предоставляет доступ к любым переменным, существующим в глобальной области видимости. Можно явно объявить переменную в REPL, присвоив ее объекту context , связанному с каждым REPLServer :
1 2 3 4
const repl = require('node:repl'); const msg = 'message'; repl.start('> ').context.m = msg;
Свойства в объекте context отображаются как локальные в REPL:
1 2 3
$ node repl_test.js > m 'message'
Контекстные свойства по умолчанию не предназначены только для чтения. Чтобы указать глобальные объекты, доступные только для чтения, свойства контекста должны быть определены с помощью Object.defineProperty() :
1 2 3 4 5 6 7 8 9
const repl = require('node: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(‘node:fs’) .
> fs.createReadStream('./some/file');
Глобальные не пойманные исключения¶
В REPL используется модуль domain для перехвата всех неперехваченных исключений для этой сессии REPL.
Использование модуля domain в REPL имеет следующие побочные эффекты:
-
Не пойманные исключения вызывают событие ‘uncaughtException’ только в автономном REPL. Добавление слушателя этого события в REPL в другой программе Node.js приводит к ERR_INVALID_REPL_INPUT .
1 2 3 4 5 6 7 8 9 10
const r = repl.start(); r.write( 'process.on("uncaughtException", () => console.log("Foobar"));\n' ); // Выходной поток включает: // TypeError [ERR_INVALID_REPL_INPUT]: Слушатели для `uncaughtException` // не могут быть использованы в REPL r.close();
Присвоение переменной _ (подчеркивание).¶
Оценщик по умолчанию присваивает результат последнего вычисленного выражения специальной переменной _ (подчеркивание). Явная установка _ в значение отключает это поведение.
1 2 3 4 5 6 7 8 9 10 11
> [ 'a', 'b', 'c' ] [ 'a', 'b', 'c' ] > _.length 3 > _ += 1 Expression assignment to _ now disabled. 4 > 1 + 1 2 > _ 4
Аналогично, _error будет ссылаться на последнюю замеченную ошибку, если таковая имела место. Явная установка _error в значение отключит это поведение.
1 2 3 4
> throw new Error('foo'); Uncaught Error: foo > _error.message 'foo'
Ключевое слово await ¶
Поддержка ключевого слова await включена на верхнем уровне.
1 2 3 4 5 6 7 8 9 10
> await Promise.resolve(123) 123 > await Promise.reject(new Error('REPL await')) Uncaught Error: REPL await at REPL2:1:54 > const timeout = util.promisify(setTimeout); undefined > const old = Date.now(); await timeout(1000); console.log(Date.now() - old); 1002 undefined
Одно известное ограничение использования ключевого слова await в REPL заключается в том, что оно делает недействительным лексическое описание ключевых слов const и let .
1 2 3 4 5 6 7 8
> const m = await Promise.resolve(123) undefined > m 123 > const m = await Promise.resolve(234) undefined > m 234
—no-experimental-repl-await должен отключить ожидание на верхнем уровне в REPL.
Reverse-i-search¶
REPL поддерживает двунаправленный обратный поиск, подобный ZSH. Он запускается с помощью Ctrl+R для поиска назад и Ctrl+S для поиска вперед.
Дублирующиеся записи истории будут пропущены.
Записи будут приняты, как только будет нажата любая клавиша, не соответствующая обратному поиску. Отмена возможна при нажатии Esc или Ctrl+C.
При изменении направления поиск следующей записи осуществляется в ожидаемом направлении, начиная с текущей позиции.
Пользовательские функции оценки¶
Когда создается новый repl.REPLServer , может быть предоставлена пользовательская функция оценки. Это может быть использовано, например, для реализации полностью специализированных приложений REPL.
Ниже показан гипотетический пример REPL, выполняющего перевод текста с одного языка на другой:
1 2 3 4 5 6 7 8 9 10
const repl = require('node: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 в предоставленную функцию обратного вызова:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
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 в зависимости от опции REPL useColors .
Булева опция useColors может быть указана при построении, чтобы указать писателю по умолчанию использовать коды стиля ANSI для окраски вывода метода util.inspect() .
Если REPL запускается как автономная программа, можно также изменить параметры REPL inspection defaults внутри REPL с помощью свойства inspect.replDefaults , которое отражает defaultOptions из util.inspect() .
1 2 3 4 5 6 7
> util.inspect.replDefaults.compact = false; false > [1] [ 1 ] >
Для полной настройки вывода экземпляра repl.REPLServer передайте новую функцию для опции writer при построении. Следующий пример, например, просто преобразует любой входной текст в верхний регистр:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
const repl = require('node: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 создаются с помощью метода repl.start() или непосредственно с помощью ключевого слова JavaScript new .
1 2 3 4 5 6
const repl = require('node:repl'); const options = useColors: true >; const firstInstance = repl.start(options); const secondInstance = new repl.REPLServer(options);
Событие: ‘exit’ ¶
Событие ‘exit’ генерируется, когда REPL завершается либо при получении команды .exit на вход, либо при нажатии пользователем Ctrl+C дважды для сигнала SIGINT , либо при нажатии Ctrl+D для сигнала ‘end’ на входном потоке. Обратный вызов слушателя вызывается без аргументов.
1 2 3 4
replServer.on('exit', () => console.log('Received "exit" event from repl!'); process.exit(); >);
Событие: reset ¶
Событие reset возникает, когда контекст REPL сбрасывается. Это происходит всякий раз, когда команда .clear поступает на вход, если REPL не использует оценщик по умолчанию и экземпляр repl.REPLServer был создан с опцией useGlobal , установленной в true . Обратный вызов слушателя будет вызван со ссылкой на объект context в качестве единственного аргумента.
Это можно использовать в основном для повторной инициализации контекста REPL в некоторое заранее определенное состояние:
1 2 3 4 5 6 7 8 9 10
const repl = require('node:repl'); function initializeContext(context) context.m = 'test'; > const r = repl.start( prompt: '> ' >); initializeContext(r.context); r.on('reset', initializeContext);
Когда этот код выполняется, глобальная переменная ‘m’ может быть изменена, но затем возвращена к исходному значению с помощью команды .clear :
1 2 3 4 5 6 7 8 9 10 11 12
$ ./node example.js > m 'test' > m = 1 1 > m 1 > .clear Clearing context. > m 'test' >
replServer.defineCommand(keyword, cmd) ¶
- ключевое слово Ключевое слово команды (без ведущего символа . ).
- cmd
Метод replServer.defineCommand() используется для добавления новых команд с префиксом . в экземпляр REPL. Такие команды вызываются путем ввода символа . , за которым следует ключевое слово . Команда cmd является либо функцией , либо объектом со следующими свойствами:
В следующем примере показаны две новые команды, добавленные в экземпляр REPL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
const repl = require('node: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:
1 2 3 4
> .sayhello Node.js User Hello, Node.js User! > .saybye Goodbye!
replServer.displayPrompt([preserveCursor]) ¶
- preserveCursor
Метод replServer.displayPrompt() готовит экземпляр REPL к вводу данных пользователем, печатая настроенный prompt на новой строке в output и возобновляя input для приема нового ввода.
Если вводится многострочный ввод, вместо «подсказки» печатается многоточие.
Когда preserveCursor имеет значение true , размещение курсора не будет сброшено на 0 .
Метод replServer.displayPrompt предназначен в основном для вызова из функции действия для команд, зарегистрированных с помощью метода replServer.defineCommand() .
replServer.clearBufferedCommand() .¶
Метод replServer.clearBufferedCommand() очищает любую команду, которая была забуферизирована, но еще не выполнена. Этот метод предназначен для вызова из функции действия для команд, зарегистрированных с помощью метода replServer.defineCommand() .
replServer.parseREPLKeyword(keyword[, rest]) .¶
Стабильность: 0 – устарело или набрало много негативных отзывов
- ключевое слово потенциальное ключевое слово для разбора и выполнения
- rest любые параметры команды ключевого слова.
- Возвращает:
Внутренний метод, используемый для разбора и выполнения ключевых слов REPLServer . Возвращает true , если keyword является правильным ключевым словом, иначе false .
replServer.setupHistory(historyPath, callback) .¶
- historyPath путь к файлу истории
- callback вызывается, когда запись истории готова или при ошибке
- err
- repl
Инициализирует файл журнала истории для экземпляра REPL. При выполнении бинарного файла Node.js и использовании командной строки REPL файл истории инициализируется по умолчанию. Однако при создании REPL программным способом это не так. Используйте этот метод для инициализации файла журнала истории при программной работе с экземплярами REPL.
repl.builtinModules ¶
Список имен всех модулей Node.js, например, ‘http’ .
repl.start([options]) ¶
- options