Skip to content

REPL

[Estable: 2 - Estable]

Estable: 2 Estabilidad: 2 - Estable

Código fuente: lib/repl.js

El módulo node:repl proporciona una implementación de Read-Eval-Print-Loop (REPL) que está disponible tanto como un programa independiente como para ser incluido en otras aplicaciones. Se puede acceder a él usando:

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

Diseño y características

El módulo node:repl exporta la clase repl.REPLServer. Mientras se ejecutan, las instancias de repl.REPLServer aceptarán líneas individuales de entrada del usuario, las evaluarán de acuerdo con una función de evaluación definida por el usuario y luego emitirán el resultado. La entrada y la salida pueden ser de stdin y stdout, respectivamente, o pueden estar conectadas a cualquier stream de Node.js.

Las instancias de repl.REPLServer admiten la finalización automática de entradas, la vista previa de la finalización, la edición de líneas simplista al estilo Emacs, las entradas de varias líneas, la búsqueda inversa al estilo ZSH, la búsqueda de historial basada en subcadenas al estilo ZSH, la salida con estilo ANSI, el guardado y la restauración del estado actual de la sesión REPL, la recuperación de errores y funciones de evaluación personalizables. Los terminales que no admiten estilos ANSI y la edición de líneas al estilo Emacs recurren automáticamente a un conjunto de funciones limitado.

Comandos y teclas especiales

Todas las instancias REPL admiten los siguientes comandos especiales:

  • .break: Cuando se está en el proceso de ingresar una expresión de varias líneas, ingrese el comando .break (o presione +) para cancelar la entrada o el procesamiento adicional de esa expresión.
  • .clear: Restablece el context del REPL a un objeto vacío y borra cualquier expresión de varias líneas que se esté ingresando.
  • .exit: Cierra el flujo de E/S, lo que hace que el REPL se cierre.
  • .help: Muestra esta lista de comandos especiales.
  • .save: Guarda la sesión REPL actual en un archivo: \> .save ./archivo/para/guardar.js
  • .load: Carga un archivo en la sesión REPL actual. \> .load ./archivo/para/cargar.js
  • .editor: Ingresa al modo editor (+ para finalizar, + para cancelar).
bash
> .editor
// Ingresando al modo editor (^D para finalizar, ^C para cancelar)
function welcome(name) {
  return `¡Hola ${name}!`;
}

welcome('Usuario de Node.js');

// ^D
'¡Hola Usuario de Node.js!'
>

Las siguientes combinaciones de teclas en el REPL tienen estos efectos especiales:

  • +: Cuando se presiona una vez, tiene el mismo efecto que el comando .break. Cuando se presiona dos veces en una línea en blanco, tiene el mismo efecto que el comando .exit.
  • +: Tiene el mismo efecto que el comando .exit.
  • : Cuando se presiona en una línea en blanco, muestra las variables globales y locales (alcance). Cuando se presiona mientras se ingresa otra entrada, muestra las opciones de autocompletado relevantes.

Para las combinaciones de teclas relacionadas con la búsqueda inversa, consulte reverse-i-search. Para todas las demás combinaciones de teclas, consulte Combinaciones de teclas TTY.

Evaluación predeterminada

De forma predeterminada, todas las instancias de repl.REPLServer utilizan una función de evaluación que evalúa expresiones de JavaScript y proporciona acceso a los módulos integrados de Node.js. Este comportamiento predeterminado se puede anular pasando una función de evaluación alternativa cuando se crea la instancia de repl.REPLServer.

Expresiones de JavaScript

El evaluador predeterminado admite la evaluación directa de expresiones de JavaScript:

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

A menos que se definan dentro de bloques o funciones, las variables declaradas implícitamente o utilizando las palabras clave const, let o var se declaran en el ámbito global.

Ámbito global y local

El evaluador predeterminado proporciona acceso a cualquier variable que exista en el ámbito global. Es posible exponer una variable al REPL explícitamente asignándola al objeto context asociado 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

Las propiedades en el objeto context aparecen como locales dentro del REPL:

