Skip to content

Readline

[Estable: 2 - Estable]

Estable: 2 Estabilidad: 2 - Estable

Código fuente: lib/readline.js

El módulo node:readline proporciona una interfaz para leer datos desde un flujo Readable (como process.stdin) una línea a la vez.

Para utilizar las API basadas en promesas:

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

Para utilizar las API de callback y síncronas:

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

El siguiente ejemplo sencillo ilustra el uso básico del 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('¿Qué opinas de Node.js? ')

console.log(`Gracias por tus valiosos comentarios: ${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('¿Qué opinas de Node.js? ', answer => {
  // TODO: Registrar la respuesta en una base de datos
  console.log(`Gracias por tus valiosos comentarios: ${answer}`)

  rl.close()
})

Una vez que se invoca este código, la aplicación de Node.js no terminará hasta que se cierre la readline.Interface porque la interfaz espera a que se reciban datos en el flujo input.

Clase: InterfaceConstructor

Añadido en: v0.1.104

Las instancias de la clase InterfaceConstructor se construyen utilizando el método readlinePromises.createInterface() o readline.createInterface(). Cada instancia está asociada con un único flujo input Readable y un único flujo output Writable. El flujo output se utiliza para imprimir las indicaciones para la entrada del usuario que llega en, y se lee desde, el flujo input.

Evento: 'close'

Añadido en: v0.1.98

El evento 'close' se emite cuando ocurre una de las siguientes acciones:

  • Se llama al método rl.close() y la instancia InterfaceConstructor ha renunciado al control sobre los flujos input y output;
  • El flujo input recibe su evento 'end';
  • El flujo input recibe + para señalar el final de la transmisión (EOT);
  • El flujo input recibe + para señalar SIGINT y no hay ningún listener de evento 'SIGINT' registrado en la instancia InterfaceConstructor.

La función listener se llama sin pasar ningún argumento.

La instancia InterfaceConstructor finaliza una vez que se emite el evento 'close'.

Evento: 'line'

Agregado en: v0.1.98

El evento 'line' se emite cada vez que el flujo input recibe una entrada de fin de línea (\n, \r o \r\n). Esto suele ocurrir cuando el usuario presiona o .

El evento 'line' también se emite si se han leído nuevos datos de un flujo y ese flujo termina sin un marcador de fin de línea final.

Se llama a la función de escucha con una cadena que contiene la única línea de entrada recibida.

js
rl.on('line', input => {
  console.log(`Recibido: ${input}`)
})

Evento: 'history'

Agregado en: v15.8.0, v14.18.0

El evento 'history' se emite cada vez que el array de historial ha cambiado.

Se llama a la función de escucha con un array que contiene el array de historial. Reflejará todos los cambios, líneas añadidas y líneas eliminadas debido a historySize y removeHistoryDuplicates.

El propósito principal es permitir que un oyente persista el historial. También es posible que el oyente cambie el objeto de historial. Esto podría ser útil para evitar que ciertas líneas se añadan al historial, como una contraseña.

js
rl.on('history', history => {
  console.log(`Recibido: ${history}`)
})

Event: 'pause'

Agregado en: v0.7.5

El evento 'pause' se emite cuando ocurre una de las siguientes situaciones:

  • El flujo input está en pausa.
  • El flujo input no está en pausa y recibe el evento 'SIGCONT'. (Ver eventos 'SIGTSTP' y 'SIGCONT'.)

La función de escucha se llama sin pasar ningún argumento.

js
rl.on('pause', () => {
  console.log('Readline en pausa.')
})

Event: 'resume'

Agregado en: v0.7.5

El evento 'resume' se emite cada vez que se reanuda el flujo input.

La función de escucha se llama sin pasar ningún argumento.

js
rl.on('resume', () => {
  console.log('Readline reanudado.')
})

Event: 'SIGCONT'

Agregado en: v0.7.5

El evento 'SIGCONT' se emite cuando un proceso de Node.js que previamente se movió al segundo plano usando + (es decir, SIGTSTP) se vuelve a poner en primer plano usando fg(1p).

Si el flujo input estaba en pausa antes de la solicitud SIGTSTP, este evento no se emitirá.

La función de escucha se invoca sin pasar ningún argumento.

js
rl.on('SIGCONT', () => {
  // `prompt` reanudará automáticamente el flujo
  rl.prompt()
})

El evento 'SIGCONT' no es compatible con Windows.

Evento: 'SIGINT'

Agregado en: v0.3.0

El evento 'SIGINT' se emite cada vez que el flujo input recibe una entrada , conocida típicamente como SIGINT. Si no hay listeners del evento 'SIGINT' registrados cuando el flujo input recibe un SIGINT, se emitirá el evento 'pause'.

La función listener se invoca sin pasar ningún argumento.

js
rl.on('SIGINT', () => {
  rl.question('¿Estás seguro de que quieres salir? ', answer => {
    if (answer.match(/^y(es)?$/i)) rl.pause()
  })
})

Evento: 'SIGTSTP'

Agregado en: v0.7.5

El evento 'SIGTSTP' se emite cuando el flujo input recibe una entrada +, típicamente conocida como SIGTSTP. Si no hay listeners del evento 'SIGTSTP' registrados cuando el flujo input recibe un SIGTSTP, el proceso de Node.js se enviará a segundo plano.

Cuando el programa se reanuda utilizando fg(1p), se emitirán los eventos 'pause' y 'SIGCONT'. Estos se pueden utilizar para reanudar el flujo input.

Los eventos 'pause' y 'SIGCONT' no se emitirán si el input se pausó antes de que el proceso se enviara a segundo plano.

La función listener se invoca sin pasar ningún argumento.

js
rl.on('SIGTSTP', () => {
  // Esto anulará SIGTSTP y evitará que el programa se vaya a segundo plano.
  console.log('SIGTSTP capturado.')
})

El evento 'SIGTSTP' no es compatible con Windows.

rl.close()

Agregado en: v0.1.98

El método rl.close() cierra la instancia de InterfaceConstructor y cede el control sobre los flujos input y output. Cuando se llama, se emitirá el evento 'close'.

Llamar a rl.close() no detiene inmediatamente la emisión de otros eventos (incluido 'line') por parte de la instancia de InterfaceConstructor.

rl.pause()

Agregado en: v0.3.4

El método rl.pause() pausa el flujo input, lo que permite que se reanude más tarde si es necesario.

Llamar a rl.pause() no pausa inmediatamente la emisión de otros eventos (incluido 'line') por parte de la instancia de InterfaceConstructor.

rl.prompt([preserveCursor])

Agregado en: v0.1.98

  • preserveCursor <boolean> Si es true, evita que la posición del cursor se restablezca a 0.

El método rl.prompt() escribe el prompt configurado de las instancias de InterfaceConstructor en una nueva línea en output para proporcionar al usuario una nueva ubicación en la que proporcionar entrada.

Cuando se llama, rl.prompt() reanudará el flujo input si se ha pausado.

Si el InterfaceConstructor se creó con output establecido en null o undefined, el prompt no se escribe.

rl.resume()

Agregado en: v0.3.4

El método rl.resume() reanuda el flujo input si se ha pausado.

rl.setPrompt(prompt)

Agregado en: v0.1.98

El método rl.setPrompt() establece el indicador que se escribirá en output cada vez que se llame a rl.prompt().

rl.getPrompt()

Agregado en: v15.3.0, v14.17.0

  • Devuelve: <string> la cadena de indicador actual

El método rl.getPrompt() devuelve el indicador actual utilizado por rl.prompt().

rl.write(data[, key])

Agregado en: v0.1.98

El método rl.write() escribirá data o una secuencia de teclas identificada por key en output. El argumento key solo se admite si output es una terminal de texto TTY. Consulte Combinaciones de teclas TTY para obtener una lista de combinaciones de teclas.

Si se especifica key, se ignora data.

Cuando se llama, rl.write() reanudará el flujo input si se ha pausado.

Si se creó InterfaceConstructor con output establecido en null o undefined, no se escriben data ni key.

js
rl.write('¡Elimina esto!')
// Simula Ctrl+U para eliminar la línea escrita previamente
rl.write(null, { ctrl: true, name: 'u' })

El método rl.write() escribirá los datos en la Interface readline input como si los proporcionara el usuario.

rl[Symbol.asyncIterator]()

[Historia]

VersiónCambios
v11.14.0, v10.17.0El soporte de Symbol.asyncIterator ya no es experimental.
v11.4.0, v10.16.0Añadido en: v11.4.0, v10.16.0

Crea un objeto AsyncIterator que itera a través de cada línea en el flujo de entrada como una cadena. Este método permite la iteración asíncrona de objetos InterfaceConstructor a través de bucles for await...of.

Los errores en el flujo de entrada no se reenvían.

Si el bucle termina con break, throw o return, se llamará a rl.close(). En otras palabras, iterar sobre un InterfaceConstructor siempre consumirá completamente el flujo de entrada.

El rendimiento no está a la par con la API de eventos 'line' tradicional. Utilice 'line' en su lugar para aplicaciones sensibles al rendimiento.

js
async function processLineByLine() {
  const rl = readline.createInterface({
    // ...
  })

  for await (const line of rl) {
    // Cada línea en la entrada de readline estará disponible sucesivamente aquí como
    // `line`.
  }
}

readline.createInterface() comenzará a consumir el flujo de entrada una vez invocado. Tener operaciones asíncronas entre la creación de la interfaz y la iteración asíncrona puede resultar en líneas perdidas.

rl.line

[Historial]

VersiónCambios
v15.8.0, v14.18.0El valor siempre será una cadena, nunca indefinido.
v0.1.98Añadido en: v0.1.98

Los datos de entrada actuales que está procesando node.

Esto se puede usar al recopilar la entrada de una transmisión TTY para recuperar el valor actual que se ha procesado hasta el momento, antes de que se emita el evento line. Una vez que se ha emitido el evento line, esta propiedad será una cadena vacía.

Tenga en cuenta que modificar el valor durante el tiempo de ejecución de la instancia puede tener consecuencias no deseadas si rl.cursor tampoco se controla.

Si no utiliza una transmisión TTY para la entrada, utilice el evento 'line'.

Un posible caso de uso sería el siguiente:

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

Agregado en: v0.1.98

La posición del cursor relativa a rl.line.

Esto rastreará dónde aterriza el cursor actual en la cadena de entrada, al leer la entrada de un flujo TTY. La posición del cursor determina la parte de la cadena de entrada que se modificará a medida que se procese la entrada, así como la columna donde se renderizará el cursor del terminal.

rl.getCursorPos()

Agregado en: v13.5.0, v12.16.0

  • Devuelve: <Object>
    • rows <number> la fila del indicador en la que se encuentra actualmente el cursor
    • cols <number> la columna de la pantalla en la que se encuentra actualmente el cursor

Devuelve la posición real del cursor en relación con el indicador de entrada + la cadena. Las cadenas de entrada largas (con ajuste de línea), así como los indicadores de varias líneas, se incluyen en los cálculos.

API de Promesas

Agregado en: v17.0.0

[Estable: 1 - Experimental]

Estable: 1 Estabilidad: 1 - Experimental

Clase: readlinePromises.Interface

Agregado en: v17.0.0

Las instancias de la clase readlinePromises.Interface se construyen utilizando el método readlinePromises.createInterface(). Cada instancia está asociada con un único flujo input Readable y un único flujo output Writable. El flujo output se utiliza para imprimir mensajes de solicitud de entrada del usuario que llegan al flujo input y se leen de él.

rl.question(query[, options])

Agregado en: v17.0.0

  • query <string> Una declaración o consulta para escribir en output, antepuesta al mensaje.

  • options <Object>

    • signal <AbortSignal> Opcionalmente permite cancelar la question() usando un AbortSignal.
  • Devuelve: <Promise> Una promesa que se cumple con la entrada del usuario en respuesta a la query.

El método rl.question() muestra la query escribiéndola en output, espera a que se proporcione la entrada del usuario en input, luego invoca la función callback pasando la entrada proporcionada como el primer argumento.

Cuando se llama, rl.question() reanudará el flujo input si se ha pausado.

Si readlinePromises.Interface se creó con output establecido en null o undefined, la query no se escribe.

Si se llama a la pregunta después de rl.close(), devuelve una promesa rechazada.

Ejemplo de uso:

js
const respuesta = await rl.question('¿Cuál es tu comida favorita? ')
console.log(`Oh, entonces tu comida favorita es ${respuesta}`)

Usando un AbortSignal para cancelar una pregunta.

js
const signal = AbortSignal.timeout(10_000)

signal.addEventListener(
  'abort',
  () => {
    console.log('La pregunta de la comida se agotó')
  },
  { once: true }
)

const respuesta = await rl.question('¿Cuál es tu comida favorita? ', { signal })
console.log(`Oh, entonces tu comida favorita es ${respuesta}`)

Clase: readlinePromises.Readline

Agregado en: v17.0.0

new readlinePromises.Readline(stream[, options])

Agregado en: v17.0.0

rl.clearLine(dir)

Agregado en: v17.0.0

  • dir <entero>
    • -1: a la izquierda del cursor
    • 1: a la derecha del cursor
    • 0: toda la línea
  • Devuelve: this

El método rl.clearLine() agrega a la lista interna de acciones pendientes una acción que borra la línea actual del stream asociado en una dirección específica identificada por dir. Llama a rl.commit() para ver el efecto de este método, a menos que se haya pasado autoCommit: true al constructor.

rl.clearScreenDown()

Agregado en: v17.0.0

  • Devuelve: this

El método rl.clearScreenDown() añade a la lista interna de acciones pendientes una acción que borra el stream asociado desde la posición actual del cursor hacia abajo. Llama a rl.commit() para ver el efecto de este método, a menos que se haya pasado autoCommit: true al constructor.

rl.commit()

Agregado en: v17.0.0

El método rl.commit() envía todas las acciones pendientes al stream asociado y borra la lista interna de acciones pendientes.

rl.cursorTo(x[, y])

Agregado en: v17.0.0

El método rl.cursorTo() añade a la lista interna de acciones pendientes una acción que mueve el cursor a la posición especificada en el stream asociado. Llama a rl.commit() para ver el efecto de este método, a menos que se haya pasado autoCommit: true al constructor.

rl.moveCursor(dx, dy)

Agregado en: v17.0.0

El método rl.moveCursor() agrega a la lista interna de acciones pendientes una acción que mueve el cursor relativamente a su posición actual en el stream asociado. Llama a rl.commit() para ver el efecto de este método, a menos que se haya pasado autoCommit: true al constructor.

rl.rollback()

Agregado en: v17.0.0

  • Devuelve: this

El método rl.rollback borra la lista interna de acciones pendientes sin enviarla al stream asociado.

readlinePromises.createInterface(options)

Agregado en: v17.0.0

  • options <Object>

    • input <stream.Readable> El stream Readable a escuchar. Esta opción es obligatoria.
    • output <stream.Writable> El stream Writable al que se escribirán los datos de readline.
    • completer <Function> Una función opcional utilizada para la autocompletación con Tab.
    • terminal <boolean> true si los streams input y output deben tratarse como un TTY, y se deben escribir códigos de escape ANSI/VT100 en él. Por defecto: verificar isTTY en el stream output al instanciar.
    • history <string[]> Lista inicial de líneas del historial. Esta opción tiene sentido solo si terminal está establecido en true por el usuario o por una verificación interna de output, de lo contrario, el mecanismo de almacenamiento en caché del historial no se inicializa en absoluto. Por defecto: [].
    • historySize <number> Número máximo de líneas del historial retenidas. Para deshabilitar el historial, establece este valor en 0. Esta opción tiene sentido solo si terminal está establecido en true por el usuario o por una verificación interna de output, de lo contrario, el mecanismo de almacenamiento en caché del historial no se inicializa en absoluto. Por defecto: 30.
    • removeHistoryDuplicates <boolean> Si es true, cuando una nueva línea de entrada agregada a la lista del historial duplica una anterior, esto elimina la línea anterior de la lista. Por defecto: false.
    • prompt <string> La cadena de prompt a utilizar. Por defecto: '\> '.
    • crlfDelay <number> Si el retraso entre \r y \n excede crlfDelay milisegundos, tanto \r como \n se tratarán como entrada de fin de línea separada. crlfDelay se forzará a un número no menor que 100. Se puede establecer en Infinity, en cuyo caso \r seguido de \n siempre se considerará una sola nueva línea (lo que puede ser razonable para leer archivos con delimitador de línea \r\n). Por defecto: 100.
    • escapeCodeTimeout <number> La duración que readlinePromises esperará por un carácter (cuando se lee una secuencia de teclas ambigua en milisegundos, una que puede formar una secuencia de teclas completa utilizando la entrada leída hasta ahora y puede tomar entrada adicional para completar una secuencia de teclas más larga). Por defecto: 500.
    • tabSize <integer> El número de espacios a los que equivale una tabulación (mínimo 1). Por defecto: 8.
  • Devuelve: <readlinePromises.Interface>

El método readlinePromises.createInterface() crea una nueva instancia de 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,
})

Una vez que se crea la instancia de readlinePromises.Interface, el caso más común es escuchar el evento 'line':

js
rl.on('line', line => {
  console.log(`Received: ${line}`)
})

Si terminal es true para esta instancia, entonces el stream output obtendrá la mejor compatibilidad si define una propiedad output.columns y emite un evento 'resize' en el output si o cuando las columnas cambian alguna vez (process.stdout lo hace automáticamente cuando es un TTY).

Uso de la función completer

La función completer toma la línea actual introducida por el usuario como argumento y devuelve un Array con 2 entradas:

  • Un Array con las entradas coincidentes para la compleción.
  • La subcadena que se utilizó para la coincidencia.

Por ejemplo: [[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 las compleciones si no se encuentra ninguna
  return [hits.length ? hits : completions, line]
}

La función completer también puede devolver una <Promise>, o ser asíncrona:

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

API de devolución de llamada

Añadido en: v0.1.104

Clase: readline.Interface

[Historial]

VersiónCambios
v17.0.0La clase readline.Interface ahora hereda de Interface.
v0.1.104Añadido en: v0.1.104

Las instancias de la clase readline.Interface se construyen utilizando el método readline.createInterface(). Cada instancia está asociada a un único flujo input Readable y a un único flujo output Writable. El flujo output se utiliza para imprimir mensajes de entrada de usuario que llegan a, y se leen desde, el flujo input.

rl.question(query[, options], callback)

Agregado en: v0.3.3

  • query <string> Una declaración o consulta para escribir en output, antepuesta al indicador.

  • options <Object>

    • signal <AbortSignal> Permite opcionalmente que question() se cancele usando un AbortController.
  • callback <Function> Una función de callback que se invoca con la entrada del usuario en respuesta a la query.

El método rl.question() muestra la query escribiéndola en la output, espera a que se proporcione la entrada del usuario en input y luego invoca la función callback pasando la entrada proporcionada como primer argumento.

Cuando se llama, rl.question() reanudará el flujo de input si se ha pausado.

Si readline.Interface se creó con output establecido en null o undefined, la query no se escribe.

La función callback pasada a rl.question() no sigue el patrón típico de aceptar un objeto Error o null como primer argumento. Se llama a la callback con la respuesta proporcionada como único argumento.

Se lanzará un error si se llama a rl.question() después de rl.close().

Ejemplo de uso:

js
rl.question('¿Cuál es tu comida favorita? ', respuesta => {
  console.log(`Oh, entonces tu comida favorita es ${respuesta}`)
})

Usando un AbortController para cancelar una pregunta.

js
const ac = new AbortController()
const signal = ac.signal

rl.question('¿Cuál es tu comida favorita? ', { signal }, respuesta => {
  console.log(`Oh, entonces tu comida favorita es ${respuesta}`)
})

signal.addEventListener(
  'abort',
  () => {
    console.log('La pregunta de la comida expiró')
  },
  { once: true }
)

setTimeout(() => ac.abort(), 10000)

readline.clearLine(stream, dir[, callback])

[Historial]

VersiónCambios
v18.0.0Pasar una devolución de llamada no válida al argumento callback ahora lanza ERR_INVALID_ARG_TYPE en lugar de ERR_INVALID_CALLBACK.
v12.7.0Se exponen la devolución de llamada write() del flujo y el valor de retorno.
v0.7.7Añadido en: v0.7.7
  • stream <stream.Writable>

  • dir <number>

    • -1: a la izquierda del cursor
    • 1: a la derecha del cursor
    • 0: toda la línea
  • callback <Function> Se invoca una vez que la operación se completa.

  • Devuelve: <boolean> false si stream desea que el código de llamada espere a que se emita el evento 'drain' antes de continuar escribiendo datos adicionales; de lo contrario, true.

El método readline.clearLine() borra la línea actual del flujo TTY dado en una dirección específica identificada por dir.

readline.clearScreenDown(stream[, callback])

[Historial]

VersiónCambios
v18.0.0Pasar una devolución de llamada no válida al argumento callback ahora lanza ERR_INVALID_ARG_TYPE en lugar de ERR_INVALID_CALLBACK.
v12.7.0Se exponen la devolución de llamada write() y el valor de retorno del flujo.
v0.7.7Añadido en: v0.7.7
  • stream <stream.Writable>
  • callback <Function> Se invoca una vez que se completa la operación.
  • Devuelve: <boolean> false si stream desea que el código que llama espere a que se emita el evento 'drain' antes de continuar escribiendo datos adicionales; de lo contrario, true.

El método readline.clearScreenDown() borra el flujo TTY dado desde la posición actual del cursor hacia abajo.

readline.createInterface(options)

[Historial]

VersiónCambios
v15.14.0, v14.18.0Ahora se admite la opción signal.
v15.8.0, v14.18.0Ahora se admite la opción history.
v13.9.0Ahora se admite la opción tabSize.
v8.3.0, v6.11.4Eliminar el límite máximo de la opción crlfDelay.
v6.6.0Ahora se admite la opción crlfDelay.
v6.3.0Ahora se admite la opción prompt.
v6.0.0La opción historySize ahora puede ser 0.
v0.1.98Añadido en: v0.1.98
  • options <Object>
    • input <stream.Readable> El flujo Readable para escuchar. Esta opción es obligatoria.
    • output <stream.Writable> El flujo Writable para escribir datos de readline.
    • completer <Function> Una función opcional utilizada para la autocompletado con Tab.
    • terminal <boolean> true si los flujos input y output deben tratarse como un TTY, y se deben escribir códigos de escape ANSI/VT100 en él. Predeterminado: comprobar isTTY en el flujo output al instanciarse.
    • history <string[]> Lista inicial de líneas de historial. Esta opción tiene sentido solo si terminal se establece en true por el usuario o mediante una verificación interna de output, de lo contrario, el mecanismo de almacenamiento en caché del historial no se inicializa en absoluto. Predeterminado: [].
    • historySize <number> Número máximo de líneas de historial retenidas. Para deshabilitar el historial, establezca este valor en 0. Esta opción tiene sentido solo si terminal se establece en true por el usuario o mediante una verificación interna de output, de lo contrario, el mecanismo de almacenamiento en caché del historial no se inicializa en absoluto. Predeterminado: 30.
    • removeHistoryDuplicates <boolean> Si es true, cuando una nueva línea de entrada agregada a la lista de historial duplica una anterior, esto elimina la línea anterior de la lista. Predeterminado: false.
    • prompt <string> La cadena de prompt para usar. Predeterminado: '\> '.
    • crlfDelay <number> Si el retraso entre \r y \n excede crlfDelay milisegundos, tanto \r como \n se tratarán como una entrada separada de fin de línea. crlfDelay se convertirá en un número no inferior a 100. Se puede establecer en Infinity, en cuyo caso \r seguido de \n siempre se considerará una sola línea nueva (lo que puede ser razonable para leer archivos con el delimitador de línea \r\n). Predeterminado: 100.
    • escapeCodeTimeout <number> La duración que readline esperará por un carácter (al leer una secuencia de teclas ambigua en milisegundos, una que puede formar una secuencia de teclas completa utilizando la entrada leída hasta ahora y puede tomar entrada adicional para completar una secuencia de teclas más larga). Predeterminado: 500.
    • tabSize <integer> El número de espacios a los que equivale una tabulación (mínimo 1). Predeterminado: 8.
    • signal <AbortSignal> Permite cerrar la interfaz utilizando un AbortSignal. La anulación de la señal llamará internamente a close en la interfaz.
  • Devuelve: <readline.Interface>

El método readline.createInterface() crea una nueva instancia de 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,
})

Una vez que se crea la instancia de readline.Interface, el caso más común es escuchar el evento 'line':

js
rl.on('line', line => {
  console.log(`Recibido: ${line}`)
})

Si terminal es true para esta instancia, entonces el flujo output obtendrá la mejor compatibilidad si define una propiedad output.columns y emite un evento 'resize' en el output si o cuando las columnas alguna vez cambian (process.stdout hace esto automáticamente cuando es un TTY).

Al crear una readline.Interface utilizando stdin como entrada, el programa no terminará hasta que reciba un carácter EOF. Para salir sin esperar la entrada del usuario, llame a process.stdin.unref().

Uso de la función completer

La función completer toma la línea actual ingresada por el usuario como argumento y devuelve un Array con 2 entradas:

  • Un Array con las entradas coincidentes para la finalización.
  • La subcadena que se usó para la coincidencia.

Por ejemplo: [[substr1, substr2, ...], originalsubstring].

js
function completer(line) {
  const completions = '.help .error .exit .quit .q'.split(' ')
  const hits = completions.filter(c => c.startsWith(line))
  // Muestra todas las finalizaciones si no se encuentra ninguna
  return [hits.length ? hits : completions, line]
}

La función completer se puede llamar de forma asíncrona si acepta dos argumentos:

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

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

[Historial]

VersiónCambios
v18.0.0Pasar un callback inválido al argumento callback ahora lanza ERR_INVALID_ARG_TYPE en lugar de ERR_INVALID_CALLBACK.
v12.7.0El callback write() del stream y el valor de retorno se exponen.
v0.7.7Agregado en: v0.7.7
  • stream <stream.Writable>
  • x <number>
  • y <number>
  • callback <Function> Se invoca una vez que se completa la operación.
  • Devuelve: <boolean> false si stream desea que el código de llamada espere a que se emita el evento 'drain' antes de continuar escribiendo datos adicionales; de lo contrario, true.

El método readline.cursorTo() mueve el cursor a la posición especificada en un stream TTY dado.

readline.moveCursor(stream, dx, dy[, callback])

[Historial]

VersiónCambios
v18.0.0Pasar una devolución de llamada no válida al argumento callback ahora lanza ERR_INVALID_ARG_TYPE en lugar de ERR_INVALID_CALLBACK.
v12.7.0Se exponen la devolución de llamada write() y el valor de retorno de la secuencia.
v0.7.7Añadido en: v0.7.7
  • stream <stream.Writable>
  • dx <number>
  • dy <number>
  • callback <Function> Se invoca una vez que se completa la operación.
  • Devuelve: <boolean> false si stream desea que el código de llamada espere a que se emita el evento 'drain' antes de continuar escribiendo datos adicionales; de lo contrario, true.

El método readline.moveCursor() mueve el cursor relativamente a su posición actual en una stream TTY dada.

readline.emitKeypressEvents(stream[, interface])

Agregado en: v0.7.7

El método readline.emitKeypressEvents() hace que el flujo Readable dado comience a emitir eventos 'keypress' correspondientes a la entrada recibida.

Opcionalmente, interface especifica una instancia de readline.Interface para la cual la autocompletación está deshabilitada cuando se detecta una entrada copiada y pegada.

Si el stream es un TTY, entonces debe estar en modo raw.

Esto es llamado automáticamente por cualquier instancia de readline en su input si el input es una terminal. Cerrar la instancia de readline no detiene la emisión de eventos 'keypress' por parte del input.

js
readline.emitKeypressEvents(process.stdin)
if (process.stdin.isTTY) process.stdin.setRawMode(true)

Ejemplo: CLI pequeño

El siguiente ejemplo ilustra el uso de la clase readline.Interface para implementar una pequeña interfaz de línea de comandos:

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(`¿Qué dices? Puede que haya oído '${line.trim()}'`)
      break
  }
  rl.prompt()
}).on('close', () => {
  console.log('¡Que tengas un gran día!')
  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(`¿Qué dices? Puede que haya oído '${line.trim()}'`)
      break
  }
  rl.prompt()
}).on('close', () => {
  console.log('¡Que tengas un gran día!')
  process.exit(0)
})

Ejemplo: Leer un flujo de archivos línea por línea

Un caso de uso común para readline es consumir un archivo de entrada una línea a la vez. La forma más sencilla de hacerlo es aprovechando la API fs.ReadStream así como un bucle 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 la opción crlfDelay para reconocer todas las instancias de CR LF
  // ('\r\n') en input.txt como un solo salto de línea.

  for await (const line of rl) {
    // Cada línea en input.txt estará disponible sucesivamente aquí como `line`.
    console.log(`Línea del archivo: ${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 la opción crlfDelay para reconocer todas las instancias de CR LF
  // ('\r\n') en input.txt como un solo salto de línea.

  for await (const line of rl) {
    // Cada línea en input.txt estará disponible sucesivamente aquí como `line`.
    console.log(`Línea del archivo: ${line}`)
  }
}

processLineByLine()

Alternativamente, se podría usar el 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(`Línea del archivo: ${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(`Línea del archivo: ${line}`)
})

Actualmente, el bucle for await...of puede ser un poco más lento. Si el flujo async / await y la velocidad son esenciales, se puede aplicar un enfoque mixto:

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 => {
      // Procesar la línea.
    })

    await once(rl, 'close')

    console.log('Archivo procesado.')
  } 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 => {
      // Procesar la línea.
    })

    await once(rl, 'close')

    console.log('Archivo procesado.')
  } catch (err) {
    console.error(err)
  }
})()

Atajos de teclado TTY

Atajos de tecladoDescripciónNotas
+ +Eliminar línea a la izquierdaNo funciona en Linux, Mac ni Windows
+ +Eliminar línea a la derechaNo funciona en Mac
+Emitir SIGINT o cerrar la instancia readline
+Eliminar a la izquierda
+Eliminar a la derecha o cerrar la instancia readline en caso de que la línea actual esté vacía / EOFNo funciona en Windows
+Eliminar desde la posición actual hasta el inicio de la línea
+Eliminar desde la posición actual hasta el final de la línea
+Pegar (Recuperar) el texto eliminado previamenteSolo funciona con texto eliminado mediante + o +
+Ciclar entre textos eliminados previamenteSolo disponible cuando la última pulsación de tecla es + o +
+Ir al inicio de la línea
+Ir al final de la línea
+Retroceder un carácter
+Avanzar un carácter
+Limpiar pantalla
+Siguiente elemento del historial
+Elemento anterior del historial
+Deshacer el cambio anteriorCualquier pulsación de tecla que emita el código de tecla 0x1F realizará esta acción. En muchas terminales, por ejemplo xterm , esto está vinculado a + .
+Rehacer el cambio anteriorMuchas terminales no tienen una pulsación de tecla predeterminada para rehacer. Elegimos el código de tecla 0x1E para realizar la rehacer. En xterm , está vinculado a + de forma predeterminada.
+Mueve el proceso en ejecución a segundo plano. Escribe fg y presiona para regresar.No funciona en Windows
+ o +Eliminar hacia atrás hasta un límite de palabra+ No funciona en Linux, Mac ni Windows
+Eliminar hacia adelante hasta un límite de palabraNo funciona en Mac
+ o +Palabra a la izquierda+ No funciona en Mac
+ o +Palabra a la derecha+ No funciona en Mac
+ o +Eliminar palabra a la derecha+ No funciona en windows
+Eliminar palabra a la izquierdaNo funciona en Mac