Skip to content

REPL

[Estável: 2 - Estável]

Estável: 2 Estabilidade: 2 - Estável

Código-Fonte: lib/repl.js

O módulo node:repl fornece uma implementação Read-Eval-Print-Loop (REPL) que está disponível tanto como um programa autônomo quanto incluível em outros aplicativos. Pode ser acessado usando:

js
import repl from 'node:repl'
js
const repl = require('node:repl')

Design e recursos

O módulo node:repl exporta a classe repl.REPLServer. Durante a execução, instâncias de repl.REPLServer aceitarão linhas individuais de entrada do usuário, avaliá-las de acordo com uma função de avaliação definida pelo usuário e, em seguida, exibirão o resultado. A entrada e a saída podem ser de stdin e stdout, respectivamente, ou podem ser conectadas a qualquer stream do Node.js.

Instâncias de repl.REPLServer suportam conclusão automática de entradas, visualização de conclusão, edição de linha simplificada no estilo Emacs, entradas de várias linhas, busca reversa no estilo ZSH, busca de histórico baseada em substring no estilo ZSH, saída com estilo ANSI, salvamento e restauração do estado atual da sessão REPL, recuperação de erros e funções de avaliação personalizáveis. Terminais que não suportam estilos ANSI e edição de linha no estilo Emacs retornam automaticamente a um conjunto de recursos limitado.

Comandos e teclas especiais

Os seguintes comandos especiais são suportados por todas as instâncias REPL:

  • .break: Quando estiver no processo de entrada de uma expressão de várias linhas, digite o comando .break (ou pressione Ctrl+C) para interromper a entrada ou o processamento adicional dessa expressão.
  • .clear: Redefine o context do REPL para um objeto vazio e limpa qualquer expressão de várias linhas que esteja sendo inserida.
  • .exit: Fecha o fluxo de I/O, fazendo com que o REPL saia.
  • .help: Mostra esta lista de comandos especiais.
  • .save: Salva a sessão REPL atual em um arquivo: \> .save ./file/to/save.js
  • .load: Carrega um arquivo na sessão REPL atual. \> .load ./file/to/load.js
  • .editor: Entra no modo de editor (Ctrl+D para finalizar, Ctrl+C para cancelar).
bash
> .editor
// Entrando no modo de editor (Ctrl+D para finalizar, Ctrl+C para cancelar)
function welcome(name) {
  return `Hello ${name}!`;
}

welcome('Node.js User');

// Ctrl+D
'Hello Node.js User!'
>

As seguintes combinações de teclas no REPL têm esses efeitos especiais:

  • Ctrl+C: Quando pressionado uma vez, tem o mesmo efeito que o comando .break. Quando pressionado duas vezes em uma linha em branco, tem o mesmo efeito que o comando .exit.
  • Ctrl+D: Tem o mesmo efeito que o comando .exit.
  • Tab: Quando pressionado em uma linha em branco, exibe variáveis globais e locais (escopo). Quando pressionado durante a inserção de outra entrada, exibe as opções de preenchimento automático relevantes.

Para associações de teclas relacionadas à busca reversa, consulte reverse-i-search. Para todas as outras associações de teclas, consulte associações de teclas TTY.

Avaliação padrão

Por padrão, todas as instâncias de repl.REPLServer usam uma função de avaliação que avalia expressões JavaScript e fornece acesso aos módulos integrados do Node.js. Este comportamento padrão pode ser substituído passando uma função de avaliação alternativa quando a instância repl.REPLServer é criada.

Expressões JavaScript

O avaliador padrão suporta a avaliação direta de expressões JavaScript:

bash
> 1 + 1
2
> const m = 2
undefined
> m + 1
3

A menos que sejam definidas em escopos dentro de blocos ou funções, as variáveis declaradas implicitamente ou usando as palavras-chave const, let ou var são declaradas no escopo global.

Escopo global e local

O avaliador padrão fornece acesso a quaisquer variáveis que existam no escopo global. É possível expor uma variável ao REPL explicitamente, atribuindo-a ao objeto context associado a cada REPLServer:

js
import repl from 'node:repl'
const msg = 'message'