bash
$ node repl_test.js
> m
'message'

Las propiedades de contexto no son de solo lectura de forma predeterminada. Para especificar globales de solo lectura, las propiedades de contexto deben definirse utilizando 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,
})

Acceso a módulos centrales de Node.js

El evaluador predeterminado cargará automáticamente los módulos centrales de Node.js en el entorno REPL cuando se utilicen. Por ejemplo, a menos que se declare como una variable global o con ámbito, la entrada fs se evaluará bajo demanda como global.fs = require('node:fs').

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

Excepciones globales no capturadas

[Historial]

VersiónCambios
v12.3.0El evento 'uncaughtException' se activa a partir de ahora si el REPL se usa como un programa independiente.

El REPL usa el módulo domain para capturar todas las excepciones no capturadas para esa sesión de REPL.

Este uso del módulo domain en el REPL tiene estos efectos secundarios:

Asignación de la variable _ (guion bajo)

[Historial]

VersiónCambios
v9.8.0Se agregó soporte para _error.

El evaluador predeterminado, por defecto, asignará el resultado de la expresión evaluada más recientemente a la variable especial _ (guion bajo). Establecer explícitamente _ a un valor deshabilitará este comportamiento.

bash
> [ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
> _.length
3
> _ += 1
Asignación de expresión a _ ahora deshabilitada.
4
> 1 + 1
2
> _
4

De manera similar, _error se referirá al último error visto, si hubo alguno. Establecer explícitamente _error a un valor deshabilitará este comportamiento.

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

Palabra clave await

El soporte para la palabra clave await está habilitado en el nivel 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

Una limitación conocida del uso de la palabra clave await en el REPL es que invalidará el alcance léxico de las palabras clave const y let.

Por ejemplo:

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

--no-experimental-repl-await deberá deshabilitar el await de nivel superior en REPL.

Añadido en: v13.6.0, v12.17.0

El REPL admite la búsqueda inversa incremental bidireccional similar a ZSH. Se activa con + para buscar hacia atrás y + para buscar hacia adelante.

Se omitirán las entradas duplicadas del historial.

Las entradas se aceptan tan pronto como se presiona cualquier tecla que no se corresponda con la búsqueda inversa. La cancelación es posible presionando o +.

Cambiar la dirección busca inmediatamente la siguiente entrada en la dirección esperada desde la posición actual.

Funciones de evaluación personalizadas

Cuando se crea un nuevo repl.REPLServer, se puede proporcionar una función de evaluación personalizada. Esto se puede usar, por ejemplo, para implementar aplicaciones REPL totalmente personalizadas.

Lo siguiente ilustra un ejemplo de un REPL que eleva al cuadrado un número dado:

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: 'Introduce un número: ', 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: 'Introduce un número: ', eval: myEval })

Errores recuperables

En el prompt de REPL, al presionar se envía la línea de entrada actual a la función eval. Para admitir la entrada de varias líneas, la función eval puede devolver una instancia de repl.Recoverable a la función de devolución de llamada proporcionada:

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
}

Personalización de la salida de REPL

De forma predeterminada, las instancias de repl.REPLServer formatean la salida utilizando el método util.inspect() antes de escribir la salida en el flujo Writable proporcionado (process.stdout de forma predeterminada). La opción de inspección showProxy se establece en true de forma predeterminada y la opción colors se establece en true dependiendo de la opción useColors de REPL.

La opción booleana useColors se puede especificar durante la construcción para indicar al escritor predeterminado que utilice códigos de estilo ANSI para colorear la salida del método util.inspect().

Si el REPL se ejecuta como un programa independiente, también es posible cambiar los valores predeterminados de inspección de REPL desde dentro del REPL utilizando la propiedad inspect.replDefaults que refleja el defaultOptions de util.inspect().

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

Para personalizar completamente la salida de una instancia repl.REPLServer pasa una nueva función para la opción writer en la construcción. El siguiente ejemplo, por ejemplo, simplemente convierte cualquier texto de entrada a mayú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()
}

Clase: REPLServer

