Spec-Zone.ru › Node.js

Readline

Исходный код: lib/readline.js

Стабильность: 2 — Стабильный

Модуль 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

Добавлено в: v0.1.104
  • Наследует: <EventEmitter>

Экземпляры класса InterfaceConstructor создаются с помощью метода readlinePromises.createInterface() или readline.createInterface(). Каждый экземпляр связан с одним потоком input Readable и одним потоком output Writable. Поток output используется для вывода приглашений для ввода пользователя, поступающего из потока input и считываемого из него.

Событие: 'close'

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

Событие 'close' генерируется при наступлении одного из следующих событий:

  • Вызывается метод rl.close(), и экземпляр InterfaceConstructor освобождает управление потоками input и output;
  • Поток input получает событие 'end';
  • Поток input получает Ctrl+D, сигнализирующее о конце передачи данных (EOT);
  • Поток input получает Ctrl+C, сигнализирующее о SIGINT, и для экземпляра InterfaceConstructor не зарегистрирован обработчик события 'SIGINT'.

Функция-обработчик вызывается без передачи аргументов.

Экземпляр InterfaceConstructor завершает работу после генерации события 'close'.

Событие: 'error'

Добавлено в: v16.0.0

Событие 'error' генерируется при возникновении ошибки в потоке input, связанном с node:readline Interface.

Функция-обработчик вызывается с объектом Error в качестве единственного аргумента.

Событие: 'line'

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

Событие 'line' генерируется каждый раз, когда поток input получает ввод с символом конца строки (\n, \r или \r\n). Обычно это происходит, когда пользователь нажимает Enter или Return.

Событие 'line' также генерируется, если из потока были прочитаны новые данные, а затем поток завершается без завершающего символа конца строки.

Функция-обработчик вызывается со строкой, содержащей единственную строку полученного ввода.

rl.on('line', (input) => {
  console.log(`Received: ${input}`);
});
jscopy

Событие: 'history'

Добавлено в: v15.8.0, v14.18.0

Событие 'history' генерируется каждый раз, когда изменяется массив истории.

Функция-обработчик вызывается с массивом, содержащим массив истории. Он отражает все изменения, добавленные и удалённые строки, возникшие в результате historySize и removeHistoryDuplicates.

Основное назначение этого события — дать обработчику возможность сохранять историю. Обработчик также может изменять объект истории. Это может быть полезно, например, чтобы запретить добавление в историю определённых строк, таких как пароль.

rl.on('history', (history) => {
  console.log(`Received: ${history}`);
});
jscopy

Событие: 'pause'

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

Событие 'pause' генерируется при наступлении одного из следующих событий:

  • Поток input приостановлен.
  • Поток input не приостановлен и получает событие 'SIGCONT'. (См. события 'SIGTSTP' и 'SIGCONT'.)

Функция-обработчик вызывается без передачи аргументов.

rl.on('pause', () => {
  console.log('Readline paused.');
});
jscopy

Событие: 'resume'

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

Событие 'resume' генерируется каждый раз, когда поток input возобновляет работу.

Функция-обработчик вызывается без передачи аргументов.

rl.on('resume', () => {
  console.log('Readline resumed.');
});
jscopy

Событие: 'SIGCONT'

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

Событие 'SIGCONT' генерируется, когда процесс Node.js, ранее переведённый в фоновый режим с помощью Ctrl+Z (то есть SIGTSTP), возвращается на передний план с помощью fg(1p).

Если поток input был приостановлен до запроса SIGTSTP, это событие не будет сгенерировано.

Функция-обработчик вызывается без передачи аргументов.

rl.on('SIGCONT', () => {
  // `prompt` will automatically resume the stream
  rl.prompt();
});
jscopy

Событие 'SIGCONT' не поддерживается в Windows.

Событие: 'SIGINT'

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

Событие '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();
  });
});
jscopy

Событие: 'SIGTSTP'

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

Событие '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.');
});
jscopy

Событие 'SIGTSTP' не поддерживается в Windows.

rl.close()

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

Метод rl.close() закрывает экземпляр InterfaceConstructor и освобождает управление потоками input и output. При вызове будет сгенерировано событие 'close'.

Вызов rl.close() не останавливает немедленно генерацию других событий (включая 'line') экземпляром InterfaceConstructor.

rl[Symbol.dispose]()

Добавлено в: v23.10.0, v22.15.0

Псевдоним для rl.close().

rl.pause()

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

