Spec-Zone.ru › Node.js 14 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(). Каждый экземпляр связан с одним потоком Readable и одним потоком Writable. Поток output используется для вывода подсказок для ввода пользователя, которые поступают и читаются из потока input.

Событие: 'close'

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

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

  • Вызван метод rl.close(), и экземпляр readline.Interface передал управление потоками input и output;
  • Поток input получает событие 'end';
  • Поток input получает Ctrl+D для сигнализации конца передачи (EOT);
  • Поток input получает Ctrl+C для сигнализации SIGINT, и нет обработчика события '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> Текст для отображения пользователю, добавляемый к приглашению.
  • callback <Function> Функция-обработчик, которая вызывается с вводом пользователя в ответ на 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()

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

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

rl.setPrompt(prompt)

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

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

rl.getPrompt()

Добавлена в: 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() запишет либо 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 в input как будто они были введены пользователем.

rl[Symbol.asyncIterator]()

История
Версия Изменения
v11.4.0, v10.16.0

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

v11.14.0, v10.17.0

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

  • Возвращает: <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`.
  }
}

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

rl.line

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

Текущие обрабатываемые данные ввода, получаемые 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();
});

rl.cursor

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

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

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

rl.getCursorPos()

Добавлен в: v13.5.0, 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)

История
Версия Изменения
v13.9.0

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

v8.3.0, v6.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 <логическое значение> true если потоки input и output должны обрабатываться как TTY и к ним должны быть записаны 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 <логическое значение> Если true, когда новая строка ввода добавляется в список истории и дублирует более старую, эта более старая строка удаляется из списка. По умолчанию: false.
    • escapeCodeTimeout <число> Продолжительность readline ожидания символа (при чтении неоднозначной последовательности клавиш, которая может как образовывать полную последовательность клавиш с помощью прочитанного ввода, так и потребовать дополнительного ввода для завершения более длинной последовательности клавиш) в миллисекундах. По умолчанию: 500.
    • tabSize <целое число> Количество пробелов, которое равно табуляции (минимум 1). По умолчанию: 8.
  • Возвращает: <readline.Interface>

Метод 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).

При создании экземпляра readline.Interface с использованием stdin в качестве входного потока программа не завершится, пока не получит EOF (Ctrl+D в Linux/macOS, Ctrl+Z за которым следует Возврат в Windows). Если вы хотите, чтобы ваша программа завершилась без ожидания пользовательского ввода, вы можете unref() стандартный поток ввода:

process.stdin.unref();

Использование функции 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

Обрабатываются обратный вызов и возвращаемое значение метода stream.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

Обрабатываются обратный вызов и возвращаемое значение метода stream.write().

v0.7.7

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

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

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

Пример: Tiny CLI

Следующий пример демонстрирует использование класса 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);
  }
})();

Сочетания клавиш для терминала

Сочетание клавиш Описание Примечания
Ctrl+Shift+Backspace Удалить строку влево Не работает в Linux, macOS и Windows
Ctrl+Shift+Delete Удалить строку вправо Не работает в macOS
Ctrl+C Вызвать SIGINT или закрыть экземпляр readline
Ctrl+H Удалить символ влево
Ctrl+D Удалить символ вправо или закрыть экземпляр readline в случае, если текущая строка пуста/EOF Не работает в Windows
Ctrl+U Удалить от текущей позиции до начала строки
Ctrl+K Удалить от текущей позиции до конца строки
Ctrl+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, macOS и Windows
Ctrl+Delete Удалить вправо до границы слова Не работает в macOS
Ctrl+Left arrow или Meta+B Слово влево Ctrl+Left arrow Не работает в macOS
Ctrl+Right arrow или Meta+F Слово вправо Ctrl+Right arrow Не работает в macOS
Meta+D или Meta +Delete Удалить слово вправо Meta+Delete Не работает в Windows
Meta+Backspace Удалить слово влево Не работает в macOS

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v14.x/docs/api/readline.html

Spec-Zone.ru

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