Readline
Модуль readline предоставляет интерфейс для чтения данных из потока Readable (например, process.stdin) по одной строке за раз. К нему можно обратиться следующим образом:
const readline = require('readline');
Следующий простой пример демонстрирует основное использование модуля readline.
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
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.
Класс: Интерфейс
Экземпляры класса readline.Interface создаются с помощью метода readline.createInterface(). Каждый экземпляр связан с одним потоком Readable и одним потоком Writable. Поток output используется для вывода подсказок для пользовательского ввода, который поступает и считывается из потока input.
Событие: 'close'
Событие 'close' генерируется в следующих случаях:
- Вызван метод
rl.close(), и экземплярreadline.Interfaceпередал управление потокамиinputиoutput; - Поток
inputполучает событие'end'; - Поток
inputполучает<ctrl>-Dдля сигнализации о конце передачи (EOT); - Поток
inputполучает<ctrl>-Cдля сигнализации оSIGINT, и на экземпляреreadline.Interfaceнет обработчика событий'SIGINT'.
Функция-обработчик вызывается без аргументов.
Экземпляр readline.Interface завершается после генерации события 'close'.
Событие: 'line'
Событие 'line' генерируется всякий раз, когда поток input получает входные данные с новой строки (\n, \r, или \r\n). Это обычно происходит, когда пользователь нажимает клавиши <Enter>, или <Return>.
Функция-обработчик вызывается со строкой, содержащей полученную строку ввода.
rl.on('line', (input) => {
console.log(`Received: ${input}`);
});
Событие: 'pause'
Событие 'pause' генерируется в следующих случаях:
- Поток
inputприостановлен. - Поток
inputне приостановлен и получает событие'SIGCONT'. (См. события'SIGTSTP'и'SIGCONT'.)
Функция-обработчик вызывается без аргументов.
rl.on('pause', () => {
console.log('Readline paused.');
});
Событие: 'resume'
Событие 'resume' генерируется всякий раз, когда поток input возобновляется.
Функция-обработчик вызывается без аргументов.
rl.on('resume', () => {
console.log('Readline resumed.');
});
Событие: 'SIGCONT'
Событие 'SIGCONT' генерируется, когда процесс Node.js, ранее переведённый в фоновый режим с помощью <ctrl>-Z (т.е. SIGTSTP ), затем возвращён в фоновый режим с помощью fg(1p).
Если поток input был приостановлен до запроса SIGTSTP, это событие не будет сгенерировано.
Функция-обработчик вызывается без аргументов.
rl.on('SIGCONT', () => {
// `prompt` will automatically resume the stream
rl.prompt();
});
Событие '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();
});
});
Событие: '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.');
});
Событие 'SIGTSTP' не поддерживается на Windows.
rl.close()
Метод rl.close() закрывает экземпляр readline.Interface и передаёт управление потоками input и output. При вызове будет сгенерировано событие 'close'.
Вызов rl.close() немедленно не останавливает генерацию других событий (включая 'line') экземпляром readline.Interface.
rl.pause()
Метод rl.pause() приостанавливает поток input, позволяя его возобновить позже при необходимости.
Вызов rl.pause() немедленно не останавливает генерацию других событий (включая 'line') экземпляром readline.Interface.
rl.prompt([preserveCursor])
-
preserveCursor<boolean> Еслиtrue, предотвращает сброс позиции курсора до0.
Метод rl.prompt() записывает заданный экземпляром readline.Interface конфигурированный prompt на новую строку в output , чтобы предоставить пользователю новое место для ввода.
При вызове rl.prompt() возобновит поток input , если он был приостановлен.
Если экземпляр readline.Interface был создан с output установленным в null или undefined, подсказка не будет выведена.
rl.question(query, callback)
-
query<строка> Текст для вывода вoutput, добавленный перед подсказкой. -
callback<Функция> Функция обратного вызова, которая вызывается с пользовательским вводом в ответ наquery.
Метод rl.question() отображает query , записывая его в output, ожидает пользовательского ввода в input, а затем вызывает функцию callback, передавая полученный ввод в качестве первого аргумента.
При вызове rl.question() возобновит поток input , если он был приостановлен.
Если экземпляр readline.Interface был создан с output установленным в null или undefined, query не будет выведено.
Пример использования:
rl.question('What is your favorite food? ', (answer) => {
console.log(`Oh, so your favorite food is ${answer}`);
});
Функция callback, переданная в rl.question(), не следует типичному шаблону, принимающему объект Error или null в качестве первого аргумента. Функция callback вызывается с предоставленным ответом в качестве единственного аргумента.
rl.resume()
Метод rl.resume() возобновляет поток input , если он был приостановлен.
rl.setPrompt(prompt)
-
prompt<строка>
Метод rl.setPrompt() устанавливает подсказку, которая будет выведена в output всякий раз, когда вызывается rl.prompt().
rl.write(data[, key])
Метод rl.write() запишет либо data, либо последовательность ключей, идентифицированную key, в output. Аргумент key поддерживается только если output является текстовым терминалом TTY.
Если key указано, data игнорируется.
При вызове rl.write() возобновит поток input, если он был приостановлен.
Если readline.Interface был создан с 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' });
Метод rl.write() запишет данные в readline Interface в input как если бы они были введены пользователем.
rl[Symbol.asyncIterator]()
- Возвращает: <AsyncIterator>
Создаёт объект AsyncIterator, который итерируется по каждой строке в потоке ввода как строка. Этот метод позволяет асинхронно итерироваться по объектам readline.Interface через циклы for-await-of.
Ошибки в потоке ввода не передаются.
Если цикл прерывается с помощью break, throw, или return, будет вызван rl.close(). Другими словами, итерация по readline.Interface всегда полностью потребляет поток ввода.
Особенностью использования этой экспериментальной API является то, что производительность в настоящее время не соответствует традиционному API событий '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`.
}
}
readline.clearLine(stream, dir)[src]
-
stream<stream.Writable> -
dir<number>-
-1- влево от курсора -
1- вправо от курсора -
0- вся строка
-
Метод readline.clearLine() очищает текущую строку указанного потока TTY в заданном направлении, определённом dir.
readline.clearScreenDown(stream)[src]
-
stream<stream.Writable>
Метод readline.clearScreenDown() очищает указанный поток TTY от текущей позиции курсора вниз.
readline.createInterface(options)[src]
-
options<Object>-
input<stream.Readable> Поток Readable для прослушивания. Эта опция обязательна. -
output<stream.Writable> Поток Writable для записи данных readline. -
completer<Function> Необязательная функция для автодополнения Tab. -
terminal<boolean>trueуказывает, следует ли рассматривать потокиinputиoutputкак TTY, и записывать ли к ним коды ANSI/VT100. По умолчанию: проверкаisTTYв потокеoutputпри создании. -
historySize<number> Максимальное число строк в истории. Для отключения истории установите это значение в0. Эта опция имеет смысл только еслиterminalустановлено вtrueпользователем или внутреннимoutputcheck. В противном случае механизм кеширования истории не инициализируется. По умолчанию:30. -
prompt<string> Строка запроса. По умолчанию:'> '. -
crlfDelay<number> Если задержка между\rи\nпревышаетcrlfDelayмиллисекунд,\rи\nбудут рассматриваться как отдельные входные данные.crlfDelayбудет приведено к числу не меньше100. Может быть установлено вInfinity, в этом случае\rи\nвсегда будут рассматриваться как один символ новой строки (что может быть уместно для чтения файлов с разделителем строк\r\n). По умолчанию:100. -
removeHistoryDuplicates<boolean> Еслиtrue, когда новая строка ввода дублирует более старую в списке истории, она удаляет старую строку из списка. По умолчанию:false. -
escapeCodeTimeout<number> Продолжительность, которуюreadlineбудет ожидать символ (при чтении неоднозначной последовательности символов, которая может быть как полной последовательностью символов, так и может принять дополнительные входные данные для завершения более длинной последовательности) в миллисекундах. По умолчанию:500.
-
Метод readline.createInterface() создаёт новый экземпляр readline.Interface.
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
После создания экземпляра readline.Interface, наиболее распространённым случаем является прослушивание события 'line'.
rl.on('line', (line) => {
console.log(`Received: ${line}`);
});
Если 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];
}
Функция completer может быть вызвана асинхронно, если она принимает два аргумента:
function completer(linePartial, callback) {
callback(null, [['123'], linePartial]);
}
readline.cursorTo(stream, x, y)[src]
-
stream<stream.Writable> -
x<число> -
y<число>
Метод readline.cursorTo() перемещает курсор в указанную позицию в заданном TTY stream.
readline.emitKeypressEvents(stream[, interface])[src]
-
stream<stream.Readable> -
interface<readline.Interface>
Метод 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);
readline.moveCursor(stream, dx, dy)[src]
-
stream<stream.Writable> -
dx<число> -
dy<число>
Метод readline.moveCursor() перемещает курсор относительно его текущей позиции в заданном TTY stream.
Пример: Небольшая командная строка
Следующий пример иллюстрирует использование класса readline.Interface для реализации небольшой командной строки:
const readline = require('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);
});
Пример: Чтение файла потока по строкам
Распространённый случай использования readline — это потребление файла ввода построчно. Самый простой способ сделать это — использовать API fs.ReadStream а также цикл for-await-of:
const fs = require('fs');
const readline = require('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();
В качестве альтернативы можно использовать событие 'line':
const fs = require('fs');
const readline = require('readline');
const rl = readline.createInterface({
input: fs.createReadStream('sample.txt'),
crlfDelay: Infinity
});
rl.on('line', (line) => {
console.log(`Line from file: ${line}`);
});
В настоящее время цикл for-await-of может быть немного медленнее. Если async / await поток и скорость имеют первостепенное значение, можно применить смешанный подход:
const { once } = require('events');
const { createReadStream } = require('fs');
const { createInterface } = require('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);
}
})();
© 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/readline.html