Readline
Исходный код: lib/readline.js
Модуль node:readline предоставляет интерфейс для чтения данных из потока Readable (например, из process.stdin) по одной строке за раз.
Чтобы использовать API на основе промисов:
MJS модули
import * as readline from 'node:readline/promises';
CJS модули
const readline = require('node:readline/promises'); Чтобы использовать API на основе обратных вызовов и синхронизации:
MJS модули
import * as readline from 'node:readline';
CJS модули
const readline = require('node:readline'); Следующий простой пример демонстрирует базовое использование модуля node:readline.
MJS модули
import * as readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';
const rl = readline.createInterface({ input, output });
const answer = await rl.question('What do you think of Node.js? ');
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
CJS модули
const readline = require('node:readline');
const { stdin: input, stdout: output } = require('node:process');
const rl = readline.createInterface({ input, output });
rl.question('What do you think of Node.js? ', (answer) => {
// TODO: Log the answer in a database
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
}); После запуска этого кода приложение Node.js не будет завершено до тех пор, пока не будет закрыт readline.Interface, так как интерфейс ожидает получения данных из потока input.
Класс: InterfaceConstructor
- Расширяет: <EventEmitter>
Экземпляры класса InterfaceConstructor создаются с помощью метода readlinePromises.createInterface() или readline.createInterface(). Каждый экземпляр связан с одним потоком input Readable и одним потоком output Writable. Поток output используется для вывода подсказок для ввода пользователя, которые поступают в поток input.
Событие: 'close'
Событие 'close' генерируется при наступлении одного из следующих событий:
- Вызов метода
rl.close()и отказ экземпляраInterfaceConstructorот управления потокамиinputиoutput; - Поток
inputполучает событие'end'; - Поток
inputполучает Ctrl+D для сигнализации об окончании передачи (EOT); - Поток
inputполучает Ctrl+C для сигнализации оSIGINTи при отсутствии обработчика события'SIGINT'для экземпляраInterfaceConstructor.
Функция-обработчик вызывается без передачи каких-либо аргументов.
Экземпляр InterfaceConstructor завершается после генерации события 'close'.
Событие: 'line'
Событие 'line' генерируется всякий раз, когда поток input получает входную строку с символом конца строки (\n, \r, или \r\n). Это обычно происходит при нажатии пользователем Enter или Return.
Событие 'line' также генерируется, если новые данные были прочитаны из потока, и этот поток завершается без конечного маркера конца строки.
Функция-обработчик вызывается со строкой, содержащей единственную полученную строку ввода.
rl.on('line', (input) => {
console.log(`Received: ${input}`);
}); copy Событие: 'history'
Событие 'history' генерируется всякий раз, когда массив истории изменяется.
Функция-обработчик вызывается с массивом, содержащим массив истории. Он будет отражать все изменения, добавленные и удалённые строки из-за historySize и removeHistoryDuplicates.
Основная цель — позволить обработчику сохранять историю. Также обработчик может изменить объект истории. Это может быть полезно для предотвращения добавления определённых строк в историю, например, пароля.
rl.on('history', (history) => {
console.log(`Received: ${history}`);
}); copy Событие: 'pause'
Событие 'pause' генерируется при наступлении одного из следующих событий:
- Поток
inputприостановлен. - Поток
inputне приостановлен и получает событие'SIGCONT'. (См. события'SIGTSTP'и'SIGCONT'.)
Функция-обработчик вызывается без передачи каких-либо аргументов.
rl.on('pause', () => {
console.log('Readline paused.');
}); copy Событие: 'resume'
Событие 'resume' генерируется всякий раз, когда поток input возобновляется.
Функция-обработчик вызывается без передачи каких-либо аргументов.
rl.on('resume', () => {
console.log('Readline resumed.');
}); copy Событие: 'SIGCONT'
Событие 'SIGCONT' генерируется, когда процесс Node.js, ранее переведённый в фоновый режим с помощью Ctrl+Z (т.е. SIGTSTP), возвращается в фоновый режим с помощью fg(1p).
Если поток input был приостановлен до запроса SIGTSTP, это событие не будет сгенерировано.
Функция-обработчик вызывается без передачи каких-либо аргументов.
rl.on('SIGCONT', () => {
// `prompt` will automatically resume the stream
rl.prompt();
}); copy Событие 'SIGCONT' не поддерживается в Windows.
Событие: 'SIGINT'
Событие 'SIGINT' генерируется всякий раз, когда поток input получает вход Ctrl+C, обычно известный как SIGINT. Если нет обработчиков событий 'SIGINT' зарегистрированы, когда поток input получает SIGINT, будет сгенерировано событие 'pause'.
Функция-обработчик вызывается без передачи каких-либо аргументов.
rl.on('SIGINT', () => {
rl.question('Are you sure you want to exit? ', (answer) => {
if (answer.match(/^y(es)?$/i)) rl.pause();
});
}); copy Событие: 'SIGTSTP'
Событие 'SIGTSTP' генерируется, когда поток input получает вход Ctrl+Z, обычно известный как SIGTSTP. Если нет обработчиков событий 'SIGTSTP' зарегистрированы, когда поток input получает SIGTSTP, процесс Node.js будет переведён в фоновый режим.
При возобновлении программы с помощью fg(1p), будут сгенерированы события 'pause' и 'SIGCONT'. Их можно использовать для возобновления потока input.
События 'pause' и 'SIGCONT' не будут сгенерированы, если поток input был приостановлен до перевода процесса в фоновый режим.
Функция-обработчик вызывается без передачи каких-либо аргументов.
rl.on('SIGTSTP', () => {
// This will override SIGTSTP and prevent the program from going to the
// background.
console.log('Caught SIGTSTP.');
}); copy Событие 'SIGTSTP' не поддерживается в Windows.
rl.close()
Метод rl.close() закрывает экземпляр InterfaceConstructor и отказывается от управления потоками input и output. При вызове будет сгенерировано событие 'close'.
Вызов rl.close() не останавливает немедленно другие события (включая 'line'), генерируемые экземпляром InterfaceConstructor.
rl.pause()
Метод rl.pause() приостанавливает поток input, позволяя его возобновить в случае необходимости.
Вызов rl.pause() не останавливает немедленно другие события (включая 'line' ), генерируемые экземпляром InterfaceConstructor.
rl.prompt([preserveCursor])
-
preserveCursor<boolean> Еслиtrue, предотвращает сброс позиции курсора до0.
Метод rl.prompt() записывает конфигурированные значения экземпляра InterfaceConstructor в новую строку в output, чтобы предоставить пользователю новое место для ввода.
При вызове rl.prompt() возобновит поток input , если он был приостановлен.
Если экземпляр InterfaceConstructor был создан с output установленным в null или undefined, приглашение не будет выведено.
rl.resume()
Метод rl.resume() возобновляет поток input , если он был приостановлен.
rl.setPrompt(prompt)
-
prompt<string>
Метод rl.setPrompt() устанавливает приглашение, которое будет выведено в output при каждом вызове rl.prompt().
rl.getPrompt()
- Возвращает: <string> текущую строку приглашения
Метод rl.getPrompt() возвращает текущее приглашение, используемое rl.prompt().
rl.write(data[, key])
Метод rl.write() записывает либо data, либо последовательность нажатий клавиш, определённую key, в output. Аргумент key поддерживается только для текстовых терминалов ТTY. См. Клавиши ТTY для списка комбинаций клавиш.
Если указан key, data игнорируется.
При вызове rl.write() возобновит поток input , если он был приостановлен.
Если экземпляр InterfaceConstructor был создан с output установленным в null или undefined, data и key не будут записаны.
rl.write('Delete this!');
// Simulate Ctrl+U to delete the line written previously
rl.write(null, { ctrl: true, name: 'u' }); copy Метод rl.write() запишет данные в readline Interface как будто они были предоставлены пользователем.
rl[Symbol.asyncIterator]()
- Возвращает: <AsyncIterator>
Создает объект AsyncIterator, который итерируется по каждой строке в потоке ввода как строке. Этот метод позволяет асинхронную итерацию по объектам InterfaceConstructor через циклы for await...of.
Ошибки в потоке ввода не передаются.
Если цикл завершен с помощью break, throw, или return, будет вызван rl.close(). Другими словами, итерация по InterfaceConstructor всегда полностью потребляет поток ввода.
Производительность не соответствует традиционному API событий 'line'. Используйте 'line' для приложений, чувствительных к производительности.
async function processLineByLine() {
const rl = readline.createInterface({
// ...
});
for await (const line of rl) {
// Each line in the readline input will be successively available here as
// `line`.
}
} copy readline.createInterface() начнёт потреблять поток ввода после вызова. Наличие асинхронных операций между созданием интерфейса и асинхронной итерацией может привести к пропускам строк.
rl.line
Текущие данные ввода, обрабатываемые узлом.
Это может быть полезно при сборе ввода из потока TTY для получения текущего обработанного значения до выдачи события line. После выдачи события line, это свойство будет пустой строкой.
Обратите внимание, что изменение значения во время выполнения экземпляра может иметь непредвиденные последствия, если rl.cursor также не контролируется.
Если вы не используете поток TTY для ввода, используйте событие 'line'.
Один из возможных вариантов использования:
const values = ['lorem ipsum', 'dolor sit amet'];
const rl = readline.createInterface(process.stdin);
const showResults = debounce(() => {
console.log(
'\n',
values.filter((val) => val.startsWith(rl.line)).join(' '),
);
}, 300);
process.stdin.on('keypress', (c, k) => {
showResults();
}); copy
rl.cursor
Положение курсора относительно rl.line.
Это отслеживает, где текущий курсор находится в строке ввода при чтении ввода из потока TTY. Положение курсора определяет часть строки ввода, которая будет изменена при обработке ввода, а также колонку, где будет отображён курсор терминала.
rl.getCursorPos()
- Возвращает: <Объект>
Возвращает реальное положение курсора относительно приглашения и строки ввода. В расчёты включены длинные строки ввода (перенос), а также приглашения с несколькими строками.
API обещаний
Класс: readlinePromises.Interface
- Расширяет: <readline.InterfaceConstructor>
Экземпляры класса readlinePromises.Interface создаются с помощью метода readlinePromises.createInterface(). Каждый экземпляр связан с одним потоком input Readable и одним потоком output Writable. Поток output используется для вывода приглашений для ввода пользователя, которые поступают и считываются из потока input.
rl.question(query[, options])
-
query<строка> Заявление или вопрос, который будет выведен вoutput, добавленный перед приглашением. -
options<Объект>-
signal<AbortSignal> Позволяет отменитьquestion()с помощьюAbortSignal.
-
- Возвращает: <Обещание> Обещание, которое выполняется со вводом пользователя в ответ на
query.
Метод rl.question() отображает query, записывая его в output, ожидает ввода пользователя в input, а затем вызывает функцию callback, передавая предоставленный ввод в качестве первого аргумента.
При вызове rl.question() возобновит поток input если он был приостановлен.
Если readlinePromises.Interface был создан с output установленным в null или undefined, то query не будет выведен.
Если вопрос вызван после rl.close(), он возвращает отклоненное обещание.
Пример использования:
const answer = await rl.question('What is your favorite food? ');
console.log(`Oh, so your favorite food is ${answer}`); copy Использование AbortSignal для отмены вопроса.
const signal = AbortSignal.timeout(10_000);
signal.addEventListener('abort', () => {
console.log('The food question timed out');
}, { once: true });
const answer = await rl.question('What is your favorite food? ', { signal });
console.log(`Oh, so your favorite food is ${answer}`); copy Класс: readlinePromises.Readline
new readlinePromises.Readline(stream[, options])
-
stream<stream.Writable> Поток TTY. -
options<Объект>-
autoCommit<логическое> Еслиtrue, нет необходимости вызыватьrl.commit().
-
rl.clearLine(dir)
-
dir<целое число>-
-1: слева от курсора -
1: справа от курсора -
0: вся строка
-
- Возвращает: this
Метод rl.clearLine() добавляет в список ожидаемых действий действие, которое очищает текущую строку связанного stream в указанном направлении, определенном dir. Вызовите rl.commit() для отображения эффекта этого метода, если autoCommit: true не был передан в конструктор.
rl.clearScreenDown()
- Возвращает: this
Метод rl.clearScreenDown() добавляет в список ожидаемых действий действие, которое очищает связанный поток от текущей позиции курсора вниз. Вызовите rl.commit() для отображения эффекта этого метода, если autoCommit: true не был передан в конструктор.
rl.commit()
- Возвращает: <Обещание>
Метод rl.commit() отправляет все ожидаемые действия связанному stream и очищает внутренний список ожидаемых действий.
rl.cursorTo(x[, y])
-
x<целое число> -
y<целое число> - Возвращает: this
Метод rl.cursorTo() добавляет в список ожидаемых действий действие, которое перемещает курсор в указанную позицию в связанном stream. Вызовите rl.commit() для отображения эффекта этого метода, если autoCommit: true не был передан в конструктор.
rl.moveCursor(dx, dy)
-
dx<целое число> -
dy<целое число> - Возвращает: this
Метод rl.moveCursor() добавляет в список ожидаемых действий действие, которое перемещает курсор *относительно* его текущей позиции в связанном stream. Вызовите rl.commit() для отображения эффекта этого метода, если autoCommit: true не был передан в конструктор.
rl.rollback()
- Возвращает: this
Метод rl.rollback очищает внутренний список ожидаемых действий без его отправки в связанный stream.
readlinePromises.createInterface(options)
-
options<Объект>-
input<stream.Readable> Поток Readable для прослушивания. Этот параметр обязателен. -
output<stream.Writable> Поток Writable для записи данных readline. -
completer<Функция> Необязательная функция для автодополнения. -
terminal<boolean>trueесли потокиinputиoutputдолжны обрабатываться как TTY и к ним должны писаться коды ANSI/VT100. По умолчанию: проверкаisTTYв потокеoutputпри создании экземпляра. -
history<string[]> Начальный список строк истории. Этот параметр имеет смысл только еслиterminalустановлен вtrueпользователем или внутреннимoutputконтролем, иначе механизм кэширования истории не инициализируется. По умолчанию:[]. -
historySize<number> Максимальное количество строк истории. Для отключения истории установите это значение в0. Этот параметр имеет смысл только еслиterminalустановлен вtrueпользователем или внутреннимoutputконтролем, иначе механизм кэширования истории не инициализируется. По умолчанию:30. -
removeHistoryDuplicates<boolean> Еслиtrue, при добавлении новой строки в список истории, дублирующей более старую, старая строка удаляется из списка. По умолчанию:false. -
prompt<строка> Строка запроса. По умолчанию:'> '. -
crlfDelay<число> Если задержка между\rи\nпревышаетcrlfDelayмиллисекунд,\rи\nбудут обрабатываться как отдельный ввод конца строки.crlfDelayбудет приведено к числу не меньше100. Можно установить вInfinity, в этом случае\rи\nвсегда будут рассматриваться как одна новая строка (что может быть уместно для чтения файлов с разделителем строк\r\n). По умолчанию:100. -
escapeCodeTimeout<число> Длительность ожиданияreadlinePromisesсимвола (при чтении неоднозначной последовательности клавиш, которая может как сформировать полную последовательность клавиш с уже прочитанным вводом, так и потребовать дополнительного ввода для завершения более длинной последовательности клавиш) в миллисекундах. По умолчанию:500. -
tabSize<целое> Количество пробелов, равное одной табуляции (минимум 1). По умолчанию:8.
-
- Возвращает: <readlinePromises.Interface>
Метод readlinePromises.createInterface() создает новый экземпляр readlinePromises.Interface.
const readlinePromises = require('node:readline/promises');
const rl = readlinePromises.createInterface({
input: process.stdin,
output: process.stdout,
}); copy После создания экземпляра readlinePromises.Interface, в большинстве случаев нужно прослушать событие 'line':
rl.on('line', (line) => {
console.log(`Received: ${line}`);
}); copy Если для этого экземпляра terminal установлено значение true, то поток output получит наилучшую совместимость, если он определит свойство output.columns и выведет событие 'resize' в потоке output, если или когда количество столбцов изменится (process.stdout делает это автоматически, когда это TTY).
Использование функции completer
Функция completer принимает текущую введенную пользователем строку в качестве аргумента и возвращает Array с 2 элементами:
Arrayс совпадающими элементами для автодополнения.- Подстрока, которая использовалась для совпадения.
Например: [[substr1, substr2, ...], originalsubstring].
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ');
const hits = completions.filter((c) => c.startsWith(line));
// Show all completions if none found
return [hits.length ? hits : completions, line];
} copy Функция completer также может возвращать <Promise> или быть асинхронной:
async function completer(linePartial) {
await someAsyncWork();
return [['123'], linePartial];
} copy API обратного вызова
Класс: readline.Interface
- Расширяет: <readline.InterfaceConstructor>
Экземпляры класса readline.Interface создаются с помощью метода readline.createInterface(). Каждый экземпляр связан с одним потоком input Readable и одним потоком output Writable. Поток output используется для вывода приглашений для ввода пользователя, который поступает и считывается из потока input.
rl.question(query[, options], callback)
-
query<строка> Оператор или запрос, который необходимо записать вoutput, добавляется перед приглашением. -
options<Объект>-
signal<AbortSignal> Допускает отменуquestion()с помощьюAbortController.
-
-
callback<Функция> Функция обратного вызова, которая вызывается с вводом пользователя в ответ наquery.
Метод rl.question() отображает query, записывая его в output, ожидает ввода пользователя в input, затем вызывает функцию callback, передавая предоставленный ввод в качестве первого аргумента.
При вызове rl.question() возобновит поток input если он был приостановлен.
Если readline.Interface был создан с output установленным на null или undefined, query не записывается.
Функция callback передаваемая в rl.question() не следует типичной структуре, принимая объект Error или null в качестве первого аргумента. Функция callback вызывается с предоставленным ответом в качестве единственного аргумента.
Будет выброшено исключение, если вызвать rl.question() после rl.close().
Пример использования:
rl.question('What is your favorite food? ', (answer) => {
console.log(`Oh, so your favorite food is ${answer}`);
}); copy Использование AbortController для отмены вопроса.
const ac = new AbortController();
const signal = ac.signal;
rl.question('What is your favorite food? ', { signal }, (answer) => {
console.log(`Oh, so your favorite food is ${answer}`);
});
signal.addEventListener('abort', () => {
console.log('The food question timed out');
}, { once: true });
setTimeout(() => ac.abort(), 10000); copy
readline.clearLine(stream, dir[, callback])
-
stream<stream.Writable> -
dir<число>-
-1: слева от курсора -
1: справа от курсора -
0: вся строка
-
-
callback<Функция> Вызывается по завершении операции. - Возвращает: <логическое>
falseеслиstreamхочет, чтобы вызывающий код ожидал события'drain'перед продолжением записи дополнительных данных; в противном случаеtrue.
Метод readline.clearLine() очищает текущую строку указанного потока TTY в заданном направлении, определенном dir.
readline.clearScreenDown(stream[, callback])
-
stream<stream.Writable> -
callback<Функция> Вызывается по завершении операции. - Возвращает: <логическое>
falseеслиstreamхочет, чтобы вызывающий код ожидал события'drain'перед продолжением записи дополнительных данных; в противном случаеtrue.
Метод readline.clearScreenDown() очищает указанный поток TTY от текущей позиции курсора вниз.
readline.createInterface(options)
-
options<Object>-
input<stream.Readable> Поток Readable для прослушивания. Этот параметр обязателен. -
output<stream.Writable> Поток Writable для записи данных readline. -
completer<Function> Необязательная функция для автодополнения Tab. -
terminal<boolean>true, если потокиinputиoutputдолжны обрабатываться как TTY, и к ним должны записываться ANSI/VT100 управляющие коды. По умолчанию: проверкаisTTYна потокеoutputпри инициализации. -
history<string[]> Начальный список строк истории. Этот параметр имеет смысл только еслиterminalустановлено вtrueпользователем или внутреннимoutputконтролем, в противном случае механизм кэширования истории не инициализируется. По умолчанию:[]. -
historySize<number> Максимальное количество сохраняемых строк истории. Для отключения истории установите это значение в0. Этот параметр имеет смысл только еслиterminalустановлено вtrueпользователем или внутреннимoutputконтролем, в противном случае механизм кэширования истории не инициализируется. По умолчанию:30. -
removeHistoryDuplicates<boolean> Еслиtrue, при добавлении новой строки в список истории, которая дублирует более старую, то старая строка удаляется из списка. По умолчанию:false. -
prompt<string> Строка подсказки. По умолчанию:'> '. -
crlfDelay<number> Если задержка между\rи\nпревышаетcrlfDelayмиллисекунд,\rи\nбудут обрабатываться как отдельный ввод по окончании строки.crlfDelayбудет приведено к числу не меньше100. Можно установить значение вInfinity, в этом случае\rза которым следует\nвсегда будет считаться одной новой строкой (что может быть целесообразно для чтения файлов с разделителем строк\r\n). По умолчанию:100. -
escapeCodeTimeout<number> Длительностьreadlineожидания символа (при чтении неоднозначной последовательности клавиш, которая может как образовать полную последовательность клавиш, используя прочитанный ввод, так и потребовать дополнительного ввода для завершения более длинной последовательности клавиш) в миллисекундах. По умолчанию:500. -
tabSize<integer> Количество пробелов, соответствующих табуляции (минимум 1). По умолчанию:8. -
signal<AbortSignal> Позволяет закрыть интерфейс с помощью AbortSignal. Прерывание сигнала вызоветcloseв интерфейсе.
-
- Возвращает: <readline.Interface>
Метод readline.createInterface() создаёт новый экземпляр readline.Interface.
const readline = require('node:readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
}); copy После создания экземпляра readline.Interface наиболее частым случаем является прослушивание события 'line':
rl.on('line', (line) => {
console.log(`Received: ${line}`);
}); copy Если terminal установлено в true для данного экземпляра, то поток output получит лучшую совместимость, если он определит свойство output.columns и выпустит событие 'resize' на потоке output при изменении колонок (process.stdout делает это автоматически, если это TTY).
При создании readline.Interface с использованием stdin в качестве входного значения, программа не завершится, пока не получит символ EOF. Чтобы завершить без ожидания ввода пользователя, вызовите process.stdin.unref().
Использование функции completer
Функция completer принимает текущую строку, введённую пользователем, в качестве аргумента и возвращает массив Array с двумя элементами:
- Массив
Arrayс совпадающими элементами для автодополнения. - Подстрока, использованная для сопоставления.
Например: [[substr1, substr2, ...], originalsubstring].
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ');
const hits = completions.filter((c) => c.startsWith(line));
// Show all completions if none found
return [hits.length ? hits : completions, line];
} copy Функция completer может вызываться асинхронно, если она принимает два аргумента:
function completer(linePartial, callback) {
callback(null, [['123'], linePartial]);
} copy
readline.cursorTo(stream, x[, y][, callback])
-
stream<stream.Writable> -
x<number> -
y<number> -
callback<Function> Вызывается по завершении операции. - Возвращает: <boolean>
false, еслиstreamхочет, чтобы вызывающий код ожидал, пока событие'drain'будет выпущено, прежде чем продолжить запись дополнительных данных; в противном случаеtrue.
Метод readline.cursorTo() перемещает курсор в указанную позицию в заданном TTY stream.
readline.moveCursor(stream, dx, dy[, callback])
-
stream<stream.Writable> -
dx<number> -
dy<number> -
callback<Function> Вызывается по завершении операции. - Возвращает: <boolean>
false, еслиstreamхочет, чтобы вызывающий код ожидал, пока событие'drain'будет выпущено, прежде чем продолжить запись дополнительных данных; в противном случаеtrue.
Метод readline.moveCursor() перемещает курсор относительно его текущей позиции в заданном TTY stream.
readline.emitKeypressEvents(stream[, interface])
-
stream<stream.Readable> -
interface<readline.InterfaceConstructor>
Метод readline.emitKeypressEvents() заставляет указанный поток Readable начать излучать события 'keypress' , соответствующие полученному вводу.
Необязательно, interface указывает экземпляр readline.Interface для которого отключается автодополнение при обнаружении введённого вставленного текста.
Если stream является TTY, то он должен быть в режиме raw.
Это автоматически вызывается любым экземпляром readline для его input , если input является терминалом. Закрытие экземпляра readline не останавливает input от излучения событий 'keypress'.
readline.emitKeypressEvents(process.stdin); if (process.stdin.isTTY) process.stdin.setRawMode(true); copy
Пример: Небольшой CLI
Следующий пример демонстрирует использование класса readline.Interface для реализации небольшой командной строки:
const readline = require('node:readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'OHAI> ',
});
rl.prompt();
rl.on('line', (line) => {
switch (line.trim()) {
case 'hello':
console.log('world!');
break;
default:
console.log(`Say what? I might have heard '${line.trim()}'`);
break;
}
rl.prompt();
}).on('close', () => {
console.log('Have a great day!');
process.exit(0);
}); copy Пример: Чтение потока файла построчно
Распространённый случай использования readline — это потребление входного файла по одной строке за раз. Самый простой способ сделать это — использовать API fs.ReadStream и цикл for await...of.
const fs = require('node:fs');
const readline = require('node:readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('input.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine(); copy В качестве альтернативы можно использовать событие 'line':
const fs = require('node:fs');
const readline = require('node:readline');
const rl = readline.createInterface({
input: fs.createReadStream('sample.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
console.log(`Line from file: ${line}`);
}); copy В настоящее время цикл for await...of может быть немного медленнее. Если async / await поток и скорость имеют первостепенное значение, можно применить смешанный подход:
const { once } = require('node:events');
const { createReadStream } = require('node:fs');
const { createInterface } = require('node:readline');
(async function processLineByLine() {
try {
const rl = createInterface({
input: createReadStream('big-file.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
// Process the line.
});
await once(rl, 'close');
console.log('File processed.');
} catch (err) {
console.error(err);
}
})(); copy Сочетания клавиш для TTY
| Сочетания клавиш | Описание | Примечания |
|---|---|---|
| Ctrl+Shift+Backspace | Удалить строку влево | Не работает в Linux, macOS и Windows |
| Ctrl+Shift+Delete | Удалить строку вправо | Не работает в macOS |
| Ctrl+C | Выдать SIGINT или закрыть экземпляр readline | |
| Ctrl+H | Удалить символ влево | |
| Ctrl+D | Удалить символ вправо или закрыть экземпляр readline, если текущая строка пуста/EOF | Не работает в Windows |
| Ctrl+U | Удалить символы от текущей позиции до начала строки | |
| Ctrl+K | Удалить символы от текущей позиции до конца строки | |
| Ctrl+Y | Восстановить (вернуть) ранее удалённый текст | Работает только с текстом, удалённым с помощью Ctrl+U или Ctrl+K |
| Meta+Y | Переключаться между ранее удалёнными текстами | Доступно только если последним нажатием была клавиша Ctrl+Y или Meta+Y |
| Ctrl+A | Перейти к началу строки | |
| Ctrl+E | Перейти к концу строки | |
| Ctrl+B | Назад на один символ | |
| Ctrl+F | Вперёд на один символ | |
| Ctrl+L | Очистить экран | |
| Ctrl+N | Следующий элемент истории | |
| Ctrl+P | Предыдущий элемент истории | |
| Ctrl+- | Отменить предыдущее изменение | Любая клавиша, которая генерирует код 0x1F, выполнит это действие. Во многих терминалах, например, в xterm, эта команда привязана к Ctrl+-. |
| Ctrl+6 | Повторить предыдущее изменение | Во многих терминалах нет стандартного сочетания клавиш для повторения. Мы используем код 0x1E, чтобы выполнить повторение. В xterm, по умолчанию он привязан к Ctrl+6. |
| Ctrl+Z | Переводит работающий процесс в фоновый режим. Введите fg и нажмите Enter, чтобы вернуться. | Не работает в Windows |
| Ctrl+W или Ctrl +Backspace | Удалить назад до границы слова | Ctrl+Backspace Не работает в Linux, macOS и Windows |
| Ctrl+Delete | Удалить вперёд до границы слова | Не работает в macOS |
| Ctrl+Left arrow или Meta+B | Слово влево | Ctrl+Left arrow Не работает в macOS |
| Ctrl+Right arrow или Meta+F | Слово вправо | Ctrl+Right arrow Не работает в macOS |
| Meta+D или Meta +Delete | Удалить слово вправо | Meta+Delete Не работает в Windows |
| Meta+Backspace | Удалить слово влево | Не работает в macOS |
© 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/api/readline.html