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:
import repl from 'node:repl'
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 ocontext
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).
> .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:
> 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
:
import repl from 'node:repl'
const msg = 'message'
repl.start('> ').context.m = msg
const repl = require('node:repl')
const msg = 'message'
repl.start('> ').context.m = msg
Propriedades no objeto context
aparecem como locais dentro do REPL:
$ 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()
:
import repl from 'node:repl'
const msg = 'message'
const r = repl.start('> ')
Object.defineProperty(r.context, 'm', {
configurable: false,
enumerable: true,
value: msg,
})
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')
.
> fs.createReadStream('./some/file');
Exceções não capturadas globais
[Histórico]
Versão | Alterações |
---|---|
v12.3.0 | O 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:
- As exceções não capturadas apenas emitem o evento
'uncaughtException'
no REPL independente. Adicionar um listener para este evento em um REPL dentro de outro programa Node.js resulta emERR_INVALID_REPL_INPUT
. - Tentar usar
process.setUncaughtExceptionCaptureCallback()
lança um erroERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE
.
Atribuição da variável _
(underscore)
[Histórico]
Versão | Alterações |
---|---|
v9.8.0 | Suporte _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.
> [ '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.
> throw new Error('foo');
Error: foo
> _error.message
'foo'
Palavra-chave await
O suporte para a palavra-chave await
é habilitado no nível superior.
> 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:
> 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.
Busca reversa interativa
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:
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 })
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:
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()
.
> 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:
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()
}
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
options
<Object> | <string> Vejarepl.start()
- Extende: <readline.Interface>
Instâncias de repl.REPLServer
são criadas usando o método repl.start()
ou diretamente usando a palavra-chave new
do JavaScript.
import repl from 'node:repl'
const options = { useColors: true }
const firstInstance = repl.start(options)
const secondInstance = new repl.REPLServer(options)
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.
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:
import repl from 'node:repl'
function initializeContext(context) {
context.m = 'test'
}
const r = repl.start({ prompt: '> ' })
initializeContext(r.context)
r.on('reset', initializeContext)
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
:
$ ./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:
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()
})
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:
> .sayhello Usuário Node.js
Olá, Usuário Node.js!
> .saybye
Adeus!
replServer.displayPrompt([preserveCursor])
Adicionado em: v0.1.91
preserveCursor
<boolean>
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
historyPath
<string> o caminho para o arquivo de históricocallback
<Function> chamado quando as gravações de histórico estiverem prontas ou em caso de erroerr
<Error>repl
<repl.REPLServer>
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ão | Alterações |
---|---|
v13.4.0, v12.17.0 | A opção preview agora está disponível. |
v12.0.0 | A opção terminal agora segue a descrição padrão em todos os casos e useColors verifica hasColors() se disponível. |
v10.0.0 | O modo REPL_MAGIC_MODE replMode foi removido. |
v6.3.0 | A opção breakEvalOnSigint agora é suportada. |
v5.8.0 | O parâmetro options agora é opcional. |
v0.1.91 | Adicionado em: v0.1.91 |
prompt
<string> O prompt de entrada a ser exibido. Padrão:'\> '
(com um espaço final).input
<stream.Readable> O fluxoReadable
do qual a entrada REPL será lida. Padrão:process.stdin
.output
<stream.Writable> O fluxoWritable
para o qual a saída REPL será escrita. Padrão:process.stdout
.terminal
<boolean> Setrue
, especifica que aoutput
deve ser tratada como um terminal TTY. Padrão: verificando o valor da propriedadeisTTY
no fluxooutput
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 JavaScripteval()
. Uma funçãoeval
pode gerar um erro comrepl.Recoverable
para indicar que a entrada estava incompleta e solicitar linhas adicionais.useColors
<boolean> Setrue
, especifica que a funçãowriter
padrão deve incluir estilo de cor ANSI à saída REPL. Se uma funçãowriter
personalizada for fornecida, isso não terá efeito. Padrão: verificando o suporte de cores no fluxooutput
se o valorterminal
da instância REPL fortrue
.useGlobal
<boolean> Setrue
, especifica que a função de avaliação padrão usará oglobal
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 comotrue
. Padrão:false
.ignoreUndefined
<boolean> Setrue
, especifica que o gravador padrão não exibirá o valor retornado de um comando se ele for avaliado comoundefined
. Padrão:false
.writer
<Function> A função a ser invocada para formatar a saída de cada comando antes de gravar emoutput
. Padrão:util.inspect()
.completer
<Function> Uma função opcional usada para autocompletar a guia personalizada. Vejareadline.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 quandoSIGINT
for recebido, como quando + for pressionado. Isso não pode ser usado junto com uma funçãoeval
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 efalse
caso uma função eval personalizada seja usada. Seterminal
for falso, não haverá visualizações e o valor depreview
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:
import repl from 'node:repl'
// um prompt no estilo Unix
repl.start('$ ')
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
):
$ 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
:
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:
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)
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.