Readline
Исходный код: lib/readline.js
Модуль node:readline предоставляет интерфейс для построчного чтения данных из потока Readable (например, из process.stdin).
Для использования API на основе промисов:
Модули JavaScript
import * as readline from 'node:readline/promises';
CommonJS
const readline = require('node:readline/promises');Для использования API с обратными вызовами и синхронных API:
Модули JavaScript
import * as readline from 'node:readline';
CommonJS
const readline = require('node:readline');Следующий простой пример иллюстрирует базовое использование модуля node:readline.
Модули JavaScript
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();CommonJS
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, и в экземпляреInterfaceConstructorне зарегистрирован обработчик события'SIGINT'.
Функция-обработчик вызывается без аргументов.
Работа экземпляра 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. Если при получении потоком input сигнала SIGINT не зарегистрирован ни один обработчик события '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. Если при получении потоком input сигнала SIGTSTP не зарегистрирован ни один обработчик события '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[Symbol.dispose]()
Псевдоним для rl.close().
rl.pause()
Метод rl.pause() приостанавливает поток input, чтобы при необходимости его можно было возобновить позже.
Вызов rl.pause() не приводит к немедленному прекращению генерации других событий (включая 'line') экземпляром InterfaceConstructor.
rl.prompt([preserveCursor])
-
preserveCursor<boolean> Если значениеtrue, курсор не будет перемещён в начальное положение0.
Метод rl.prompt() выводит настроенное значение 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() выводит в output значение data или последовательность клавиш, заданную параметром key. Аргумент key поддерживается только в том случае, если output является текстовым терминалом TTY. Список сочетаний клавиш см. в разделе Сочетания клавиш TTY.
Если указан параметр 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's input, как если бы их ввёл пользователь.
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
- Тип: <string>
Текущие входные данные, обрабатываемые Node.js.
Это свойство можно использовать при сборе данных из потока 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
- Тип: <number> | <undefined>
Позиция курсора относительно rl.line.
При чтении данных из потока TTY отслеживается положение текущего курсора во входной строке. Положение курсора определяет, какая часть входной строки будет изменена при обработке данных, а также в каком столбце будет отображаться курсор терминала.
rl.getCursorPos()
- Возвращает: <Object>
Возвращает фактическое положение курсора относительно строки приглашения и введённой строки. При вычислении учитываются длинные строки ввода с переносами, а также многострочные приглашения.
API Promises
Класс: readlinePromises.Interface
- Наследует: <readline.InterfaceConstructor>
Экземпляры класса readlinePromises.Interface создаются с помощью метода readlinePromises.createInterface(). Каждый экземпляр связан с одним потоком input Readable и одним потоком output Writable. Поток output используется для вывода приглашений к вводу, который поступает из потока input и считывается из него.
rl.question(query[, options])
-
query<string> Инструкция или запрос, который нужно записать вoutputперед приглашением. -
options<Object>-
signal<AbortSignal> Позволяет отменитьquestion()с помощьюAbortSignal.
-
- Возвращает: <Promise> Промис, который разрешается вводом пользователя в ответ на
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<Object>-
autoCommit<boolean> Еслиtrue, вызыватьrl.commit()не требуется.
-
rl.clearLine(dir)
-
dir<integer>-
-1: слева от курсора -
1: справа от курсора -
0: вся строка
-
- Возвращает: this
Метод rl.clearLine() добавляет во внутренний список ожидающих действий действие, которое очищает текущую строку связанного stream в направлении, указанном параметром dir. Вызовите rl.commit(), чтобы увидеть результат работы этого метода, если только конструктору не был передан параметр autoCommit: true.
rl.clearScreenDown()
- Возвращает: this
Метод rl.clearScreenDown() добавляет во внутренний список ожидающих действий действие, которое очищает связанный поток от текущего положения курсора до конца. Вызовите rl.commit(), чтобы увидеть результат работы этого метода, если только конструктору не был передан параметр autoCommit: true.
rl.commit()
- Возвращает: <Promise>
Метод rl.commit() отправляет все ожидающие действия в связанный stream и очищает внутренний список ожидающих действий.
rl.cursorTo(x[, y])
Метод rl.cursorTo() добавляет во внутренний список ожидающих действий действие, которое перемещает курсор в указанное положение в связанном stream. Вызовите rl.commit(), чтобы увидеть результат работы этого метода, если только конструктору не был передан параметр autoCommit: true.
rl.moveCursor(dx, dy)
Метод rl.moveCursor() добавляет во внутренний список ожидающих действий действие, которое перемещает курсор относительно его текущего положения в связанном stream. Вызовите rl.commit(), чтобы увидеть результат работы этого метода, если только конструктору не был передан параметр autoCommit: true.
rl.rollback()
- Возвращает: this
Метод rl.rollback очищает внутренний список ожидающих действий, не отправляя их в связанный stream.
readlinePromises.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[]> Начальный список строк истории. Этот параметр имеет смысл, только если пользователь или внутренняя проверкаoutputустановилиterminalвtrue; в противном случае механизм кэширования истории вообще не инициализируется. По умолчанию:[]. -
historySize<number> Максимальное число сохраняемых строк истории. Чтобы отключить историю, установите это значение в0. Этот параметр имеет смысл, только если пользователь или внутренняя проверкаoutputустановилиterminalвtrue; в противном случае механизм кэширования истории вообще не инициализируется. По умолчанию:30. -
removeHistoryDuplicates<boolean> Еслиtrue, при добавлении в список истории новой строки ввода, совпадающей с более старой, старая строка удаляется из списка. По умолчанию:false. -
prompt<string> Используемая строка приглашения. По умолчанию:'> '. -
crlfDelay<number> Если задержка между\rи\nпревышаетcrlfDelayмиллисекунд,\rи\nбудут считаться отдельными символами конца строки. ЗначениеcrlfDelayбудет преобразовано в число не меньше100. Можно задать значениеInfinity; в этом случае\r, за которым следует\n, всегда будет считаться одним символом новой строки (это может быть целесообразно при чтении файлов с разделителем строк\r\n). По умолчанию:100. -
escapeCodeTimeout<number> Время, в течение которогоreadlinePromisesожидает появления символа (при чтении неоднозначной последовательности клавиш, которая может как образовать полную последовательность клавиш с уже прочитанными данными, так и требовать дополнительных данных для завершения более длинной последовательности клавиш). По умолчанию:500. -
tabSize<integer> Количество пробелов, эквивалентное одной табуляции (минимум 1). По умолчанию:8. -
signal<AbortSignal> Позволяет закрыть интерфейс с помощью AbortSignal.
-
- Возвращает: <readlinePromises.Interface>
Метод readlinePromises.createInterface() создаёт новый экземпляр readlinePromises.Interface.
Модули JavaScript
import { createInterface } from 'node:readline/promises';
import { stdin, stdout } from 'node:process';
const rl = createInterface({
input: stdin,
output: stdout,
});CommonJS
const { createInterface } = require('node:readline/promises');
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});После создания экземпляра 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 с двумя элементами:
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<string> Инструкция или запрос для записи вoutputперед подсказкой. -
options<Object>-
signal<AbortSignal> Позволяет при необходимости отменитьquestion()с помощьюAbortController.
-
-
callback<Function> Функция обратного вызова, вызываемая с пользовательским вводом в ответ на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<number>-
-1: слева от курсора -
1: справа от курсора -
0: вся строка
-
-
callback<Function> Вызывается после завершения операции. - Возвращает: <boolean>
false, еслиstreamхочет, чтобы вызывающий код дождался отправки события'drain', прежде чем продолжить запись дополнительных данных; в противном случае —true.
Метод readline.clearLine() очищает текущую строку заданного потока TTY в направлении, указанном параметром dir.
readline.clearScreenDown(stream[, callback])
-
stream<stream.Writable> -
callback<Function> Вызывается после завершения операции. - Возвращает: <boolean>
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.
Модули JavaScript
import { createInterface } from 'node:readline';
import { stdin, stdout } from 'node:process';
const rl = createInterface({
input: stdin,
output: stdout,
});CommonJS
const { createInterface } = require('node:readline');
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});После создания экземпляра 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, он должен находиться в необработанном режиме.
Этот метод автоматически вызывается любым экземпляром readline для его input, если input является терминалом. Закрытие экземпляра readline не останавливает отправку событий 'keypress' потоком input.
readline.emitKeypressEvents(process.stdin); if (process.stdin.isTTY) process.stdin.setRawMode(true); copy
Пример: простейший интерфейс командной строки
В следующем примере показано использование класса readline.Interface для реализации небольшого интерфейса командной строки:
Модули JavaScript
import { createInterface } from 'node:readline';
import { exit, stdin, stdout } from 'node:process';
const rl = createInterface({
input: stdin,
output: 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!');
exit(0);
});CommonJS
const { createInterface } = require('node:readline');
const rl = 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);
});Пример: чтение файла построчно из потока
Часто readline используют для обработки входного файла построчно. Проще всего это сделать с помощью API fs.ReadStream и цикла for await...of:
Модули JavaScript
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
async function processLineByLine() {
const fileStream = createReadStream('input.txt');
const rl = 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();CommonJS
const { createReadStream } = require('node:fs');
const { createInterface } = require('node:readline');
async function processLineByLine() {
const fileStream = createReadStream('input.txt');
const rl = 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();В качестве альтернативы можно использовать событие 'line':
Модули JavaScript
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
const rl = createInterface({
input: createReadStream('sample.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
console.log(`Line from file: ${line}`);
});CommonJS
const { createReadStream } = require('node:fs');
const { createInterface } = require('node:readline');
const rl = createInterface({
input: createReadStream('sample.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
console.log(`Line from file: ${line}`);
});В настоящее время цикл for await...of может работать немного медленнее. Если важны и поток async / await, и скорость, можно использовать смешанный подход:
Модули JavaScript
import { once } from 'node:events';
import { createReadStream } from 'node:fs';
import { createInterface } from '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);
}
})();CommonJS
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);
}
})();Сочетания клавиш TTY
| Сочетания клавиш | Описание | Примечания |
|---|---|---|
| Ctrl+Shift+Backspace | Удалить строку слева | Не работает в Linux, Mac и Windows |
| Ctrl+Shift+Delete | Удалить строку справа | Не работает на Mac |
| 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, Mac и Windows |
| Ctrl+Delete | Удалить текст вперёд до границы слова | Не работает на Mac |
| Ctrl+Left arrow или Meta+B | Перейти на слово влево | Ctrl+Left arrow Не работает на Mac |
| Ctrl+Right arrow или Meta+F | Перейти на слово вправо | Ctrl+Right arrow Не работает на Mac |
| Meta+D или Meta +Delete | Удалить слово справа | Meta+Delete Не работает в Windows |
| Meta+Backspace | Удалить слово слева | Не работает на Mac |
© 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-v22.x/docs/api/readline.html