repl.start('> ').context.m = msg
js
const repl = require('node:repl')
const msg = 'message'

repl.start('> ').context.m = msg

Propriedades no objeto context aparecem como locais dentro do REPL:

bash
$ node repl_test.js
> m
'message'

As propriedades do contexto não são somente leitura por padrão. Para especificar globais somente leitura, as propriedades do contexto devem ser definidas usando Object.defineProperty():

js
import repl from 'node:repl'
const msg = 'message'

const r = repl.start('> ')
Object.defineProperty(r.context, 'm', {
  configurable: false,
  enumerable: true,
  value: msg,
})
js
const repl = require('node:repl')
const msg = 'message'

const r = repl.start('> ')
Object.defineProperty(r.context, 'm', {
  configurable: false,
  enumerable: true,
  value: msg,
})

Acessando módulos principais do Node.js

O avaliador padrão carregará automaticamente os módulos principais do Node.js no ambiente REPL quando usado. Por exemplo, a menos que declarado de outra forma como uma variável global ou de escopo, a entrada fs será avaliada sob demanda como global.fs = require('node:fs').

bash
> fs.createReadStream('./some/file');

Exceções não capturadas globais

[Histórico]

VersãoAlterações
v12.3.0O evento 'uncaughtException' agora é acionado se o REPL for usado como um programa independente.

O REPL usa o módulo domain para capturar todas as exceções não capturadas para aquela sessão REPL.

Este uso do módulo domain no REPL tem estes efeitos colaterais:

Atribuição da variável _ (underscore)

[Histórico]

VersãoAlterações
v9.8.0Suporte _error adicionado.

O avaliador padrão, por padrão, atribuirá o resultado da expressão mais recentemente avaliada à variável especial _ (underscore). Definir explicitamente _ para um valor desativará este comportamento.