Agregado en: v0.1.91

Las instancias de repl.REPLServer se crean usando el método repl.start() o directamente usando la palabra clave new de 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'

Agregado en: v0.7.7

El evento 'exit' se emite cuando se sale del REPL, ya sea recibiendo el comando .exit como entrada, presionando + dos veces para señalar SIGINT, o presionando + para señalar 'end' en el flujo de entrada. La función de devolución de llamada del oyente se invoca sin ningún argumento.

js
replServer.on('exit', () => {
  console.log('¡Recibido evento "exit" de repl!')
  process.exit()
})

Evento: 'reset'

Agregado en: v0.11.0

El evento 'reset' se emite cuando se restablece el contexto del REPL. Esto ocurre cada vez que se recibe el comando .clear como entrada a menos que el REPL esté utilizando el evaluador predeterminado y la instancia repl.REPLServer se haya creado con la opción useGlobal establecida en true. La función de devolución de llamada del receptor se llamará con una referencia al objeto context como único argumento.

Esto se puede usar principalmente para reinicializar el contexto de REPL a algún 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)

Cuando se ejecuta este código, la variable global 'm' se puede modificar pero luego se restablece a su valor inicial utilizando el comando .clear:

bash
$ ./node example.js
> m
'test'
> m = 1
1
> m
1
> .clear
Clearing context...
> m
'test'
>

replServer.defineCommand(keyword, cmd)

Agregado en: v0.3.0

  • keyword <string> La palabra clave del comando (sin un carácter . inicial).
  • cmd <Object> | <Function> La función a invocar cuando se procesa el comando.

El método replServer.defineCommand() se utiliza para agregar nuevos comandos con prefijo . a la instancia REPL. Dichos comandos se invocan escribiendo un . seguido de la keyword. El cmd es una Function o un Object con las siguientes propiedades:

  • help <string> Texto de ayuda que se mostrará cuando se ingrese .help (Opcional).
  • action <Function> La función a ejecutar, que opcionalmente acepta un solo argumento de cadena.

El siguiente ejemplo muestra dos nuevos comandos agregados a la instancia REPL:

js
import repl from 'node:repl'

const replServer = repl.start({ prompt: '> ' })
replServer.defineCommand('sayhello', {
  help: 'Say hello',
  action(name) {
    this.clearBufferedCommand()
    console.log(`Hello, ${name}!`)
    this.displayPrompt()
  },
})
replServer.defineCommand('saybye', function saybye() {
  console.log('Goodbye!')
  this.close()
})
js
const repl = require('node:repl')

const replServer = repl.start({ prompt: '> ' })
replServer.defineCommand('sayhello', {
  help: 'Say hello',
  action(name) {
    this.clearBufferedCommand()
    console.log(`Hello, ${name}!`)
    this.displayPrompt()
  },
})
replServer.defineCommand('saybye', function saybye() {
  console.log('Goodbye!')
  this.close()
})

Los nuevos comandos se pueden usar desde dentro de la instancia REPL:

bash
> .sayhello Node.js User
Hello, Node.js User!
> .saybye
Goodbye!

replServer.displayPrompt([preserveCursor])

Agregado en: v0.1.91

El método replServer.displayPrompt() prepara la instancia REPL para la entrada del usuario, imprimiendo el prompt configurado en una nueva línea en la salida y reanudando la entrada para aceptar una nueva entrada.

Cuando se introduce una entrada de varias líneas, se imprime una elipsis en lugar del 'prompt'.

Cuando preserveCursor es true, la posición del cursor no se restablecerá a 0.

El método replServer.displayPrompt está destinado principalmente a ser llamado desde la función de acción para los comandos registrados utilizando el método replServer.defineCommand().

replServer.clearBufferedCommand()

Agregado en: v9.0.0

El método replServer.clearBufferedCommand() borra cualquier comando que haya sido almacenado en búfer pero que aún no se haya ejecutado. Este método está destinado principalmente a ser llamado desde la función de acción para los comandos registrados utilizando el método replServer.defineCommand().

