Spec-Zone.ru › Node.js 16 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 input и одним потоком Writable output. Поток 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}`);
});

Событие: 'history'

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

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

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

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

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

Событие: '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[, 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 был создан с output установленным в null или undefined, запрос query не будет выведен.

Функция callback, переданная в rl.question(), не следует типичному шаблону принятия объекта Error или сигнала null в качестве первого аргумента. Функция callback вызывается с предоставленным ответом как единственным аргументом.

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

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

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

Если этот метод вызывается в виде его util.promisify() версии, он возвращает Promise, который выполняется с ответом. Если вопрос отменён с помощью AbortController, он будет отклонен с AbortError.

const util = require('util');
const question = util.promisify(rl.question).bind(rl);

async function questionExample() {
  try {
    const answer = await question('What is you favorite food? ');
    console.log(`Oh, so your favorite food is ${answer}`);
  } catch (err) {
    console.error('Question rejected', err);
  }
}
questionExample();

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
  • Возвращает: <string> текущую строку запроса

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

rl.write(data[, key])

Добавлен в: v0.1.98
  • data <строка>
  • key <Объект>
    • ctrl <логическое> true для обозначения клавиши Ctrl.
    • meta <логическое> true для обозначения клавиши Meta.
    • shift <логическое> true для обозначения клавиши Shift.
    • name <строка> Название клавиши.

Метод 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.4.0, v10.16.0

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

v11.14.0, v10.17.0

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

История
Версия Изменения
v15.8.0

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

v0.1.98

Добавлен в: 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()

Добавлен в: 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 <Функция> Вызывается после завершения операции.
  • Возвращает: <логическое> 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 <Функция> Вызывается после завершения операции.
  • Возвращает: <логическое> false если stream хочет, чтобы вызывающий код ожидал, пока событие 'drain' будет выброшено, прежде чем продолжить запись дополнительных данных; в противном случае true.

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

readline.createInterface(options)

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

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

v15.8.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.

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 при инициализации.
    • history <строковый массив> Начальный список строк истории. Эта опция имеет смысл только если terminal установлено значением true пользователем или в ходе внутренней проверки output, в противном случае механизм кэширования истории не будет инициализирован. По умолчанию: [].
    • historySize <число> Максимальное количество строк истории, которые сохраняются. Для отключения истории установите это значение в 0. Эта опция имеет смысл только если terminal установлено значением true пользователем или в ходе внутренней проверки output, в противном случае механизм кэширования истории не будет инициализирован. По умолчанию: 30.
    • removeHistoryDuplicates <булево> Если true, когда новая строка ввода добавляется в список истории и дублирует более старую, то более старая строка удаляется из списка. По умолчанию: false.
    • prompt <строка> Строка приглашения для использования. По умолчанию: '> '.
    • crlfDelay <число> Если задержка между \r и \n превышает crlfDelay миллисекунд, оба \r и \n будут обрабатываться как отдельный ввод конца строки. crlfDelay будет приведено к числу не меньше 100. Его можно установить в Infinity, в этом случае \r , за которым следует \n , всегда будет рассматриваться как одна новая строка (что может быть разумным для чтения файлов с разделителем строк \r\n). По умолчанию: 100.
    • escapeCodeTimeout <число> Длительность readline ожидания символа (при чтении неоднозначной последовательности символов, которая может как образовать полную последовательность символов, используя прочитанный ввод, так и принять дополнительный ввод для завершения более длинной последовательности символов) в миллисекундах. По умолчанию: 500.
    • tabSize <целое число> Количество пробелов, которое равно значению табуляции (минимум 1). По умолчанию: 8.
    • signal <AbortSignal> Позволяет закрыть интерфейс с помощью AbortSignal. Прерывание сигнала вызовет внутренне close на интерфейсе.
  • Возвращает: <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, за которым следует Return на 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

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

v0.7.7

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

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

Метод readline.cursorTo() перемещает курсор в указанную позицию в заданном потоке 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 при его создании, если stream является терминалом. Закрытие экземпляра readline не останавливает input от излучения событий 'keypress' .

readline.emitKeypressEvents(process.stdin);
if (process.stdin.isTTY)
  process.stdin.setRawMode(true);

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

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

Обработчик записи потока (write() callback) и значение возврата теперь доступны.

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 arrow или Meta+B Слово влево Ctrl+Left arrow Не работает в Mac
Ctrl+Right arrow или Meta+F Слово вправо Ctrl+Right arrow Не работает в Mac
Meta+D или Meta +Delete Удалить слово вправо Meta+Delete Не работает в Windows
Meta+Backspace Удалить слово влево Не работает в Mac

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

Spec-Zone.ru

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