Skip to content

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:

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

Para usar as APIs de callback e síncronas:

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

O seguinte exemplo simples ilustra o uso básico do módulo 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('O que você pensa sobre o Node.js? ')

console.log(`Obrigado pelo seu valioso feedback: ${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('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

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ância InterfaceConstructor liberou o controle sobre os fluxos input e output;
  • O fluxo input recebe seu evento 'end';
  • O fluxo input recebe + para sinalizar o fim da transmissão (EOT);
  • O fluxo input recebe + para sinalizar SIGINT e nenhum ouvinte de evento 'SIGINT' está registrado na instância InterfaceConstructor.

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.

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

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

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

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

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

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

js
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> Se true, impede que o posicionamento do cursor seja redefinido para 0.

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

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.

js
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ãoAlterações
v11.14.0, v10.17.0O suporte a Symbol.asyncIterator não é mais experimental.
v11.4.0, v10.16.0Adicionado em: v11.4.0, v10.16.0

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.

js
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ãoAlterações
v15.8.0, v14.18.0O valor será sempre uma string, nunca indefinido.
v0.1.98Adicionado 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:

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

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>
    • rows <number> a linha do prompt em que o cursor está atualmente
    • cols <number> a coluna da tela em que o cursor está atualmente

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

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 em output, precedendo o prompt.

  • options <Object>

    • signal <AbortSignal> Opcionalmente permite que question() seja cancelado usando um AbortSignal.
  • 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:

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

js
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

rl.clearLine(dir)

Adicionado em: v17.0.0

  • dir <inteiro>

    • -1: para a esquerda do cursor
    • 1: para a direita do cursor
    • 0: 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

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 fluxos input e output devem ser tratados como um TTY e ter códigos de escape ANSI/VT100 escritos nele. Padrão: verificando isTTY no fluxo output na instanciação.
    • history <string[]> Lista inicial de linhas de histórico. Esta opção só faz sentido se terminal estiver definido como true pelo usuário ou por uma verificação interna de output, 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 como 0. Esta opção só faz sentido se terminal estiver definido como true pelo usuário ou por uma verificação interna de output, caso contrário, o mecanismo de cache de histórico não é inicializado. Padrão: 30.
    • removeHistoryDuplicates <boolean> Se true, 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 exceder crlfDelay 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 a 100. Pode ser definido como Infinity, 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 que readlinePromises 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.

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,
})

Assim que a instância readlinePromises.Interface for criada, o caso mais comum é ouvir o evento 'line':

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

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

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

API de Callback

Adicionado em: v0.1.104

Classe: readline.Interface

[Histórico]

VersãoAlterações
v17.0.0A classe readline.Interface agora herda de Interface.
v0.1.104Adicionada em: v0.1.104

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 para output, precedida do prompt.

  • options <Object>

    • signal <AbortSignal> Opcionalmente permite que question() seja cancelado usando um AbortController.
  • 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:

js
rl.question('Qual sua comida favorita? ', answer => {
  console.log(`Ah, então sua comida favorita é ${answer}`)
})

Usando um AbortController para cancelar uma pergunta.

js
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ãoAlterações
v18.0.0Passar um callback inválido para o argumento callback agora lança ERR_INVALID_ARG_TYPE em vez de ERR_INVALID_CALLBACK.
v12.7.0O callback e o valor de retorno do write() do stream são expostos.
v0.7.7Adicionado em: v0.7.7
  • stream <stream.Writable>

  • dir <number>

    • -1: para a esquerda do cursor
    • 1: para a direita do cursor
    • 0: a linha inteira
  • callback <Function> Invoca-se assim que a operação é concluída.

  • Retorna: <boolean> false se stream 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ãoAlterações
v18.0.0Passar um callback inválido para o argumento callback agora lança ERR_INVALID_ARG_TYPE em vez de ERR_INVALID_CALLBACK.
v12.7.0O callback e o valor de retorno do write() do stream são expostos.
v0.7.7Adicionado em: v0.7.7
  • stream <stream.Writable>
  • callback <Function> Invoca-se assim que a operação é concluída.
  • Retorna: <boolean> false se stream 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ãoAlterações
v15.14.0, v14.18.0A opção signal agora é suportada.
v15.8.0, v14.18.0A opção history agora é suportada.
v13.9.0A opção tabSize agora é suportada.
v8.3.0, v6.11.4Limite máximo da opção crlfDelay removido.
v6.6.0A opção crlfDelay agora é suportada.
v6.3.0A opção prompt agora é suportada.
v6.0.0A opção historySize agora pode ser 0.
v0.1.98Adicionado 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 fluxos input e output devem ser tratados como um TTY e ter códigos de escape ANSI/VT100 escritos nele. Padrão: verificando isTTY no fluxo output na instanciação.
    • history <string[]> Lista inicial de linhas de histórico. Esta opção só faz sentido se terminal estiver definido como true pelo usuário ou por uma verificação interna de output, 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 como 0. Esta opção só faz sentido se terminal estiver definido como true pelo usuário ou por uma verificação interna de output, caso contrário, o mecanismo de cache de histórico não é inicializado. Padrão: 30.
    • removeHistoryDuplicates <boolean> Se true, 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 exceder crlfDelay 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 a 100. Pode ser definido como Infinity, 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 que readline 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á internamente close na interface.
  • Retorna: <readline.Interface>

O método readline.createInterface() cria uma nova instância 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,
})

Assim que a instância readline.Interface for criada, o caso mais comum é escutar o evento 'line':

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

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

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

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

[Histórico]

VersãoAlterações
v18.0.0Passar um callback inválido para o argumento callback agora lança ERR_INVALID_ARG_TYPE em vez de ERR_INVALID_CALLBACK.
v12.7.0O callback e o valor de retorno do stream's write() são expostos.
v0.7.7Adicionado em: v0.7.7
  • stream <stream.Writable>
  • x <number>
  • y <number>
  • callback <Function> Invocou assim que a operação completa.
  • Retorna: <boolean> false se stream deseja que o código de chamada aguarde o evento 'drain' ser emitido antes de continuar a escrever dados adicionais; caso contrário true.

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ãoAlterações
v18.0.0Passar um callback inválido para o argumento callback agora lança ERR_INVALID_ARG_TYPE em vez de ERR_INVALID_CALLBACK.
v12.7.0O callback e o valor de retorno do stream's write() são expostos.
v0.7.7Adicionado em: v0.7.7
  • stream <stream.Writable>
  • dx <number>
  • dy <number>
  • callback <Function> Invocou assim que a operação completa.
  • Retorna: <boolean> false se stream deseja que o código de chamada aguarde o evento 'drain' ser emitido antes de continuar a escrever dados adicionais; caso contrário true.

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

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'.

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

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

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:

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,
  })
  // 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()
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,
  })
  // 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':

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(`Linha do arquivo: ${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(`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:

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 => {
      // Processa a linha.
    })

    await once(rl, 'close')

    console.log('Arquivo processado.')
  } 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 => {
      // Processa a linha.
    })

    await once(rl, 'close')

    console.log('Arquivo processado.')
  } catch (err) {
    console.error(err)
  }
})()

Atalhos de teclado TTY

Atalhos de tecladoDescriçãoNotas
+ +Apagar linha à esquerdaNão funciona no Linux, Mac e Windows
+ +Apagar linha à direitaNã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/EOFNã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 anteriormenteFunciona apenas com texto apagado por + ou +
+Ciclar entre textos apagados anteriormenteDisponí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 anteriorQualquer 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 anteriorMuitos 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 palavraNã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 esquerdaNão funciona no Mac