Readline
[Стабильно: 2 - Стабильно]
Стабильно: 2 Стабильность: 2 - Стабильно
Исходный код: lib/readline.js
Модуль node:readline
предоставляет интерфейс для чтения данных из потока Readable (например, process.stdin
) построчно.
Для использования API на основе промисов:
import * as readline from 'node:readline/promises'
const readline = require('node:readline/promises')
Для использования API с обратными вызовами и синхронного API:
import * as readline from 'node:readline'
const readline = require('node:readline')
Следующий простой пример иллюстрирует базовое использование модуля node:readline
.
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()
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
- Расширяет: <EventEmitter>
Экземпляры класса InterfaceConstructor
создаются с помощью метода readlinePromises.createInterface()
или readline.createInterface()
. Каждый экземпляр связан с одним потоком input
Readable и одним потоком output
Writable. Поток output
используется для вывода приглашений для ввода пользователя, который поступает и считывается из потока input
.
Событие: 'close'
Добавлено в: v0.1.98
Событие 'close'
генерируется в одном из следующих случаев:
- Вызывается метод
rl.close()
, и экземплярInterfaceConstructor
отказался от управления потокамиinput
иoutput
; - Поток
input
получает событие'end'
; - Поток
input
получает + для сигнализации конца передачи (EOT); - Поток
input
получает + для сигнализацииSIGINT
, и обработчик события'SIGINT'
не зарегистрирован в экземпляреInterfaceConstructor
.
Функция прослушивателя вызывается без передачи каких-либо аргументов.
Экземпляр InterfaceConstructor
завершает работу после генерации события 'close'
.
Событие: 'line'
Добавлено в: v0.1.98
Событие 'line'
генерируется всякий раз, когда поток input
получает входные данные конца строки (\n
, \r
или \r\n
). Обычно это происходит, когда пользователь нажимает или .
Событие 'line'
также генерируется, если новые данные были считаны из потока, и этот поток завершается без финального маркера конца строки.
Функция прослушивателя вызывается со строкой, содержащей одну строку полученных входных данных.
rl.on('line', input => {
console.log(`Received: ${input}`)
})
Событие: 'history'
Добавлено в: v15.8.0, v14.18.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 возобновлен.')
})
Событие: 'SIGCONT'
Добавлено в: v0.7.5
Событие 'SIGCONT'
генерируется, когда процесс Node.js, ранее переведенный в фоновый режим с помощью + (т.е. SIGTSTP
), возвращается на передний план с помощью fg(1p)
.
Если поток input
был приостановлен до запроса SIGTSTP
, это событие генерироваться не будет.
Функция прослушивателя вызывается без передачи каких-либо аргументов.
rl.on('SIGCONT', () => {
// `prompt` автоматически возобновит поток
rl.prompt()
})
Событие 'SIGCONT'
не поддерживается в Windows.
Событие: 'SIGINT'
Добавлено в: v0.3.0
Событие 'SIGINT'
генерируется всякий раз, когда поток input
получает входные данные, обычно известные как SIGINT
. Если при получении потоком input
сигнала SIGINT
не зарегистрировано обработчиков событий 'SIGINT'
, будет сгенерировано событие 'pause'
.
Функция прослушивателя вызывается без передачи каких-либо аргументов.
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
был приостановлен до того, как процесс был переведен в фоновый режим.
Функция прослушивателя вызывается без передачи каких-либо аргументов.
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
prompt
<string>
Метод rl.setPrompt()
устанавливает приглашение, которое будет выводиться в output
при каждом вызове rl.prompt()
.
rl.getPrompt()
Добавлено в: v15.3.0, v14.17.0
- Возвращает: <string> текущую строку приглашения
Метод rl.getPrompt()
возвращает текущее приглашение, используемое rl.prompt()
.
rl.write(data[, key])
Добавлено в: v0.1.98
Метод rl.write()
записывает data
или последовательность клавиш, идентифицированную key
, в output
. Аргумент key
поддерживается только в том случае, если output
является текстовым терминалом TTY. Список сочетаний клавиш см. в разделе Сочетания клавиш TTY.
Если указан key
, data
игнорируется.
При вызове rl.write()
возобновляет поток input
, если он был приостановлен.
Если InterfaceConstructor
был создан с output
, установленным в null
или undefined
, data
и key
не записываются.
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>
Создает объект AsyncIterator
, который перебирает каждую строку во входном потоке как строку. Этот метод позволяет асинхронную итерацию объектов InterfaceConstructor
через циклы for await...of
.
Ошибки во входном потоке не передаются дальше.
Если цикл завершается с помощью break
, throw
или return
, будет вызван метод rl.close()
. Другими словами, итерация по InterfaceConstructor
всегда полностью потребляет входной поток.
Производительность не соответствует традиционному API события 'line'
. Для производительных приложений используйте 'line'
.
async function processLineByLine() {
const rl = readline.createInterface({
// ...
})
for await (const line of rl) {
// Каждая строка во входных данных 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'
.
Один из возможных вариантов использования:
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>
Возвращает реальную позицию курсора относительно приглашения + строки ввода. Длинные входные (переносимые) строки, а также приглашения из нескольких строк включены в вычисления.
API обещаний
Добавлено в: v17.0.0
[Стабильно: 1 - Экспериментально]
Стабильно: 1 Стабильность: 1 - Экспериментально
Класс: readlinePromises.Interface
Добавлено в: v17.0.0
- Расширяет: <readline.InterfaceConstructor>
Экземпляры класса readlinePromises.Interface
создаются с помощью метода readlinePromises.createInterface()
. Каждый экземпляр связан с одним потоком input
Readable и одним потоком output
Writable. Поток output
используется для вывода приглашений для ввода пользователя, который поступает и считывается из потока input
.
rl.question(query[, options])
Добавлено в: v17.0.0
query
<string> Утверждение или запрос для записи вoutput
, добавляемый к подсказке.options
<Object>signal
<AbortSignal> Позволяет опционально отменитьquestion()
с помощьюAbortSignal
.
Возвращает: <Promise> Promise, который выполняется с вводом пользователя в ответ на
query
.
Метод rl.question()
отображает query
, записывая его в output
, ожидает ввода пользователя в input
, затем вызывает функцию callback
, передавая предоставленный ввод в качестве первого аргумента.
При вызове rl.question()
возобновит поток input
, если он был приостановлен.
Если readlinePromises.Interface
был создан с output
, установленным в null
или undefined
, query
не записывается.
Если вопрос задан после rl.close()
, возвращается отклоненное promise.
Пример использования:
const answer = await rl.question('What is your favorite food? ')
console.log(`Oh, so your favorite food is ${answer}`)
Использование AbortSignal
для отмены вопроса.
const signal = AbortSignal.timeout(10_000)
signal.addEventListener(
'abort',
() => {
console.log('The food question timed out')
},
{ once: true }
)
const answer = await rl.question('What is your favorite food? ', { signal })
console.log(`Oh, so your favorite food is ${answer}`)
Класс: readlinePromises.Readline
Добавлено в: v17.0.0
new readlinePromises.Readline(stream[, options])
Добавлено в: v17.0.0
stream
<stream.Writable> Поток TTY.options
<Object>autoCommit
<boolean> Еслиtrue
, вызыватьrl.commit()
не нужно.
rl.clearLine(dir)
Добавлено в: v17.0.0
dir
<целое число>-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
- Возвращает: <Promise>
Метод rl.commit()
отправляет все ожидающие действия в связанный stream
и очищает внутренний список ожидающих действий.
rl.cursorTo(x[, y])
Добавлено в: v17.0.0
x
<целое число>y
<целое число>- Возвращает: this
Метод rl.cursorTo()
добавляет в внутренний список ожидающих действий действие, перемещающее курсор в указанное положение в связанном stream
. Вызовите rl.commit()
, чтобы увидеть результат этого метода, если только autoCommit: true
не был передан в конструктор.
rl.moveCursor(dx, dy)
Добавлено в: v17.0.0
dx
<целое число>dy
<целое число>- Возвращает: this
Метод rl.moveCursor()
добавляет в внутренний список ожидающих действий действие, перемещающее курсор относительно его текущего положения в связанном stream
. Вызовите rl.commit()
, чтобы увидеть результат этого метода, если только autoCommit: true
не был передан в конструктор.
rl.rollback()
Добавлен в: v17.0.0
- Возвращает: this
Метод rl.rollback
очищает внутренний список ожидающих действий, не отправляя его в связанный stream
.
readlinePromises.createInterface(options)
Добавлен в: v17.0.0
options
<Object>input
<stream.Readable> Поток Readable для прослушивания. Этот параметр является обязательным.output
<stream.Writable> Поток Writable для записи данных readline.completer
<Function> Необязательная функция, используемая для автодополнения Tab.terminal
<boolean>true
, если потокиinput
иoutput
должны обрабатываться как TTY и в них должны записываться 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
.
import { createInterface } from 'node:readline/promises'
import { stdin, stdout } from 'node:process'
const rl = createInterface({
input: stdin,
output: stdout,
})
const { createInterface } = require('node:readline/promises')
const rl = createInterface({
input: process.stdin,
output: process.stdout,
})
После создания экземпляра readlinePromises.Interface
наиболее распространенный случай - прослушивание события 'line'
:
rl.on('line', line => {
console.log(`Received: ${line}`)
})
Если 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))
// Показать все варианты, если ничего не найдено
return [hits.length ? hits : completions, line]
}
Функция completer
также может возвращать <Promise> или быть асинхронной:
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.InterfaceConstructor>
Экземпляры класса readline.Interface
создаются с помощью метода readline.createInterface()
. Каждый экземпляр связан с одним потоком input
Readable и одним потоком output
Writable. Поток output
используется для вывода приглашений для ввода пользователя, который поступает и считывается из потока input
.
rl.question(query[, options], callback)
Добавлено в: v0.3.3
query
<string> Утверждение или запрос для записи вoutput
, добавляемый перед приглашением.options
<Object>signal
<AbortSignal> Дополнительно позволяет отменитьquestion()
с помощьюAbortController
.
callback
<Function> Функция обратного вызова, которая вызывается с вводом пользователя в ответ наquery
.
Метод rl.question()
отображает query
, записывая его в output
, ожидает ввода пользователя в input
, а затем вызывает функцию callback
, передавая предоставленный ввод в качестве первого аргумента.
При вызове rl.question()
возобновит поток input
, если он был приостановлен.
Если readline.Interface
был создан с output
, установленным в null
или undefined
, query
не записывается.
Функция callback
, переданная в rl.question()
, не следует типичному шаблону принятия объекта Error
или null
в качестве первого аргумента. callback
вызывается с предоставленным ответом в качестве единственного аргумента.
Ошибка будет выброшена, если вызвать rl.question()
после rl.close()
.
Пример использования:
rl.question('Какая ваша любимая еда? ', answer => {
console.log(`О, так ваша любимая еда - это ${answer}`)
})
Использование AbortController
для отмены вопроса.
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
.
import { createInterface } from 'node:readline'
import { stdin, stdout } from 'node:process'
const rl = createInterface({
input: stdin,
output: stdout,
})
const { createInterface } = require('node:readline')
const rl = createInterface({
input: process.stdin,
output: process.stdout,
})
После создания экземпляра readline.Interface
наиболее распространенный случай — это прослушивание события 'line'
:
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]
.
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
может быть вызвана асинхронно, если она принимает два аргумента:
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
stream
<stream.Readable>interface
<readline.InterfaceConstructor>
Метод readline.emitKeypressEvents()
заставляет заданный поток Readable начать генерировать события 'keypress'
, соответствующие принятому вводу.
Необязательно, interface
указывает экземпляр readline.Interface
, для которого автодополнение отключено, когда обнаружен скопированный вставленный ввод.
Если stream
является TTY, то он должен быть в сыром режиме.
Это автоматически вызывается любым экземпляром readline на его input
, если input
является терминалом. Закрытие экземпляра readline
не останавливает input
от генерации событий 'keypress'
.
readline.emitKeypressEvents(process.stdin)
if (process.stdin.isTTY) process.stdin.setRawMode(true)
Пример: Минимальный CLI
В следующем примере показано использование класса readline.Interface
для реализации небольшого интерфейса командной строки:
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)
})
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
:
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()
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'
:
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}`)
})
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 поток, так и скорость, можно применить комбинированный подход:
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)
}
})()
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 |