Метод rl.pause() приостанавливает поток input, позволяя при необходимости возобновить его позднее.

Вызов rl.pause() не приостанавливает немедленно генерацию других событий (включая 'line') экземпляром InterfaceConstructor.

rl.prompt([preserveCursor])

Добавлено в: v0.1.98
  • preserveCursor <boolean> Если true, положение курсора не будет сброшено в 0.

Метод rl.prompt() записывает настроенное значение prompt экземпляра InterfaceConstructor в новую строку в output, чтобы предоставить пользователю новое место для ввода данных.

При вызове rl.prompt() возобновит поток input, если он был приостановлен.

Если InterfaceConstructor был создан со значением null для output или undefined, приглашение не выводится.

rl.resume()

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

Метод rl.resume() возобновляет поток input, если он был приостановлен.

rl.setPrompt(prompt)

Добавлено в: v0.1.98
  • prompt <string>

Метод rl.setPrompt() задаёт приглашение, которое будет записано в output при каждом вызове rl.prompt().

rl.getPrompt()

Добавлено в: v15.3.0, v14.17.0
  • Возвращает: <string> текущую строку приглашения

Метод rl.getPrompt() возвращает текущее приглашение, используемое rl.prompt().

rl.write(data[, key])

Добавлено в: v0.1.98
  • data <string>
  • key <Object>
    • ctrl <boolean> true для обозначения клавиши Ctrl.
    • meta <boolean> true для обозначения клавиши Meta.
    • shift <boolean> true для обозначения клавиши Shift.
    • name <string> Название клавиши.

Метод rl.write() записывает в output либо data, либо последовательность клавиш, определённую key. Аргумент key поддерживается только в том случае, если output является текстовым терминалом TTY. Список комбинаций клавиш см. в разделе Сочетания клавиш TTY.

Если указан key, data игнорируется.

При вызове rl.write() возобновит поток input, если он был приостановлен.

Если InterfaceConstructor был создан со значением null для output или undefined, data и key не записываются.

rl.write('Delete this!');
// Simulate Ctrl+U to delete the line written previously
rl.write(null, { ctrl: true, name: 'u' });
jscopy

Метод rl.write() записывает данные в input Interface объекта readline, как если бы их ввёл пользователь.

rl[Symbol.asyncIterator]()

Добавлено в: v11.4.0, v10.16.0
История
Версия Изменения
v11.14.0, v10.17.0

Поддержка 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`.
  }
}
jscopy

readline.createInterface() начинает потреблять входной поток сразу после вызова. Асинхронные операции между созданием интерфейса и асинхронным перебором могут привести к потере строк.

rl.line

Добавлено в: v0.1.98
История
Версия Изменения
v15.8.0, v14.18.0

Значение всегда будет строкой, а не undefined.

  • Тип: <string>

Текущие входные данные, обрабатываемые node.

Это свойство можно использовать при сборе ввода из потока 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();
});
jscopy

rl.cursor

Добавлено в: v0.1.98
  • Тип: <number> | <undefined>

Положение курсора относительно rl.line.

При чтении ввода из потока TTY отслеживается положение текущего курсора в строке ввода. Положение курсора определяет, какая часть строки ввода будет изменена при обработке ввода, а также в каком столбце будет отображаться курсор терминала.

rl.getCursorPos()

Добавлено в: v13.5.0, v12.16.0
  • Возвращает: <Object>
    • rows <number> строку приглашения, на которой в данный момент находится курсор
    • cols <number> столбец экрана, на котором в данный момент находится курсор

Возвращает фактическое положение курсора относительно приглашения и строки ввода. При вычислениях учитываются длинные строки ввода с переносами и многострочные приглашения.

API промисов

Добавлено в: v17.0.0
История
Версия Изменения
v24.0.0, v22.17.0

API объявлен стабильным.

Класс: readlinePromises.Interface

Добавлено в: v17.0.0
  • Наследует: <readline.InterfaceConstructor>

Экземпляры класса readlinePromises.Interface создаются с помощью метода readlinePromises.createInterface(). Каждый экземпляр связан с одним потоком input Readable и одним потоком output Writable. Поток output используется для вывода приглашений для ввода пользователя, поступающего из потока input и считываемого из него.

rl.question(query[, options])
Добавлено в: v17.0.0
  • query <string> Инструкция или запрос для записи в output перед приглашением.
  • options <Object>
    • signal <AbortSignal> Позволяет отменить question() с помощью AbortSignal.
  • Возвращает: <Promise> Промис, который выполняется с вводом пользователя в ответ на query.

Метод rl.question() отображает query, записывая его в output, ожидает ввода пользователя в input, а затем вызывает функцию callback, передавая полученный ввод в качестве первого аргумента.

При вызове rl.question() возобновит поток input, если он был приостановлен.

Если readlinePromises.Interface был создан со значением null для output или undefined, query не выводится.

Если вопрос задан после rl.close(), возвращается отклонённый промис.

Пример использования:

const answer = await rl.question('What is your favorite food? ');
console.log(`Oh, so your favorite food is ${answer}`);
mjscopy

Использование 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}`);
mjscopy