replServer.setupHistory(historyPath, callback)

Agregado en: v11.10.0

Inicializa un archivo de registro del historial para la instancia REPL. Al ejecutar el binario de Node.js y usar el REPL de la línea de comandos, se inicializa un archivo de historial de forma predeterminada. Sin embargo, este no es el caso al crear un REPL mediante programación. Use este método para inicializar un archivo de registro del historial cuando trabaje con instancias REPL mediante programación.

repl.builtinModules

Agregado en: v14.5.0

Una lista de los nombres de todos los módulos de Node.js, p. ej., 'http'.

repl.start([options])

[Historial]

VersiónCambios
v13.4.0, v12.17.0La opción preview ahora está disponible.
v12.0.0La opción terminal ahora sigue la descripción predeterminada en todos los casos y useColors verifica hasColors() si está disponible.
v10.0.0Se eliminó el replMode REPL_MAGIC_MODE.
v6.3.0Ahora se admite la opción breakEvalOnSigint.
v5.8.0El parámetro options ahora es opcional.
v0.1.91Agregado en: v0.1.91
  • options <Objeto> | <cadena>

    • prompt <cadena> El prompt de entrada a mostrar. Predeterminado: '\> ' (con un espacio al final).

    • input <stream.Readable> El flujo Readable desde el cual se leerá la entrada REPL. Predeterminado: process.stdin.

    • output <stream.Writable> El flujo Writable al que se escribirá la salida REPL. Predeterminado: process.stdout.

    • terminal <boolean> Si es true, especifica que la output debe tratarse como una terminal TTY. Predeterminado: verificar el valor de la propiedad isTTY en el flujo output al instanciar.

    • eval <Función> La función que se usará al evaluar cada línea de entrada dada. Predeterminado: un envoltorio asíncrono para la función JavaScript eval(). Una función eval puede generar un error con repl.Recoverable para indicar que la entrada estaba incompleta y solicitar líneas adicionales.

    • useColors <boolean> Si es true, especifica que la función writer predeterminada debe incluir estilos de color ANSI en la salida REPL. Si se proporciona una función writer personalizada, esto no tiene efecto. Predeterminado: verificar la compatibilidad de color en el flujo output si el valor terminal de la instancia REPL es true.

    • useGlobal <boolean> Si es true, especifica que la función de evaluación predeterminada usará el JavaScript global como contexto en lugar de crear un nuevo contexto separado para la instancia REPL. El REPL de la CLI de Node establece este valor en true. Predeterminado: false.

    • ignoreUndefined <boolean> Si es true, especifica que el escritor predeterminado no mostrará el valor de retorno de un comando si se evalúa como undefined. Predeterminado: false.

    • writer <Función> La función que se invocará para formatear la salida de cada comando antes de escribir en output. Predeterminado: util.inspect().

    • completer <Función> Una función opcional utilizada para la auto-finalización personalizada de la tecla Tab. Consulte readline.InterfaceCompleter para ver un ejemplo.

    • replMode <symbol> Una bandera que especifica si el evaluador predeterminado ejecuta todos los comandos de JavaScript en modo estricto o en modo predeterminado (flexible). Los valores aceptables son:

      • repl.REPL_MODE_SLOPPY para evaluar expresiones en modo flexible.
      • repl.REPL_MODE_STRICT para evaluar expresiones en modo estricto. Esto es equivalente a anteponer cada declaración de repl con 'use strict'.
    • breakEvalOnSigint <boolean> Detener la evaluación del fragmento de código actual cuando se recibe SIGINT, como cuando se presiona +. Esto no se puede usar junto con una función eval personalizada. Predeterminado: false.

    • preview <boolean> Define si el repl imprime auto-completado y previsualizaciones de salida o no. Predeterminado: true con la función eval predeterminada y false en caso de que se utilice una función eval personalizada. Si terminal es falso, entonces no hay vistas previas y el valor de preview no tiene efecto.

  • Devuelve: <repl.REPLServer>

El método repl.start() crea e inicia una instancia de repl.REPLServer.

