Skip to content

Readline

[Стабильно: 2 - Стабильно]

Стабильно: 2 Стабильность: 2 - Стабильно

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

Модуль node:readline предоставляет интерфейс для чтения данных из потока Readable (например, process.stdin) построчно.

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

js
import * as readline from 'node:readline/promises'
js
const readline = require('node:readline/promises')

Для использования API с обратными вызовами и синхронного API:

js
import * as readline from 'node:readline'
js
const readline = require('node:readline')

Следующий простой пример иллюстрирует базовое использование модуля node:readline.

js
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('Что вы думаете о Node.js? ')

console.log(`Спасибо за ваш ценный отзыв: ${answer}`)

rl.close()
js
const readline = require('node:readline')
const { stdin: input, stdout: output } = require('node:process')

const rl = readline.createInterface({ input, output })

rl.question('Что вы думаете о Node.js? ', answer => {
  // TODO: Залогировать ответ в базу данных
  console.log(`Спасибо за ваш ценный отзыв: ${answer}`)

  rl.close()
})

После вызова этого кода приложение Node.js не завершится до тех пор, пока readline.Interface не будет закрыт, поскольку интерфейс ожидает получения данных в потоке input.

Класс: InterfaceConstructor

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

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

Событие: 'close'

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

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

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

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

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

Событие: 'line'

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

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

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

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

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

Событие: 'history'

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

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

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

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

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

Событие: 'pause'

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

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

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

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

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

Событие: 'resume'

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

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

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

js
rl.on('resume', () => {
  console.log('Readline возобновлен.')
})

Событие: 'SIGCONT'

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

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

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

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

js
rl.on('SIGCONT', () => {
  // `prompt` автоматически возобновит поток
  rl.prompt()
})

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

Событие: 'SIGINT'

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

Событие 'SIGINT' генерируется всякий раз, когда поток input получает входные данные, обычно известные как SIGINT. Если при получении потоком input сигнала SIGINT не зарегистрировано обработчиков событий 'SIGINT', будет сгенерировано событие 'pause'.

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

js
rl.on('SIGINT', () => {
  rl.question('Вы уверены, что хотите выйти? ', answer => {
    if (answer.match(/^y(es)?$/i)) rl.pause()
  })
})

Событие: 'SIGTSTP'

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

Событие 'SIGTSTP' генерируется, когда поток input получает входные данные +, обычно известные как SIGTSTP. Если при получении потоком input сигнала SIGTSTP не зарегистрировано обработчиков событий 'SIGTSTP', процесс Node.js будет переведен в фоновый режим.

Когда программа возобновляется с помощью fg(1p), будут сгенерированы события 'pause' и 'SIGCONT'. Их можно использовать для возобновления потока input.

События 'pause' и 'SIGCONT' генерироваться не будут, если input был приостановлен до того, как процесс был переведен в фоновый режим.

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

js
rl.on('SIGTSTP', () => {
  // Это переопределит SIGTSTP и предотвратит переход программы в фоновый режим.
  console.log('Перехвачено SIGTSTP.')
})

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

rl.close()

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

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

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

rl.pause()

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

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

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

rl.prompt([preserveCursor])

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

  • preserveCursor <boolean> Если true, предотвращает сброс позиции курсора в 0.

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

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

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

rl.resume()

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

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

rl.setPrompt(prompt)

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

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

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

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

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

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

js
rl.write('Удалить это!')
// Имитируем Ctrl+U для удаления ранее написанной строки
rl.write(null, { ctrl: true, name: 'u' })

Метод rl.write() записывает данные в input интерфейса readline так, как если бы они были предоставлены пользователем.

rl[Symbol.asyncIterator]()

[История]

ВерсияИзменения
v11.14.0, v10.17.0Поддержка Symbol.asyncIterator больше не является экспериментальной.
v11.4.0, v10.16.0Добавлено в: v11.4.0, v10.16.0

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

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

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

Производительность не соответствует традиционному API события 'line'. Для производительных приложений используйте 'line'.

js
async function processLineByLine() {
  const rl = readline.createInterface({
    // ...
  })

  for await (const line of rl) {
    // Каждая строка во входных данных readline будет последовательно доступна здесь как
    // `line`.
  }
}

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