Класс: readlinePromises.Readline

Добавлено в: v17.0.0
new readlinePromises.Readline(stream[, options])
Добавлено в: v17.0.0
  • stream <stream.Writable> Поток TTY.
  • options <Object>
    • autoCommit <boolean> Если true, вызывать rl.commit() не требуется.
rl.clearLine(dir)
Добавлено в: v17.0.0
  • dir <integer>
    • -1: слева от курсора
    • 1: справа от курсора
    • 0: вся строка
  • Возвращает: this

Метод rl.clearLine() добавляет во внутренний список ожидающих действий действие, которое очищает текущую строку связанного stream в направлении, заданном dir. Чтобы увидеть результат работы этого метода, вызовите rl.commit(), если только при создании объекта не был передан autoCommit: true.

rl.clearScreenDown()
Добавлено в: v17.0.0
  • Возвращает: this

Метод rl.clearScreenDown() добавляет во внутренний список ожидающих действий действие, которое очищает связанный поток от текущего положения курсора до конца. Чтобы увидеть результат работы этого метода, вызовите rl.commit(), если только при создании объекта не был передан autoCommit: true.

rl.commit()
Добавлено в: v17.0.0
  • Возвращает: <Promise>

Метод rl.commit() отправляет все ожидающие действия в связанный stream и очищает внутренний список ожидающих действий.

rl.cursorTo(x[, y])
Добавлено в: v17.0.0
  • x <integer>
  • y <integer>
  • Возвращает: this

Метод rl.cursorTo() добавляет во внутренний список ожидающих действий действие, перемещающее курсор в указанное положение в связанном stream. Чтобы увидеть результат работы этого метода, вызовите rl.commit(), если только при создании объекта не был передан autoCommit: true.

rl.moveCursor(dx, dy)
Добавлено в: v17.0.0
  • dx <integer>
  • dy <integer>
  • Возвращает: this

Метод rl.moveCursor() добавляет во внутренний список ожидающих действий действие, перемещающее курсор относительно его текущего положения в связанном stream. Чтобы увидеть результат работы этого метода, вызовите rl.commit(), если только при создании объекта не был передан autoCommit: true.

rl.rollback()
Добавлено в: v17.0.0
  • Возвращает: this

Метод rl.rollback очищает внутренний список ожидающих действий, не отправляя их в связанный stream.

readlinePromises.createInterface(options)

Добавлено в: v17.0.0
  • 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}`);
});
jscopy

Если для этого экземпляра 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];
}
jscopy

Функция completer также может возвращать <Promise> или быть асинхронной:

async function completer(linePartial) {
  await someAsyncWork();
  return [['123'], linePartial];
}
jscopy

API обратного вызова

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

Класс: readline.Interface

Добавлено в: v0.1.104
История
Версия Изменения
v17.0.0

Класс readline.Interface теперь наследуется от Interface.

  • Расширяет: <readline.InterfaceConstructor>

Экземпляры класса readline.Interface создаются с помощью метода readline.createInterface(). Каждый экземпляр связан с одним потоком input Readable и одним потоком output Writable. Поток output используется для вывода приглашений для ввода пользователя, поступающего из потока input и считываемого из него.

rl.question(query[, options], callback)
Добавлено в: v0.3.3
  • query <string> Оператор или запрос, записываемый в output перед приглашением.
  • options <Object>
    • signal <AbortSignal> Позволяет отменить question() с помощью AbortController.
  • callback <Function> Функция обратного вызова, вызываемая с вводом пользователя в ответ на query.

Метод rl.question() отображает query, записывая его в output, ожидает ввода пользователя в input, а затем вызывает функцию callback, передавая введенные данные в качестве первого аргумента.

При вызове rl.question() возобновит работу потока input, если он был приостановлен.

Если экземпляр readline.Interface создан со значением null или undefined для output, то 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}`);
});
jscopy

