Readline
[Estável: 2 - Estável]
Estável: 2 Estabilidade: 2 - Estável
Código-Fonte: lib/readline.js
O módulo node:readline
fornece uma interface para ler dados de um fluxo Legível (como process.stdin
) linha por linha.
Para usar as APIs baseadas em promises:
import * as readline from 'node:readline/promises'
const readline = require('node:readline/promises')
Para usar as APIs de callback e síncronas:
import * as readline from 'node:readline'
const readline = require('node:readline')
O seguinte exemplo simples ilustra o uso básico do módulo 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('O que você pensa sobre o Node.js? ')
console.log(`Obrigado pelo seu valioso feedback: ${answer}`)
rl.close()
const readline = require('node:readline')
const { stdin: input, stdout: output } = require('node:process')
const rl = readline.createInterface({ input, output })
rl.question('O que você pensa sobre o Node.js? ', answer => {
// TODO: Registrar a resposta em um banco de dados
console.log(`Obrigado pelo seu valioso feedback: ${answer}`)
rl.close()
})
Uma vez que este código é invocado, o aplicativo Node.js não terminará até que o readline.Interface
seja fechado porque a interface espera que os dados sejam recebidos no fluxo input
.
Classe: InterfaceConstructor
Adicionado em: v0.1.104
- Extende: <EventEmitter>
Instâncias da classe InterfaceConstructor
são construídas usando o método readlinePromises.createInterface()
ou readline.createInterface()
. Cada instância está associada a um único fluxo de entrada Legível e a um único fluxo de saída Gravável. O fluxo de saída é usado para imprimir prompts para entrada do usuário que chega e é lida do fluxo de entrada.
Evento: 'close'
Adicionado em: v0.1.98
O evento 'close'
é emitido quando um dos seguintes eventos ocorre:
- O método
rl.close()
é chamado e a instânciaInterfaceConstructor
liberou o controle sobre os fluxosinput
eoutput
; - O fluxo
input
recebe seu evento'end'
; - O fluxo
input
recebe + para sinalizar o fim da transmissão (EOT); - O fluxo
input
recebe + para sinalizarSIGINT
e nenhum ouvinte de evento'SIGINT'
está registrado na instânciaInterfaceConstructor
.
A função listener é chamada sem passar nenhum argumento.
A instância InterfaceConstructor
é finalizada assim que o evento 'close'
é emitido.
Evento: 'line'
Adicionado em: v0.1.98
O evento 'line'
é emitido sempre que o fluxo input
recebe uma entrada de fim de linha (\n
, \r
ou \r\n
). Isso geralmente ocorre quando o usuário pressiona ou .
O evento 'line'
também é emitido se novos dados foram lidos de um fluxo e esse fluxo termina sem um marcador final de fim de linha.
A função listener é chamada com uma string contendo a única linha de entrada recebida.
rl.on('line', input => {
console.log(`Recebido: ${input}`)
})
Evento: 'history'
Adicionado em: v15.8.0, v14.18.0
O evento 'history'
é emitido sempre que a matriz de histórico muda.
A função listener é chamada com uma matriz contendo a matriz de histórico. Ela refletirá todas as alterações, linhas adicionadas e linhas removidas devido a historySize
e removeHistoryDuplicates
.
O objetivo principal é permitir que um listener persista o histórico. Também é possível para o listener alterar o objeto de histórico. Isso pode ser útil para evitar que determinadas linhas sejam adicionadas ao histórico, como uma senha.
rl.on('history', history => {
console.log(`Recebido: ${history}`)
})
Evento: 'pause'
Adicionado em: v0.7.5
O evento 'pause'
é emitido quando um dos seguintes eventos ocorre:
- O fluxo
input
é pausado. - O fluxo
input
não está pausado e recebe o evento'SIGCONT'
. (Veja os eventos'SIGTSTP'
e'SIGCONT'
.)
A função listener é chamada sem passar nenhum argumento.
rl.on('pause', () => {
console.log('Readline pausado.')
})
Evento: 'resume'
Adicionado em: v0.7.5
O evento 'resume'
é emitido sempre que o fluxo de input
é retomado.
A função de listener é chamada sem passar nenhum argumento.
rl.on('resume', () => {
console.log('Readline retomado.')
})
Evento: 'SIGCONT'
Adicionado em: v0.7.5
O evento 'SIGCONT'
é emitido quando um processo Node.js previamente movido para segundo plano usando + (ou seja, SIGTSTP
) é então trazido de volta para o primeiro plano usando fg(1p)
.
Se o fluxo de input
foi pausado antes da solicitação SIGTSTP
, este evento não será emitido.
A função de listener é invocada sem passar nenhum argumento.
rl.on('SIGCONT', () => {
// `prompt` irá automaticamente retomar o fluxo
rl.prompt()
})
O evento 'SIGCONT'
não é suportado no Windows.
Evento: 'SIGINT'
Adicionado em: v0.3.0
O evento 'SIGINT'
é emitido sempre que o fluxo de input
recebe uma entrada, tipicamente conhecida como SIGINT
. Se não houver listeners de evento 'SIGINT'
registrados quando o fluxo de input
recebe um SIGINT
, o evento 'pause'
será emitido.
A função de listener é invocada sem passar nenhum argumento.
rl.on('SIGINT', () => {
rl.question('Tem certeza de que deseja sair? ', answer => {
if (answer.match(/^y(es)?$/i)) rl.pause()
})
})
Evento: 'SIGTSTP'
Adicionado em: v0.7.5
O evento 'SIGTSTP'
é emitido quando o fluxo de input
recebe uma entrada +, tipicamente conhecida como SIGTSTP
. Se não houver listeners de evento 'SIGTSTP'
registrados quando o fluxo de input
recebe um SIGTSTP
, o processo Node.js será enviado para segundo plano.
Quando o programa é retomado usando fg(1p)
, os eventos 'pause'
e 'SIGCONT'
serão emitidos. Estes podem ser usados para retomar o fluxo de input
.
Os eventos 'pause'
e 'SIGCONT'
não serão emitidos se o input
foi pausado antes do processo ser enviado para segundo plano.
A função de listener é invocada sem passar nenhum argumento.
rl.on('SIGTSTP', () => {
// Isto irá sobrescrever SIGTSTP e prevenir o programa de ir para o
// segundo plano.
console.log('SIGTSTP capturado.')
})
O evento 'SIGTSTP'
não é suportado no Windows.
rl.close()
Adicionado em: v0.1.98
O método rl.close()
fecha a instância InterfaceConstructor
e libera o controle sobre os fluxos input
e output
. Quando chamado, o evento 'close'
será emitido.
Chamar rl.close()
não interrompe imediatamente outros eventos (incluindo 'line'
) de serem emitidos pela instância InterfaceConstructor
.
rl.pause()
Adicionado em: v0.3.4
O método rl.pause()
pausa o fluxo input
, permitindo que seja retomado posteriormente, se necessário.
Chamar rl.pause()
não pausa imediatamente outros eventos (incluindo 'line'
) de serem emitidos pela instância InterfaceConstructor
.
rl.prompt([preserveCursor])
Adicionado em: v0.1.98
preserveCursor
<boolean> Setrue
, impede que o posicionamento do cursor seja redefinido para0
.
O método rl.prompt()
escreve o prompt
configurado das instâncias InterfaceConstructor
em uma nova linha em output
para fornecer ao usuário um novo local para fornecer entrada.
Quando chamado, rl.prompt()
retomará o fluxo input
se ele tiver sido pausado.
Se o InterfaceConstructor
foi criado com output
definido como null
ou undefined
, o prompt não é escrito.
rl.resume()
Adicionado em: v0.3.4
O método rl.resume()
retoma o fluxo input
se ele tiver sido pausado.
rl.setPrompt(prompt)
Adicionado em: v0.1.98
prompt
<string>
O método rl.setPrompt()
define o prompt que será escrito para output
sempre que rl.prompt()
for chamado.
rl.getPrompt()
Adicionado em: v15.3.0, v14.17.0
- Retorna: <string> a string de prompt atual
O método rl.getPrompt()
retorna o prompt atual usado por rl.prompt()
.
rl.write(data[, key])
Adicionado em: v0.1.98
O método rl.write()
escreverá data
ou uma sequência de teclas identificada por key
para o output
. O argumento key
é suportado apenas se output
for um terminal de texto TTY. Veja Combinações de teclas TTY para uma lista de combinações de teclas.
Se key
for especificado, data
será ignorado.
Quando chamado, rl.write()
retomará o fluxo input
se ele tiver sido pausado.
Se o InterfaceConstructor
foi criado com output
definido como null
ou undefined
, data
e key
não são escritos.
rl.write('Delete this!')
// Simula Ctrl+U para apagar a linha escrita anteriormente
rl.write(null, { ctrl: true, name: 'u' })
O método rl.write()
escreverá os dados para a entrada input
da Interface
readline
como se fosse fornecido pelo usuário.
rl[Symbol.asyncIterator]()
[Histórico]
Versão | Alterações |
---|---|
v11.14.0, v10.17.0 | O suporte a Symbol.asyncIterator não é mais experimental. |
v11.4.0, v10.16.0 | Adicionado em: v11.4.0, v10.16.0 |
- Retorna: <AsyncIterator>
Cria um objeto AsyncIterator
que itera por cada linha na entrada como uma string. Este método permite a iteração assíncrona de objetos InterfaceConstructor
através de loops for await...of
.
Erros na entrada não são repassados.
Se o loop for terminado com break
, throw
ou return
, rl.close()
será chamado. Em outras palavras, iterar sobre um InterfaceConstructor
sempre consumirá a entrada completamente.
O desempenho não é comparável à API de evento tradicional 'line'
. Use 'line'
para aplicações sensíveis a desempenho.
async function processLineByLine() {
const rl = readline.createInterface({
// ...
})
for await (const line of rl) {
// Cada linha na entrada do readline estará sucessivamente disponível aqui como
// `line`.
}
}
readline.createInterface()
começará a consumir a entrada assim que invocado. Ter operações assíncronas entre a criação da interface e a iteração assíncrona pode resultar em linhas perdidas.
rl.line
[Histórico]
Versão | Alterações |
---|---|
v15.8.0, v14.18.0 | O valor será sempre uma string, nunca indefinido. |
v0.1.98 | Adicionado em: v0.1.98 |
Os dados de entrada atuais sendo processados pelo nó.
Isso pode ser usado ao coletar entrada de um fluxo TTY para recuperar o valor atual que foi processado até agora, antes do evento line
ser emitido. Uma vez que o evento line
foi emitido, esta propriedade será uma string vazia.
Esteja ciente de que modificar o valor durante o tempo de execução da instância pode ter consequências imprevistas se rl.cursor
não for também controlado.
Se não estiver usando um fluxo TTY para entrada, use o evento 'line'
.
Um possível caso de uso seria o seguinte:
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
Adicionado em: v0.1.98
A posição do cursor em relação a rl.line
.
Isso rastreará onde o cursor atual se posiciona na string de entrada, ao ler a entrada de um stream TTY. A posição do cursor determina a parte da string de entrada que será modificada à medida que a entrada é processada, bem como a coluna onde o caret do terminal será renderizado.
rl.getCursorPos()
Adicionado em: v13.5.0, v12.16.0
- Retorna: <Object>
Retorna a posição real do cursor em relação ao prompt de entrada + string. Strings de entrada longas (com quebras de linha), bem como prompts de várias linhas são incluídos nos cálculos.
Promises API
Adicionado em: v17.0.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1 - Experimental
Classe: readlinePromises.Interface
Adicionado em: v17.0.0
- Extende: <readline.InterfaceConstructor>
Instâncias da classe readlinePromises.Interface
são construídas usando o método readlinePromises.createInterface()
. Cada instância está associada a um único stream input
Readable e a um único stream output
Writable. O stream output
é usado para imprimir prompts para entrada do usuário que chega e é lida do stream input
.
rl.question(query[, options])
Adicionado em: v17.0.0
query
<string> Uma declaração ou consulta a ser escrita emoutput
, precedendo o prompt.options
<Object>signal
<AbortSignal> Opcionalmente permite quequestion()
seja cancelado usando umAbortSignal
.
Retorna: <Promise> Uma promessa que é cumprida com a entrada do usuário em resposta à
query
.
O método rl.question()
exibe a query
escrevendo-a em output
, aguarda a entrada do usuário em input
e, em seguida, invoca a função callback
passando a entrada fornecida como o primeiro argumento.
Quando chamado, rl.question()
retomará o fluxo input
se ele tiver sido pausado.
Se o readlinePromises.Interface
foi criado com output
definido como null
ou undefined
, a query
não é escrita.
Se a pergunta for chamada após rl.close()
, ela retorna uma promessa rejeitada.
Exemplo de uso:
const answer = await rl.question('Qual sua comida favorita? ')
console.log(`Ah, então sua comida favorita é ${answer}`)
Usando um AbortSignal
para cancelar uma pergunta.
const signal = AbortSignal.timeout(10_000)
signal.addEventListener(
'abort',
() => {
console.log('A pergunta sobre comida expirou')
},
{ once: true }
)
const answer = await rl.question('Qual sua comida favorita? ', { signal })
console.log(`Ah, então sua comida favorita é ${answer}`)
Classe: readlinePromises.Readline
Adicionado em: v17.0.0
new readlinePromises.Readline(stream[, options])
Adicionado em: v17.0.0
stream
<stream.Writable> Um fluxo TTY.options
<Object>autoCommit
<boolean> Setrue
, não há necessidade de chamarrl.commit()
.
rl.clearLine(dir)
Adicionado em: v17.0.0
dir
<inteiro>-1
: para a esquerda do cursor1
: para a direita do cursor0
: a linha inteira
Retorna: this
O método rl.clearLine()
adiciona à lista interna de ações pendentes uma ação que limpa a linha atual do stream
associado em uma direção especificada identificada por dir
. Chame rl.commit()
para ver o efeito deste método, a menos que autoCommit: true
tenha sido passado para o construtor.
rl.clearScreenDown()
Adicionado em: v17.0.0
- Retorna: this
O método rl.clearScreenDown()
adiciona à lista interna de ações pendentes uma ação que limpa o stream
associado da posição atual do cursor para baixo. Chame rl.commit()
para ver o efeito deste método, a menos que autoCommit: true
tenha sido passado para o construtor.
rl.commit()
Adicionado em: v17.0.0
- Retorna: <Promise>
O método rl.commit()
envia todas as ações pendentes para o stream
associado e limpa a lista interna de ações pendentes.
rl.cursorTo(x[, y])
Adicionado em: v17.0.0
O método rl.cursorTo()
adiciona à lista interna de ações pendentes uma ação que move o cursor para a posição especificada no stream
associado. Chame rl.commit()
para ver o efeito deste método, a menos que autoCommit: true
tenha sido passado para o construtor.
rl.moveCursor(dx, dy)
Adicionado em: v17.0.0
O método rl.moveCursor()
adiciona à lista interna de ações pendentes uma ação que move o cursor relativamente à sua posição atual no stream
associado. Chame rl.commit()
para ver o efeito deste método, a menos que autoCommit: true
tenha sido passado para o construtor.
rl.rollback()
Adicionado em: v17.0.0
- Retorna: this
O método rl.rollback
limpa a lista interna de ações pendentes sem enviá-la para o stream
associado.
readlinePromises.createInterface(options)
Adicionado em: v17.0.0
options
<Object>input
<stream.Readable> O fluxo Readable para ouvir. Esta opção é obrigatória.output
<stream.Writable> O fluxo Writable para escrever dados readline.completer
<Function> Uma função opcional usada para autocompletar com Tab.terminal
<boolean>true
se os fluxosinput
eoutput
devem ser tratados como um TTY e ter códigos de escape ANSI/VT100 escritos nele. Padrão: verificandoisTTY
no fluxooutput
na instanciação.history
<string[]> Lista inicial de linhas de histórico. Esta opção só faz sentido seterminal
estiver definido comotrue
pelo usuário ou por uma verificação interna deoutput
, caso contrário, o mecanismo de cache de histórico não é inicializado. Padrão:[]
.historySize
<number> Número máximo de linhas de histórico retidas. Para desativar o histórico, defina este valor como0
. Esta opção só faz sentido seterminal
estiver definido comotrue
pelo usuário ou por uma verificação interna deoutput
, caso contrário, o mecanismo de cache de histórico não é inicializado. Padrão:30
.removeHistoryDuplicates
<boolean> Setrue
, quando uma nova linha de entrada adicionada à lista de histórico duplicar uma mais antiga, isso remove a linha mais antiga da lista. Padrão:false
.prompt
<string> A string de prompt a ser usada. Padrão:'\> '
.crlfDelay
<number> Se o atraso entre\r
e\n
excedercrlfDelay
milissegundos,\r
e\n
serão tratados como entradas separadas de fim de linha.crlfDelay
será forçado a um número não inferior a100
. Pode ser definido comoInfinity
, caso em que\r
seguido de\n
sempre será considerado uma única nova linha (o que pode ser razoável para ler arquivos com delimitador de linha\r\n
). Padrão:100
.escapeCodeTimeout
<number> A duração quereadlinePromises
esperará por um caractere (ao ler uma sequência de tecla ambígua em milissegundos, uma que pode formar uma sequência de tecla completa usando a entrada lida até agora e pode receber entrada adicional para completar uma sequência de tecla mais longa). Padrão:500
.tabSize
<integer> O número de espaços a que uma tabulação é igual (mínimo 1). Padrão:8
.
Retorna: <readlinePromises.Interface>
O método readlinePromises.createInterface()
cria uma nova instância 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,
})
Assim que a instância readlinePromises.Interface
for criada, o caso mais comum é ouvir o evento 'line'
:
rl.on('line', line => {
console.log(`Recebido: ${line}`)
})
Se terminal
for true
para esta instância, o fluxo output
terá a melhor compatibilidade se definir uma propriedade output.columns
e emitir um evento 'resize'
no output
se ou quando as colunas mudarem (process.stdout
faz isso automaticamente quando é um TTY).
Uso da função completer
A função completer
recebe como argumento a linha atual inserida pelo usuário e retorna um Array
com 2 entradas:
- Um
Array
com entradas correspondentes para a conclusão. - A substring que foi usada para a correspondência.
Por exemplo: [[substr1, substr2, ...], originalsubstring]
.
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ')
const hits = completions.filter(c => c.startsWith(line))
// Mostrar todas as conclusões se nenhuma for encontrada
return [hits.length ? hits : completions, line]
}
A função completer
também pode retornar uma <Promise>, ou ser assíncrona:
async function completer(linePartial) {
await someAsyncWork()
return [['123'], linePartial]
}
API de Callback
Adicionado em: v0.1.104
Classe: readline.Interface
[Histórico]
Versão | Alterações |
---|---|
v17.0.0 | A classe readline.Interface agora herda de Interface . |
v0.1.104 | Adicionada em: v0.1.104 |
- Extende: <readline.InterfaceConstructor>
Instâncias da classe readline.Interface
são construídas usando o método readline.createInterface()
. Cada instância está associada a um único fluxo input
Readable e a um único fluxo output
Writable. O fluxo output
é usado para imprimir prompts para entrada do usuário que chega e é lida do fluxo input
.
rl.question(query[, options], callback)
Adicionado em: v0.3.3
query
<string> Uma declaração ou consulta a ser escrita paraoutput
, precedida do prompt.options
<Object>signal
<AbortSignal> Opcionalmente permite quequestion()
seja cancelado usando umAbortController
.
callback
<Function> Uma função de callback que é invocada com a entrada do usuário em resposta àquery
.
O método rl.question()
exibe a query
escrevendo-a para output
, espera que a entrada do usuário seja fornecida em input
e, em seguida, invoca a função callback
passando a entrada fornecida como o primeiro argumento.
Quando chamado, rl.question()
retomará o fluxo input
se ele tiver sido pausado.
Se o readline.Interface
foi criado com output
definido como null
ou undefined
, a query
não é escrita.
A função callback
passada para rl.question()
não segue o padrão típico de aceitar um objeto Error
ou null
como o primeiro argumento. O callback
é chamado com a resposta fornecida como o único argumento.
Um erro será lançado se rl.question()
for chamado após rl.close()
.
Exemplo de uso:
rl.question('Qual sua comida favorita? ', answer => {
console.log(`Ah, então sua comida favorita é ${answer}`)
})
Usando um AbortController
para cancelar uma pergunta.
const ac = new AbortController()
const signal = ac.signal
rl.question('Qual sua comida favorita? ', { signal }, answer => {
console.log(`Ah, então sua comida favorita é ${answer}`)
})
signal.addEventListener(
'abort',
() => {
console.log('A pergunta sobre comida expirou')
},
{ once: true }
)
setTimeout(() => ac.abort(), 10000)
readline.clearLine(stream, dir[, callback])
[Histórico]
Versão | Alterações |
---|---|
v18.0.0 | Passar um callback inválido para o argumento callback agora lança ERR_INVALID_ARG_TYPE em vez de ERR_INVALID_CALLBACK . |
v12.7.0 | O callback e o valor de retorno do write() do stream são expostos. |
v0.7.7 | Adicionado em: v0.7.7 |
stream
<stream.Writable>dir
<number>-1
: para a esquerda do cursor1
: para a direita do cursor0
: a linha inteira
callback
<Function> Invoca-se assim que a operação é concluída.Retorna: <boolean>
false
sestream
deseja que o código chamador aguarde o evento'drain'
ser emitido antes de continuar a escrever dados adicionais; caso contrário,true
.
O método readline.clearLine()
limpa a linha atual do stream TTY dado em uma direção especificada identificada por dir
.
readline.clearScreenDown(stream[, callback])
[Histórico]
Versão | Alterações |
---|---|
v18.0.0 | Passar um callback inválido para o argumento callback agora lança ERR_INVALID_ARG_TYPE em vez de ERR_INVALID_CALLBACK . |
v12.7.0 | O callback e o valor de retorno do write() do stream são expostos. |
v0.7.7 | Adicionado em: v0.7.7 |
stream
<stream.Writable>callback
<Function> Invoca-se assim que a operação é concluída.- Retorna: <boolean>
false
sestream
deseja que o código chamador aguarde o evento'drain'
ser emitido antes de continuar a escrever dados adicionais; caso contrário,true
.
O método readline.clearScreenDown()
limpa o stream TTY dado a partir da posição atual do cursor para baixo.
readline.createInterface(options)
[Histórico]
Versão | Alterações |
---|---|
v15.14.0, v14.18.0 | A opção signal agora é suportada. |
v15.8.0, v14.18.0 | A opção history agora é suportada. |
v13.9.0 | A opção tabSize agora é suportada. |
v8.3.0, v6.11.4 | Limite máximo da opção crlfDelay removido. |
v6.6.0 | A opção crlfDelay agora é suportada. |
v6.3.0 | A opção prompt agora é suportada. |
v6.0.0 | A opção historySize agora pode ser 0 . |
v0.1.98 | Adicionado em: v0.1.98 |
options
<Object>input
<stream.Readable> O fluxo Readable para monitorar. Esta opção é obrigatória.output
<stream.Writable> O fluxo Writable para escrever dados readline.completer
<Function> Uma função opcional usada para autocompletar com Tab.terminal
<boolean>true
se os fluxosinput
eoutput
devem ser tratados como um TTY e ter códigos de escape ANSI/VT100 escritos nele. Padrão: verificandoisTTY
no fluxooutput
na instanciação.history
<string[]> Lista inicial de linhas de histórico. Esta opção só faz sentido seterminal
estiver definido comotrue
pelo usuário ou por uma verificação interna deoutput
, caso contrário, o mecanismo de cache de histórico não é inicializado. Padrão:[]
.historySize
<number> Número máximo de linhas de histórico retidas. Para desativar o histórico, defina este valor como0
. Esta opção só faz sentido seterminal
estiver definido comotrue
pelo usuário ou por uma verificação interna deoutput
, caso contrário, o mecanismo de cache de histórico não é inicializado. Padrão:30
.removeHistoryDuplicates
<boolean> Setrue
, quando uma nova linha de entrada adicionada à lista de histórico duplica uma linha mais antiga, isso remove a linha mais antiga da lista. Padrão:false
.prompt
<string> A string de prompt a ser usada. Padrão:'\> '
.crlfDelay
<number> Se o atraso entre\r
e\n
excedercrlfDelay
milissegundos,\r
e\n
serão tratados como entradas separadas de fim de linha.crlfDelay
será forçado a um número não inferior a100
. Pode ser definido comoInfinity
, caso em que\r
seguido de\n
sempre será considerado uma única nova linha (o que pode ser razoável para ler arquivos com delimitador de linha\r\n
). Padrão:100
.escapeCodeTimeout
<number> A duração quereadline
esperará por um caractere (ao ler uma sequência de tecla ambígua em milissegundos, uma que pode formar uma sequência de tecla completa usando a entrada lida até agora e pode receber entrada adicional para completar uma sequência de tecla mais longa). Padrão:500
.tabSize
<integer> O número de espaços a que um tab é igual (mínimo 1). Padrão:8
.signal
<AbortSignal> Permite fechar a interface usando um AbortSignal. Interromper o sinal chamará internamenteclose
na interface.
Retorna: <readline.Interface>
O método readline.createInterface()
cria uma nova instância 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,
})
Assim que a instância readline.Interface
for criada, o caso mais comum é escutar o evento 'line'
:
rl.on('line', line => {
console.log(`Recebido: ${line}`)
})
Se terminal
for true
para esta instância, o fluxo output
terá a melhor compatibilidade se definir uma propriedade output.columns
e emitir um evento 'resize'
no output
se ou quando as colunas mudarem (process.stdout
faz isso automaticamente quando é um TTY).
Ao criar um readline.Interface
usando stdin
como entrada, o programa não terminará até receber um caractere EOF. Para sair sem esperar a entrada do usuário, chame process.stdin.unref()
.
Uso da função completer
A função completer
recebe como argumento a linha atual inserida pelo usuário e retorna um Array
com 2 entradas:
- Um
Array
com entradas correspondentes para a conclusão. - A substring que foi usada para a correspondência.
Por exemplo: [[substr1, substr2, ...], originalsubstring]
.
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ')
const hits = completions.filter(c => c.startsWith(line))
// Mostrar todas as conclusões se nenhuma for encontrada
return [hits.length ? hits : completions, line]
}
A função completer
pode ser chamada assincronamente se aceitar dois argumentos:
function completer(linePartial, callback) {
callback(null, [['123'], linePartial])
}
readline.cursorTo(stream, x[, y][, callback])
[Histórico]
Versão | Alterações |
---|---|
v18.0.0 | Passar um callback inválido para o argumento callback agora lança ERR_INVALID_ARG_TYPE em vez de ERR_INVALID_CALLBACK . |
v12.7.0 | O callback e o valor de retorno do stream's write() são expostos. |
v0.7.7 | Adicionado em: v0.7.7 |
stream
<stream.Writable>x
<number>y
<number>callback
<Function> Invocou assim que a operação completa.- Retorna: <boolean>
false
sestream
deseja que o código de chamada aguarde o evento'drain'
ser emitido antes de continuar a escrever dados adicionais; caso contráriotrue
.
O método readline.cursorTo()
move o cursor para a posição especificada em um dado TTY stream
.
readline.moveCursor(stream, dx, dy[, callback])
[Histórico]
Versão | Alterações |
---|---|
v18.0.0 | Passar um callback inválido para o argumento callback agora lança ERR_INVALID_ARG_TYPE em vez de ERR_INVALID_CALLBACK . |
v12.7.0 | O callback e o valor de retorno do stream's write() são expostos. |
v0.7.7 | Adicionado em: v0.7.7 |
stream
<stream.Writable>dx
<number>dy
<number>callback
<Function> Invocou assim que a operação completa.- Retorna: <boolean>
false
sestream
deseja que o código de chamada aguarde o evento'drain'
ser emitido antes de continuar a escrever dados adicionais; caso contráriotrue
.
O método readline.moveCursor()
move o cursor relativo à sua posição atual em um dado TTY stream
.
readline.emitKeypressEvents(stream[, interface])
Adicionado em: v0.7.7
stream
<stream.Readable>interface
<readline.InterfaceConstructor>
O método readline.emitKeypressEvents()
faz com que o fluxo Readable fornecido comece a emitir eventos 'keypress'
correspondentes à entrada recebida.
Opcionalmente, interface
especifica uma instância readline.Interface
para a qual o autocompletar é desabilitado quando a entrada copiada e colada é detectada.
Se o stream
for um TTY, ele deve estar no modo raw.
Isso é chamado automaticamente por qualquer instância readline em sua entrada se a entrada for um terminal. Fechar a instância readline
não impede que a entrada emita eventos 'keypress'
.
readline.emitKeypressEvents(process.stdin)
if (process.stdin.isTTY) process.stdin.setRawMode(true)
Exemplo: Tiny CLI
O exemplo a seguir ilustra o uso da classe readline.Interface
para implementar uma pequena interface de linha de comando:
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)
})
Exemplo: Ler fluxo de arquivo linha por linha
Um caso de uso comum para readline
é consumir um arquivo de entrada uma linha por vez. A maneira mais fácil de fazer isso é aproveitar a API fs.ReadStream
e um loop 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,
})
// Nota: usamos a opção crlfDelay para reconhecer todas as instâncias de CR LF
// ('\r\n') em input.txt como uma única quebra de linha.
for await (const line of rl) {
// Cada linha em input.txt estará sucessivamente disponível aqui como `line`.
console.log(`Linha do arquivo: ${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,
})
// Nota: usamos a opção crlfDelay para reconhecer todas as instâncias de CR LF
// ('\r\n') em input.txt como uma única quebra de linha.
for await (const line of rl) {
// Cada linha em input.txt estará sucessivamente disponível aqui como `line`.
console.log(`Linha do arquivo: ${line}`)
}
}
processLineByLine()
Alternativamente, pode-se usar o evento '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(`Linha do arquivo: ${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(`Linha do arquivo: ${line}`)
})
Atualmente, o loop for await...of
pode ser um pouco mais lento. Se o fluxo async
/ await
e a velocidade forem essenciais, uma abordagem mista pode ser aplicada:
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 => {
// Processa a linha.
})
await once(rl, 'close')
console.log('Arquivo processado.')
} 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 => {
// Processa a linha.
})
await once(rl, 'close')
console.log('Arquivo processado.')
} catch (err) {
console.error(err)
}
})()
Atalhos de teclado TTY
Atalhos de teclado | Descrição | Notas |
---|---|---|
+ + | Apagar linha à esquerda | Não funciona no Linux, Mac e Windows |
+ + | Apagar linha à direita | Não funciona no Mac |
+ | Emitir SIGINT ou fechar a instância readline | |
+ | Apagar à esquerda | |
+ | Apagar à direita ou fechar a instância readline caso a linha atual esteja vazia/EOF | Não funciona no Windows |
+ | Apagar da posição atual até o início da linha | |
+ | Apagar da posição atual até o fim da linha | |
+ | Recortar (recuperar) o texto apagado anteriormente | Funciona apenas com texto apagado por + ou + |
+ | Ciclar entre textos apagados anteriormente | Disponível apenas quando a última tecla pressionada for + ou + |
+ | Ir para o início da linha | |
+ | Ir para o fim da linha | |
+ | Retroceder um caractere | |
+ | Avançar um caractere | |
+ | Limpar tela | |
+ | Próximo item do histórico | |
+ | Item anterior do histórico | |
+ | Desfazer alteração anterior | Qualquer tecla que emita o código de tecla 0x1F fará esta ação. Em muitos terminais, por exemplo, xterm , este está associado a + . |
+ | Refazer alteração anterior | Muitos terminais não têm um atalho de teclado padrão para refazer. Escolhemos o código de tecla 0x1E para realizar o refazer. Em xterm , está associado a + por padrão. |
+ | Move o processo em execução para segundo plano. Digite fg e pressione para retornar. | Não funciona no Windows |
+ ou + | Apagar para trás até um limite de palavra | + Não funciona no Linux, Mac e Windows |
+ | Apagar para frente até um limite de palavra | Não funciona no Mac |
+ ou + | Palavra esquerda | + Não funciona no Mac |
+ ou + | Palavra direita | + Não funciona no Mac |
+ ou + | Apagar palavra direita | + Não funciona no Windows |
+ | Apagar palavra esquerda | Não funciona no Mac |