rl.line

[История]

ВерсияИзменения
v15.8.0, v14.18.0Значение всегда будет строкой, никогда не undefined.
v0.1.98Добавлено в: v0.1.98

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

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

Обратите внимание, что изменение значения во время выполнения экземпляра может иметь непредвиденные последствия, если rl.cursor также не контролируется.

Если не используется поток TTY для ввода, используйте событие 'line'.

Один из возможных вариантов использования:

js
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

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

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

API обещаний

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

[Стабильно: 1 - Экспериментально]

Стабильно: 1 Стабильность: 1 - Экспериментально

Класс: readlinePromises.Interface

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

Экземпляры класса 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> Promise, который выполняется с вводом пользователя в ответ на query.

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

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

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

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

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

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

Использование AbortSignal для отмены вопроса.

js
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}`)

Класс: readlinePromises.Readline

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

new readlinePromises.Readline(stream[, options])

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

rl.clearLine(dir)

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

  • dir <целое число>

    • -1: влево от курсора
    • 1: вправо от курсора
    • 0: вся строка
  • Возвращает: this

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

rl.clearScreenDown()

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

  • Возвращает: this

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

rl.commit()

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

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

rl.cursorTo(x[, y])

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

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

rl.moveCursor(dx, dy)

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

Метод 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 и в них должны записываться escape-последовательности ANSI/VT100. По умолчанию: проверка isTTY в потоке output при создании экземпляра.
    • history <string[]> Начальный список строк истории. Этот параметр имеет смысл только в том случае, если terminal установлен в true пользователем или внутренней проверкой output, в противном случае механизм кэширования истории вообще не инициализируется. По умолчанию: [].
    • historySize <number> Максимальное количество сохраняемых строк истории. Чтобы отключить историю, установите это значение в 0. Этот параметр имеет смысл только в том случае, если terminal установлен в true пользователем или внутренней проверкой output, в противном случае механизм кэширования истории вообще не инициализируется. По умолчанию: 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.
  • Возвращает: <readlinePromises.Interface>

Метод readlinePromises.createInterface() создает новый экземпляр readlinePromises.Interface.

js
import { createInterface } from 'node:readline/promises'
import { stdin, stdout } from 'node:process'
const rl = createInterface({
  input: stdin,
  output: stdout,
})
js
const { createInterface } = require('node:readline/promises')
const rl = createInterface({
  input: process.stdin,
  output: process.stdout,
})

После создания экземпляра readlinePromises.Interface наиболее распространенный случай - прослушивание события 'line':

js
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].

js
function completer(line) {
  const completions = '.help .error .exit .quit .q'.split(' ')
  const hits = completions.filter(c => c.startsWith(line))
  // Показать все варианты, если ничего не найдено
  return [hits.length ? hits : completions, line]
}

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

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

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

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

Класс: readline.Interface

[История]

ВерсияИзменения
v17.0.0Класс readline.Interface теперь наследуется от Interface.
v0.1.104Добавлено в: v0.1.104

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

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

Ошибка будет выброшена, если вызвать rl.question() после rl.close().

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

js
rl.question('Какая ваша любимая еда? ', answer => {
  console.log(`О, так ваша любимая еда - это ${answer}`)
})

Использование AbortController для отмены вопроса.

js
const ac = new AbortController()
const signal = ac.signal

rl.question('Какая ваша любимая еда? ', { signal }, answer => {
  console.log(`О, так ваша любимая еда - это ${answer}`)
})

signal.addEventListener(
  'abort',
  () => {
    console.log('Время ожидания ответа на вопрос о еде истекло')
  },
  { once: true }
)

setTimeout(() => ac.abort(), 10000)

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

[История]

ВерсияИзменения
v18.0.0Передача недопустимого обратного вызова в аргумент callback теперь вызывает исключение ERR_INVALID_ARG_TYPE вместо ERR_INVALID_CALLBACK.
v12.7.0Обратный вызов и возвращаемое значение метода write() потока теперь доступны.
v0.7.7Добавлено в: v0.7.7
  • stream <stream.Writable>

  • dir <number>

    • -1: влево от курсора
    • 1: вправо от курсора
    • 0: вся строка
  • callback <Function> Вызывается по завершении операции.

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

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

readline.clearScreenDown(stream[, callback])

[История]

ВерсияИзменения
v18.0.0Передача недопустимого обратного вызова в аргумент callback теперь вызывает исключение ERR_INVALID_ARG_TYPE вместо ERR_INVALID_CALLBACK.
v12.7.0Обратный вызов и возвращаемое значение метода write() потока теперь доступны.
v0.7.7Добавлено в: v0.7.7
  • stream <stream.Writable>
  • callback <Function> Вызывается по завершении операции.
  • Возвращает: <boolean> false, если stream ожидает, что вызывающий код будет ждать события 'drain', прежде чем продолжить запись дополнительных данных; в противном случае true.

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

readline.createInterface(options)

[История]

ВерсияИзменения
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.
v0.1.98Добавлено в: v0.1.98
  • options <Object>

    • input <stream.Readable> Поток Readable для прослушивания. Этот параметр является обязательным.
    • output <stream.Writable> Поток Writable для записи данных readline.
    • completer <Function> Необязательная функция, используемая для автодополнения Tab.
    • terminal <boolean> true, если потоки input и output должны обрабатываться как TTY и в них должны записываться escape-последовательности ANSI/VT100. По умолчанию: проверка isTTY в потоке output при создании экземпляра.
    • history <string[]> Начальный список строк истории. Этот параметр имеет смысл только в том случае, если terminal установлен в true пользователем или внутренней проверкой output, в противном случае механизм кэширования истории вообще не инициализируется. По умолчанию: [].
    • historySize <number> Максимальное количество сохраняемых строк истории. Чтобы отключить историю, установите это значение равным 0. Этот параметр имеет смысл только в том случае, если terminal установлен в true пользователем или внутренней проверкой output, в противном случае механизм кэширования истории вообще не инициализируется. По умолчанию: 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.

js
import { createInterface } from 'node:readline'
import { stdin, stdout } from 'node:process'
const rl = createInterface({
  input: stdin,
  output: stdout,
})
js
const { createInterface } = require('node:readline')
const rl = createInterface({
  input: process.stdin,
  output: process.stdout,
})

После создания экземпляра readline.Interface наиболее распространенный случай — это прослушивание события 'line':

js
rl.on('line', line => {
  console.log(`Получено: ${line}`)
})

Если для этого экземпляра terminal равен true, то поток output получит наилучшую совместимость, если он определяет свойство output.columns и генерирует событие 'resize' в output, если или когда столбцы когда-либо меняются (process.stdout делает это автоматически, когда это TTY).

При создании readline.Interface с использованием stdin в качестве ввода, программа не завершится, пока не получит символ EOF. Чтобы выйти, не дожидаясь ввода пользователя, вызовите process.stdin.unref().

Использование функции completer

Функция completer принимает в качестве аргумента текущую строку, введённую пользователем, и возвращает Array с 2 элементами:

  • Array с совпадающими элементами для автодополнения.
  • Подстрока, которая использовалась для сопоставления.

Например: [[substr1, substr2, ...], originalsubstring].

js
function completer(line) {
  const completions = '.help .error .exit .quit .q'.split(' ')
  const hits = completions.filter(c => c.startsWith(line))
  // Показать все варианты автодополнения, если ничего не найдено
  return [hits.length ? hits : completions, line]
}

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

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

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

[История]

ВерсияИзменения
v18.0.0Передача недопустимого обратного вызова в аргумент callback теперь вызывает исключение ERR_INVALID_ARG_TYPE вместо ERR_INVALID_CALLBACK.
v12.7.0Обратный вызов и возвращаемое значение метода write() потока стали доступны.
v0.7.7Добавлено в: v0.7.7
  • stream <stream.Writable>
  • x <number>
  • y <number>
  • callback <Function> Вызывается после завершения операции.
  • Возвращаемое значение: <boolean> false, если stream желает, чтобы вызывающий код ожидал события 'drain', прежде чем продолжить запись дополнительных данных; в противном случае true.

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

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

[История]

ВерсияИзменения
v18.0.0Передача недопустимого обратного вызова в аргумент callback теперь вызывает исключение ERR_INVALID_ARG_TYPE вместо ERR_INVALID_CALLBACK.
v12.7.0Обратный вызов и возвращаемое значение метода write() потока стали доступны.
v0.7.7Добавлено в: v0.7.7
  • stream <stream.Writable>
  • dx <number>
  • dy <number>
  • callback <Function> Вызывается после завершения операции.
  • Возвращаемое значение: <boolean> false, если stream желает, чтобы вызывающий код ожидал события 'drain', прежде чем продолжить запись дополнительных данных; в противном случае true.

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

readline.emitKeypressEvents(stream[, interface])

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

Метод readline.emitKeypressEvents() заставляет заданный поток Readable начать генерировать события 'keypress', соответствующие принятому вводу.

Необязательно, interface указывает экземпляр readline.Interface, для которого автодополнение отключено, когда обнаружен скопированный вставленный ввод.

Если stream является TTY, то он должен быть в сыром режиме.

Это автоматически вызывается любым экземпляром readline на его input, если input является терминалом. Закрытие экземпляра readline не останавливает input от генерации событий 'keypress'.

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

Пример: Минимальный CLI

В следующем примере показано использование класса readline.Interface для реализации небольшого интерфейса командной строки:

js
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)
})
js
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:

js
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,
  })
  // Примечание: мы используем опцию crlfDelay для распознавания всех экземпляров CR LF
  // ('\r\n') в input.txt как одного разрыва строки.

  for await (const line of rl) {
    // Каждая строка в input.txt будет последовательно доступна здесь как `line`.
    console.log(`Строка из файла: ${line}`)
  }
}

processLineByLine()
js
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,
  })
  // Примечание: мы используем опцию crlfDelay для распознавания всех экземпляров CR LF
  // ('\r\n') в input.txt как одного разрыва строки.

  for await (const line of rl) {
    // Каждая строка в input.txt будет последовательно доступна здесь как `line`.
    console.log(`Строка из файла: ${line}`)
  }
}

processLineByLine()

В качестве альтернативы можно использовать событие 'line':

js
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}`)
})
js
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}`)
})

В настоящее время цикл for await...of может быть немного медленнее. Если важны как асинхронный/await поток, так и скорость, можно применить комбинированный подход:

js
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 => {
      // Обработка строки.
    })

    await once(rl, 'close')

    console.log('Файл обработан.')
  } catch (err) {
    console.error(err)
  }
})()
js
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 => {
      // Обработка строки.
    })

    await once(rl, 'close')

    console.log('Файл обработан.')
  } catch (err) {
    console.error(err)
  }
})()

Связывания клавиш TTY

Связывания клавишОписаниеПримечания
+ +Удалить строку слеваНе работает в Linux, Mac и Windows
+ +Удалить строку справаНе работает в Mac
+Отправить SIGINT или закрыть экземпляр readline
+Удалить влево
+Удалить вправо или закрыть экземпляр readline, если текущая строка пуста / EOFНе работает в Windows
+Удалить от текущей позиции до начала строки
+Удалить от текущей позиции до конца строки
+Восстановить (вспомнить) ранее удалённый текстРаботает только с текстом, удалённым с помощью + или +
+Переключаться между ранее удалёнными текстамиДоступно только, если последний нажатый ключ был + или +
+Перейти в начало строки
+Перейти в конец строки
+Вернуться на один символ назад
+Перейти на один символ вперёд
+Очистить экран
+Следующий элемент истории
+Предыдущий элемент истории
+Отменить предыдущее изменениеЛюбое нажатие клавиши, которое отправляет код клавиши 0x1F , выполнит это действие. Во многих терминалах, например, xterm , это связано с + .
+Повторить предыдущее изменениеВо многих терминалах нет клавиши повтора по умолчанию. Мы выбираем код клавиши 0x1E для выполнения повтора. В xterm , он по умолчанию связан с + .
+Перемещает запущенный процесс в фоновый режим. Введите fg и нажмите для возврата.Не работает в Windows
+ или +Удалить назад до границы слова+ Не работает в Linux, Mac и Windows
+Удалить вперёд до границы словаНе работает в Mac
+ или +Слово влево+ Не работает в Mac
+ или +Слово вправо+ Не работает в Mac
+ или +Удалить слово вправо+ Не работает в Windows
+Удалить слово влевоНе работает в Mac