bash
> [ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
> _.length
3
> _ += 1
Atribuição de expressão para _ agora desabilitada.
4
> 1 + 1
2
> _
4

Similarmente, _error referenciará o último erro encontrado, se houver algum. Definir explicitamente _error para um valor desativará este comportamento.

bash
> throw new Error('foo');
Error: foo
> _error.message
'foo'

Palavra-chave await

O suporte para a palavra-chave await é habilitado no nível superior.

bash
> await Promise.resolve(123)
123
> await Promise.reject(new Error('REPL await'))
Uncaught Error: REPL await
    at REPL2:1:54
> const timeout = util.promisify(setTimeout);
undefined
> const old = Date.now(); await timeout(1000); console.log(Date.now() - old);
1002
undefined

Uma limitação conhecida do uso da palavra-chave await no REPL é que ela invalidará o escopo léxico das palavras-chave const e let.

Por exemplo:

bash
> const m = await Promise.resolve(123)
undefined
> m
123
> const m = await Promise.resolve(234)
undefined
> m
234

--no-experimental-repl-await desabilitará o await de nível superior no REPL.

Adicionado em: v13.6.0, v12.17.0

O REPL suporta busca reversa interativa bidirecional similar ao ZSH. É acionado com Ctrl+R para buscar para trás e Ctrl+S para buscar para frente.

Entradas de histórico duplicadas serão ignoradas.

Entradas são aceitas assim que qualquer tecla é pressionada que não corresponda à busca reversa. O cancelamento é possível pressionando Ctrl+C ou Ctrl+R.

Mudar a direção imediatamente busca pela próxima entrada na direção esperada a partir da posição atual.

Funções de avaliação personalizadas

Quando um novo repl.REPLServer é criado, uma função de avaliação personalizada pode ser fornecida. Isso pode ser usado, por exemplo, para implementar aplicações REPL totalmente personalizadas.

O seguinte ilustra um exemplo de um REPL que eleva um número ao quadrado:

js
import repl from 'node:repl'

function byThePowerOfTwo(number) {
  return number * number
}

function myEval(cmd, context, filename, callback) {
  callback(null, byThePowerOfTwo(cmd))
}

repl.start({ prompt: 'Enter a number: ', eval: myEval })
js
const repl = require('node:repl')

function byThePowerOfTwo(number) {
  return number * number
}

function myEval(cmd, context, filename, callback) {
  callback(null, byThePowerOfTwo(cmd))
}

repl.start({ prompt: 'Enter a number: ', eval: myEval })

Erros recuperáveis

No prompt do REPL, pressionar Enter envia a linha atual de entrada para a função eval. Para suportar entrada de múltiplas linhas, a função eval pode retornar uma instância de repl.Recoverable para a função de callback fornecida:

js
function myEval(cmd, context, filename, callback) {
  let result
  try {
    result = vm.runInThisContext(cmd)
  } catch (e) {
    if (isRecoverableError(e)) {
      return callback(new repl.Recoverable(e))
    }
  }
  callback(null, result)
}

function isRecoverableError(error) {
  if (error.name === 'SyntaxError') {
    return /^(Unexpected end of input|Unexpected token)/.test(error.message)
  }
  return false
}

Personalizando a saída do REPL

Por padrão, as instâncias de repl.REPLServer formatam a saída usando o método util.inspect() antes de escrever a saída para o fluxo Writable fornecido (process.stdout por padrão). A opção de inspeção showProxy é definida como verdadeira por padrão e a opção colors é definida como verdadeira dependendo da opção useColors do REPL.

A opção booleana useColors pode ser especificada na construção para instruir o gravador padrão a usar códigos de estilo ANSI para colorir a saída do método util.inspect().

Se o REPL for executado como um programa autônomo, também é possível alterar as configurações padrão de inspeção do REPL de dentro do REPL usando a propriedade inspect.replDefaults, que reflete as defaultOptions de util.inspect().

bash
> util.inspect.replDefaults.compact = false;
false
> [1]
[
  1
]
>

Para personalizar totalmente a saída de uma instância repl.REPLServer, passe uma nova função para a opção writer na construção. O exemplo a seguir, por exemplo, simplesmente converte qualquer texto de entrada para maiúsculas:

js
import repl from 'node:repl'

const r = repl.start({ prompt: '> ', eval: myEval, writer: myWriter })

function myEval(cmd, context, filename, callback) {
  callback(null, cmd)
}

function myWriter(output) {
  return output.toUpperCase()
}
js
const repl = require('node:repl')

const r = repl.start({ prompt: '> ', eval: myEval, writer: myWriter })

function myEval(cmd, context, filename, callback) {
  callback(null, cmd)
}

function myWriter(output) {
  return output.toUpperCase()
}

Classe: REPLServer

Adicionado em: v0.1.91

Instâncias de repl.REPLServer são criadas usando o método repl.start() ou diretamente usando a palavra-chave new do JavaScript.

js
import repl from 'node:repl'

const options = { useColors: true }

const firstInstance = repl.start(options)
const secondInstance = new repl.REPLServer(options)
js
const repl = require('node:repl')

const options = { useColors: true }

const firstInstance = repl.start(options)
const secondInstance = new repl.REPLServer(options)

Evento: 'exit'

Adicionado em: v0.7.7

O evento 'exit' é emitido quando o REPL é encerrado, seja recebendo o comando .exit como entrada, o usuário pressionando + duas vezes para sinalizar SIGINT, ou pressionando + para sinalizar 'end' no fluxo de entrada. O callback do ouvinte é invocado sem nenhum argumento.

js
replServer.on('exit', () => {
  console.log('Recebeu o evento "exit" do repl!')
  process.exit()
})

Evento: 'reset'

Adicionado em: v0.11.0

O evento 'reset' é emitido quando o contexto do REPL é redefinido. Isso ocorre sempre que o comando .clear é recebido como entrada, a menos que o REPL esteja usando o avaliador padrão e a instância repl.REPLServer tenha sido criada com a opção useGlobal definida como true. O callback do ouvinte será chamado com uma referência ao objeto context como único argumento.

Isso pode ser usado principalmente para reinicializar o contexto REPL para algum estado predefinido:

js
import repl from 'node:repl'

function initializeContext(context) {
  context.m = 'test'
}

const r = repl.start({ prompt: '> ' })
initializeContext(r.context)

r.on('reset', initializeContext)
js
const repl = require('node:repl')

function initializeContext(context) {
  context.m = 'test'
}

const r = repl.start({ prompt: '> ' })
initializeContext(r.context)

r.on('reset', initializeContext)

Quando este código é executado, a variável global 'm' pode ser modificada, mas depois redefinida para seu valor inicial usando o comando .clear:

bash
$ ./node example.js
> m
'test'
> m = 1
1
> m
1
> .clear
Limpando contexto...
> m
'test'
>

replServer.defineCommand(keyword, cmd)

Adicionado em: v0.3.0

  • keyword <string> A palavra-chave do comando (sem um caractere . inicial).
  • cmd <Object> | <Function> A função a ser invocada quando o comando for processado.

O método replServer.defineCommand() é usado para adicionar novos comandos com prefixo . à instância REPL. Esses comandos são invocados digitando um . seguido pela keyword. O cmd é uma Function ou um Object com as seguintes propriedades:

  • help <string> Texto de ajuda a ser exibido quando .help for inserido (opcional).
  • action <Function> A função a ser executada, opcionalmente aceitando um único argumento de string.

O exemplo a seguir mostra dois novos comandos adicionados à instância REPL:

js
import repl from 'node:repl'

const replServer = repl.start({ prompt: '> ' })
replServer.defineCommand('sayhello', {
  help: 'Dizer olá',
  action(name) {
    this.clearBufferedCommand()
    console.log(`Olá, ${name}!`)
    this.displayPrompt()
  },
})
replServer.defineCommand('saybye', function saybye() {
  console.log('Adeus!')
  this.close()
})
js
const repl = require('node:repl')

const replServer = repl.start({ prompt: '> ' })
replServer.defineCommand('sayhello', {
  help: 'Dizer olá',
  action(name) {
    this.clearBufferedCommand()
    console.log(`Olá, ${name}!`)
    this.displayPrompt()
  },
})
replServer.defineCommand('saybye', function saybye() {
  console.log('Adeus!')
  this.close()
})

Os novos comandos podem então ser usados de dentro da instância REPL:

bash
> .sayhello Usuário Node.js
Olá, Usuário Node.js!
> .saybye
Adeus!

replServer.displayPrompt([preserveCursor])

Adicionado em: v0.1.91

O método replServer.displayPrompt() prepara a instância REPL para a entrada do usuário, imprimindo o prompt configurado em uma nova linha na output e retomando a input para aceitar novas entradas.

Quando a entrada de várias linhas está sendo inserida, uma reticências é impressa em vez do 'prompt'.

Quando preserveCursor é true, o posicionamento do cursor não será redefinido para 0.

O método replServer.displayPrompt destina-se principalmente a ser chamado de dentro da função de ação para comandos registrados usando o método replServer.defineCommand().

replServer.clearBufferedCommand()

Adicionado em: v9.0.0

O método replServer.clearBufferedCommand() limpa qualquer comando que tenha sido armazenado em buffer, mas ainda não executado. Este método destina-se principalmente a ser chamado de dentro da função de ação para comandos registrados usando o método replServer.defineCommand().

replServer.setupHistory(historyPath, callback)

Adicionado em: v11.10.0

Inicializa um arquivo de log de histórico para a instância REPL. Ao executar o binário Node.js e usar o REPL de linha de comando, um arquivo de histórico é inicializado por padrão. No entanto, este não é o caso ao criar um REPL programaticamente. Use este método para inicializar um arquivo de log de histórico ao trabalhar com instâncias REPL programaticamente.

repl.builtinModules

Adicionado em: v14.5.0

Uma lista dos nomes de todos os módulos Node.js, por exemplo, 'http'.

repl.start([options])

[Histórico]

VersãoAlterações
v13.4.0, v12.17.0A opção preview agora está disponível.
v12.0.0A opção terminal agora segue a descrição padrão em todos os casos e useColors verifica hasColors() se disponível.
v10.0.0O modo REPL_MAGIC_MODE replMode foi removido.
v6.3.0A opção breakEvalOnSigint agora é suportada.
v5.8.0O parâmetro options agora é opcional.
v0.1.91Adicionado em: v0.1.91
  • options <Object> | <string>

    • prompt <string> O prompt de entrada a ser exibido. Padrão: '\> ' (com um espaço final).

    • input <stream.Readable> O fluxo Readable do qual a entrada REPL será lida. Padrão: process.stdin.

    • output <stream.Writable> O fluxo Writable para o qual a saída REPL será escrita. Padrão: process.stdout.

    • terminal <boolean> Se true, especifica que a output deve ser tratada como um terminal TTY. Padrão: verificando o valor da propriedade isTTY no fluxo output na instanciação.

    • eval <Function> A função a ser usada ao avaliar cada linha de entrada fornecida. Padrão: um wrapper assíncrono para a função JavaScript eval(). Uma função eval pode gerar um erro com repl.Recoverable para indicar que a entrada estava incompleta e solicitar linhas adicionais.

    • useColors <boolean> Se true, especifica que a função writer padrão deve incluir estilo de cor ANSI à saída REPL. Se uma função writer personalizada for fornecida, isso não terá efeito. Padrão: verificando o suporte de cores no fluxo output se o valor terminal da instância REPL for true.

    • useGlobal <boolean> Se true, especifica que a função de avaliação padrão usará o global do JavaScript como contexto, em vez de criar um novo contexto separado para a instância REPL. O REPL do CLI do node define este valor como true. Padrão: false.

    • ignoreUndefined <boolean> Se true, especifica que o gravador padrão não exibirá o valor retornado de um comando se ele for avaliado como undefined. Padrão: false.

    • writer <Function> A função a ser invocada para formatar a saída de cada comando antes de gravar em output. Padrão: util.inspect().

    • completer <Function> Uma função opcional usada para autocompletar a guia personalizada. Veja readline.InterfaceCompleter para um exemplo.

    • replMode <symbol> Uma bandeira que especifica se o avaliador padrão executa todos os comandos JavaScript em modo estrito ou modo padrão (desleixado). Os valores aceitáveis são:

    • repl.REPL_MODE_SLOPPY para avaliar expressões em modo desleixado.

    • repl.REPL_MODE_STRICT para avaliar expressões em modo estrito. Isso é equivalente a prefaciar todas as declarações repl com 'use strict'.

    • breakEvalOnSigint <boolean> Pare de avaliar o código atual quando SIGINT for recebido, como quando + for pressionado. Isso não pode ser usado junto com uma função eval personalizada. Padrão: false.

    • preview <boolean> Define se o repl imprime visualizações de preenchimento automático e saída ou não. Padrão: true com a função eval padrão e false caso uma função eval personalizada seja usada. Se terminal for falso, não haverá visualizações e o valor de preview não terá efeito.

  • Retorna: <repl.REPLServer>

O método repl.start() cria e inicia uma instância repl.REPLServer.

Se options for uma string, ele especifica o prompt de entrada:

js
import repl from 'node:repl'

// um prompt no estilo Unix
repl.start('$ ')
js
const repl = require('node:repl')

// um prompt no estilo Unix
repl.start('$ ')

O REPL do Node.js

O próprio Node.js utiliza o módulo node:repl para fornecer sua própria interface interativa para execução de JavaScript. Isso pode ser usado executando o binário do Node.js sem passar nenhum argumento (ou passando o argumento -i):

bash
$ node
> const a = [1, 2, 3];
undefined
> a
[ 1, 2, 3 ]
> a.forEach((v) => {
...   console.log(v);
...   });
1
2
3

Opções de variáveis de ambiente

Vários comportamentos do REPL do Node.js podem ser personalizados usando as seguintes variáveis de ambiente:

  • NODE_REPL_HISTORY: Quando um caminho válido é fornecido, o histórico persistente do REPL será salvo no arquivo especificado em vez de .node_repl_history no diretório home do usuário. Definir este valor como '' (uma string vazia) desativará o histórico persistente do REPL. Os espaços em branco serão removidos do valor. Em plataformas Windows, variáveis de ambiente com valores vazios são inválidas, portanto, defina esta variável como um ou mais espaços para desativar o histórico persistente do REPL.
  • NODE_REPL_HISTORY_SIZE: Controla quantas linhas de histórico serão persistidas se o histórico estiver disponível. Deve ser um número positivo. Padrão: 1000.
  • NODE_REPL_MODE: Pode ser 'sloppy' ou 'strict'. Padrão: 'sloppy', que permitirá que código em modo não estrito seja executado.

Histórico persistente

Por padrão, o REPL do Node.js persistirá o histórico entre as sessões REPL node salvando as entradas em um arquivo .node_repl_history localizado no diretório home do usuário. Isso pode ser desabilitado definindo a variável de ambiente NODE_REPL_HISTORY=''.

Usando o REPL do Node.js com editores de linha avançados

Para editores de linha avançados, inicie o Node.js com a variável de ambiente NODE_NO_READLINE=1. Isso iniciará o REPL principal e o depurador nas configurações de terminal canônicas, o que permitirá o uso com rlwrap.

Por exemplo, o seguinte pode ser adicionado a um arquivo .bashrc:

bash
alias node="env NODE_NO_READLINE=1 rlwrap node"

Iniciando várias instâncias REPL em uma única instância em execução

É possível criar e executar várias instâncias REPL em uma única instância do Node.js em execução que compartilham um único objeto global, mas têm interfaces de E/S separadas.

O exemplo a seguir, por exemplo, fornece REPLs separados em stdin, um socket Unix e um socket TCP:

js
import net from 'node:net'
import repl from 'node:repl'
import process from 'node:process'

let connections = 0

repl.start({
  prompt: 'Node.js via stdin> ',
  input: process.stdin,
  output: process.stdout,
})

net
  .createServer(socket => {
    connections += 1
    repl
      .start({
        prompt: 'Node.js via Unix socket> ',
        input: socket,
        output: socket,
      })
      .on('exit', () => {
        socket.end()
      })
  })
  .listen('/tmp/node-repl-sock')

net
  .createServer(socket => {
    connections += 1
    repl
      .start({
        prompt: 'Node.js via TCP socket> ',
        input: socket,
        output: socket,
      })
      .on('exit', () => {
        socket.end()
      })
  })
  .listen(5001)
js
const net = require('node:net')
const repl = require('node:repl')
let connections = 0

repl.start({
  prompt: 'Node.js via stdin> ',
  input: process.stdin,
  output: process.stdout,
})

net
  .createServer(socket => {
    connections += 1
    repl
      .start({
        prompt: 'Node.js via Unix socket> ',
        input: socket,
        output: socket,
      })
      .on('exit', () => {
        socket.end()
      })
  })
  .listen('/tmp/node-repl-sock')

net
  .createServer(socket => {
    connections += 1
    repl
      .start({
        prompt: 'Node.js via TCP socket> ',
        input: socket,
        output: socket,
      })
      .on('exit', () => {
        socket.end()
      })
  })
  .listen(5001)

Executar este aplicativo na linha de comando iniciará um REPL no stdin. Outros clientes REPL podem se conectar através do socket Unix ou do socket TCP. telnet, por exemplo, é útil para conectar a sockets TCP, enquanto socat pode ser usado para conectar a sockets Unix e TCP.

Ao iniciar um REPL de um servidor baseado em socket Unix em vez de stdin, é possível conectar-se a um processo Node.js de longa execução sem reiniciá-lo.

Para um exemplo de execução de um REPL "completo" (terminal) sobre uma instância net.Server e net.Socket, veja: https://gist.github.com/TooTallNate/2209310.

Para um exemplo de execução de uma instância REPL sobre curl(1), veja: https://gist.github.com/TooTallNate/2053342.

Este exemplo destina-se puramente a fins educacionais para demonstrar como os REPLs do Node.js podem ser iniciados usando diferentes fluxos de E/S. Ele não deve ser usado em ambientes de produção ou em qualquer contexto em que a segurança seja uma preocupação sem medidas de proteção adicionais. Se você precisar implementar REPLs em um aplicativo do mundo real, considere abordagens alternativas que mitiguem esses riscos, como usar mecanismos de entrada seguros e evitar interfaces de rede abertas.