Si options es una cadena, entonces especifica el prompt de entrada:

js
import repl from 'node:repl'

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

// un prompt estilo Unix
repl.start('$ ')

El REPL de Node.js

Node.js utiliza el módulo node:repl para proporcionar su propia interfaz interactiva para ejecutar JavaScript. Esto se puede utilizar ejecutando el binario de Node.js sin pasar ningún argumento (o pasando el argumento -i):

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

Opciones de variables de entorno

Varios comportamientos del REPL de Node.js se pueden personalizar utilizando las siguientes variables de entorno:

  • NODE_REPL_HISTORY: Cuando se proporciona una ruta válida, el historial persistente del REPL se guardará en el archivo especificado en lugar de .node_repl_history en el directorio de inicio del usuario. Establecer este valor a '' (una cadena vacía) deshabilitará el historial persistente del REPL. Los espacios en blanco se eliminarán del valor. En las plataformas Windows, las variables de entorno con valores vacíos no son válidas, así que establezca esta variable en uno o más espacios para deshabilitar el historial persistente del REPL.
  • NODE_REPL_HISTORY_SIZE: Controla cuántas líneas de historial se conservarán si el historial está disponible. Debe ser un número positivo. Predeterminado: 1000.
  • NODE_REPL_MODE: Puede ser 'sloppy' o 'strict'. Predeterminado: 'sloppy', que permitirá que se ejecute código en modo no estricto.

Historial persistente

De forma predeterminada, el REPL de Node.js conservará el historial entre sesiones REPL de node guardando las entradas en un archivo .node_repl_history ubicado en el directorio de inicio del usuario. Esto se puede deshabilitar configurando la variable de entorno NODE_REPL_HISTORY=''.

Uso del REPL de Node.js con editores de línea avanzados

Para editores de línea avanzados, inicie Node.js con la variable de entorno NODE_NO_READLINE=1. Esto iniciará el REPL principal y el depurador en la configuración de terminal canónica, lo que permitirá el uso con rlwrap.

Por ejemplo, lo siguiente se puede agregar a un archivo .bashrc:

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

Iniciar múltiples instancias REPL contra una única instancia en ejecución

Es posible crear y ejecutar múltiples instancias REPL contra una única instancia en ejecución de Node.js que compartan un único objeto global pero tengan interfaces de E/S separadas.

El siguiente ejemplo, por ejemplo, proporciona REPL separados en stdin, un socket Unix y un 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 a través de stdin> ',
  input: process.stdin,
  output: process.stdout,
})

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

net
  .createServer(socket => {
    connections += 1
    repl
      .start({
        prompt: 'Node.js a través de socket TCP> ',
        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 a través de stdin> ',
  input: process.stdin,
  output: process.stdout,
})

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

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

Al ejecutar esta aplicación desde la línea de comandos, se iniciará un REPL en stdin. Otros clientes REPL pueden conectarse a través del socket Unix o el socket TCP. telnet, por ejemplo, es útil para conectarse a sockets TCP, mientras que socat se puede utilizar para conectarse tanto a sockets Unix como TCP.

Al iniciar un REPL desde un servidor basado en socket Unix en lugar de stdin, es posible conectarse a un proceso Node.js de larga duración sin reiniciarlo.

Para un ejemplo de cómo ejecutar un REPL "completo" (terminal) a través de una instancia de net.Server y net.Socket, consulte: https://gist.github.com/TooTallNate/2209310.

Para un ejemplo de cómo ejecutar una instancia REPL a través de curl(1), consulte: https://gist.github.com/TooTallNate/2053342.

Este ejemplo tiene fines puramente educativos para demostrar cómo se pueden iniciar los REPL de Node.js utilizando diferentes flujos de E/S. No se debe utilizar en entornos de producción ni en ningún contexto donde la seguridad sea una preocupación sin medidas de protección adicionales. Si necesita implementar REPL en una aplicación del mundo real, considere enfoques alternativos que mitiguen estos riesgos, como el uso de mecanismos de entrada seguros y evitar interfaces de red abiertas.