Использование 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);
jscopy

readline.clearLine(stream, dir[, callback])

Добавлено в: v0.7.7
История
Версия Изменения
v18.0.0

Теперь при передаче недопустимой функции обратного вызова в аргумент callback выбрасывается ERR_INVALID_ARG_TYPE вместо ERR_INVALID_CALLBACK.

v12.7.0

Стали доступны функция обратного вызова write() и возвращаемое значение потока.

  • stream <stream.Writable>
  • dir <number>
    • -1: влево от курсора
    • 1: вправо от курсора
    • 0: вся строка
  • callback <Function> Вызывается после завершения операции.
  • Возвращает: <boolean> false, если stream требуется, чтобы вызывающий код дождался генерации события 'drain' перед продолжением записи данных; в противном случае — true.

Метод readline.clearLine() очищает текущую строку указанного потока TTY в направлении, заданном параметром dir.

readline.clearScreenDown(stream[, callback])

Добавлено в: v0.7.7
История
Версия Изменения
v18.0.0

Теперь при передаче недопустимой функции обратного вызова в аргумент callback выбрасывается ERR_INVALID_ARG_TYPE вместо ERR_INVALID_CALLBACK.

v12.7.0

Стали доступны функция обратного вызова write() и возвращаемое значение потока.

  • stream <stream.Writable>
  • callback <Function> Вызывается после завершения операции.
  • Возвращает: <boolean> false, если stream требуется, чтобы вызывающий код дождался генерации события 'drain' перед продолжением записи данных; в противном случае — true.

Метод readline.clearScreenDown() очищает указанный поток TTY от текущего положения курсора до конца экрана.

readline.createInterface(options)

Добавлено в: v0.1.98
История
Версия Изменения
v15.14.0, v14.18.0

Теперь поддерживается параметр signal.

v15.8.0, v14.18.0

Теперь поддерживается параметр history.

v13.9.0

Теперь поддерживается параметр tabSize.

v8.3.0, v6.11.4

Снято максимальное ограничение параметра crlfDelay.

v6.6.0

Теперь поддерживается параметр crlfDelay.

v6.3.0

Теперь поддерживается параметр prompt.

v6.0.0

Теперь параметру historySize можно присвоить значение 0.

  • 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> Время в миллисекундах, в течение которого 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}`);
});
jscopy

Если для этого экземпляра 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];
}
jscopy

Функцию completer можно вызывать асинхронно, если она принимает два аргумента:

function completer(linePartial, callback) {
  callback(null, [['123'], linePartial]);
}
jscopy

readline.cursorTo(stream, x[, y][, callback])

Добавлено в: v0.7.7
История
Версия Изменения
v18.0.0

Теперь при передаче недопустимой функции обратного вызова в аргумент callback выбрасывается ERR_INVALID_ARG_TYPE вместо ERR_INVALID_CALLBACK.

v12.7.0

Стали доступны функция обратного вызова write() и возвращаемое значение потока.

  • stream <stream.Writable>
  • x <number>
  • y <number>
  • callback <Function> Вызывается после завершения операции.
  • Возвращает: <boolean> false, если stream требуется, чтобы вызывающий код дождался генерации события 'drain' перед продолжением записи данных; в противном случае — true.

Метод readline.cursorTo() перемещает курсор в заданное положение в указанном потоке TTY stream.

readline.moveCursor(stream, dx, dy[, callback])

Добавлено в: v0.7.7
История
Версия Изменения
v18.0.0

Теперь при передаче недопустимой функции обратного вызова в аргумент callback выбрасывается ERR_INVALID_ARG_TYPE вместо ERR_INVALID_CALLBACK.

v12.7.0

Стали доступны функция обратного вызова write() и возвращаемое значение потока.

  • stream <stream.Writable>
  • dx <number>
  • dy <number>
  • callback <Function> Вызывается после завершения операции.
  • Возвращает: <boolean> false, если stream требуется, чтобы вызывающий код дождался генерации события 'drain' перед продолжением записи данных; в противном случае — true.

Метод readline.moveCursor() перемещает курсор относительно его текущего положения в указанном потоке TTY stream.

readline.emitKeypressEvents(stream[, interface])

Добавлено в: v0.7.7
  • 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);
jscopy

Пример: небольшая CLI

В следующем примере показано использование класса 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/api/readline.html

Spec-Zone.ru

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