Spec-Zone.ru › Node.js 12 LTS

Readline

Устойчивость: 2 - Стабильно

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

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

Класс: Interface

Добавлен в: v0.1.104
  • Расширяет: <EventEmitter>

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

Событие: 'close'

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

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

  • Вызов метода rl.close() и экземпляр readline.Interface отказался от управления потоками input и output;
  • Поток input получает событие 'end';
  • Поток input получает <ctrl>-D, сигнализируя об окончании передачи (EOT);
  • Поток input получает <ctrl>-C, сигнализируя об окончании и отсутствии обработчика события 'SIGINT' на экземпляре readline.Interface.

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

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

Событие: 'line'

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

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

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

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

Событие: 'pause'

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

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

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

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

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

Событие: 'resume'

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

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

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

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

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

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

Событие: 'SIGINT'

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

Событие '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'

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

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

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

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

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

rl.pause()

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

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

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

rl.prompt([preserveCursor])

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

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

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

Если экземпляр readline.Interface был создан с output установленным в null или undefined, запрос не будет выведен.

rl.question(query, callback)

Добавлен в: v0.3.3
  • query <string> Выражение или запрос, которые будут записаны в output, добавленные перед запросом.
  • callback <Function> Функция-обработчик, которая вызывается с вводом пользователя в ответ на query.

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

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

Если экземпляр readline.Interface был создан с output установленным в null или undefined, запрос не будет выведен.

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

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()

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

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

rl.setPrompt(prompt)

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

Метод rl.setPrompt() устанавливает запрос, который будет записываться в output всякий раз, когда вызывается 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() запишет либо data, либо последовательность клавиш, определённую key, в output. Аргумент key поддерживается только если output это текстовый терминал TTY. См. Настройки клавиш 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's input как будто они были предоставлены пользователем.

rl[Symbol.asyncIterator]()

История
Версия Изменения
v11.14.0

Поддержка Symbol.asyncIterator больше не является экспериментальной.

v11.4.0

Добавлен в: v11.4.0

  • Возвращает: <AsyncIterator>

Создает объект AsyncIterator, который итерируется по каждой строке в потоке ввода как строка. Этот метод позволяет асинхронную итерацию по объектам readline.Interface с помощью циклов for await...of.

Ошибки в потоке ввода не передаются.

Если цикл прерван с помощью break, throw, или return, будет вызван rl.close(). Другими словами, итерация по readline.Interface всегда полностью потребляет поток ввода.

Производительность не соответствует традиционному 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`.
  }
}

rl.line

Добавлен в: v0.1.98
  • <строка> | <не определено>

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

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

rl.cursor

Добавлен в: v0.1.98
  • <число> | <не определено>

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

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

rl.getCursorPos()

Добавлен в: v12.16.0
  • Возвращает: <Объект>
    • rows <число> строка подсказки, на которой сейчас находится курсор
    • cols <число> столбец экрана, на котором сейчас находится курсор

Возвращает реальное положение курсора по отношению к подсказке ввода + строке. В расчёты включены длинные строки ввода (перенос) и подсказки, занимающие несколько строк.

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

История
Версия Изменения
v12.7.0

Возвращается обратный вызов write() и значение потока.

v0.7.7

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

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

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

readline.clearScreenDown(stream[, callback])

История
Версия Изменения
v12.7.0

Возвращается обратный вызов write() и значение потока.

v0.7.7

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

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

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

readline.createInterface(options)

История
Версия Изменения
v8.3.0, 6.11.4

Удален максимальный лимит опции crlfDelay.

v6.6.0

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

v6.3.0

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

v6.0.0

Опция historySize теперь может быть 0.

v0.1.98

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

  • options <Объект>
    • input <stream.Readable> Поток Readable для прослушивания. Этот параметр обязателен.
    • output <stream.Writable> Поток Writable для записи данных readline.
    • completer <Функция> Необязательная функция, используемая для автозаполнения Tab.
    • terminal <boolean> true, если потоки input и output должны обрабатываться как TTY и к ним должны записываться escape-коды ANSI/VT100. По умолчанию: проверяется isTTY в потоке output при создании экземпляра.
    • historySize <число> Максимальное количество сохранённых строк истории. Чтобы отключить историю, установите это значение в 0. Этот параметр имеет смысл только если terminal установлено в true пользователем или внутренним контролем output, в противном случае механизм кеширования истории не инициализируется. По умолчанию: 30.
    • prompt <строка> Строка подсказки, которую нужно использовать. По умолчанию: '> '.
    • crlfDelay <число> Если задержка между \r и \n превышает crlfDelay миллисекунд, то \r и \n будут обрабатываться как отдельный ввод по окончанию строки. crlfDelay будет приведено к числу не меньше 100. Его можно установить в Infinity, в этом случае \r, за которым следует \n, всегда будет рассматриваться как один символ новой строки (что может быть уместно для чтения файлов с разделителем строк \r\n). По умолчанию: 100.
    • removeHistoryDuplicates <boolean> Если true, когда новая строка ввода добавляется в список истории и дублирует более раннюю, то более ранняя строка удаляется из списка. По умолчанию: false.
    • escapeCodeTimeout <число> Длительность ожидания 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][, callback])

История
Версия Изменения
v12.7.0

Выставлены в доступ callback и возвращаемое значение метода write() потока.

v0.7.7

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

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

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

readline.emitKeypressEvents(stream[, interface])

Добавлена в: v0.7.7
  • 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[, callback])

История
Версия Изменения
v12.7.0

Выставлены в доступ callback и возвращаемое значение метода write() потока.

v0.7.7

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

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

Метод 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);
  }
})();

Сопоставления клавиш 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 + a Перейти к началу строки
ctrl + e Перейти к концу строки
ctrl + b Назад на один символ
ctrl + f Вперед на один символ
ctrl + l Очистить экран
ctrl + n Следующий элемент истории
ctrl + p Предыдущий элемент истории
ctrl + z Перемещает запущенный процесс в фоновый режим. Введите fg и нажмите enter, чтобы вернуться. Не работает в Windows
ctrl + w или ctrl + backspace Удалить символ назад до границы слова ctrl + backspace Не работает в Linux, Mac и Windows
ctrl + delete Удалить символ вперед до границы слова Не работает в Mac
ctrl + left или meta + b Слово влево ctrl + left Не работает в Mac
ctrl + right или meta + f Слово вправо ctrl + right Не работает в 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-v12.x/docs/api/readline.html

Spec-Zone.ru

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