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:
import * as readline from 'node:readline/promises'
const readline = require('node:readline/promises')
Para utilizar las API de callback y síncronas:
import * as readline from 'node:readline'
const readline = require('node:readline')
El siguiente ejemplo sencillo ilustra el uso básico del módulo node:readline
.
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()
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
- Extiende: <EventEmitter>
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 instanciaInterfaceConstructor
ha renunciado al control sobre los flujosinput
youtput
; - 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ñalarSIGINT
y no hay ningún listener de evento'SIGINT'
registrado en la instanciaInterfaceConstructor
.
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.
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.
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.
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.
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.
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.
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.
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 estrue
, evita que la posición del cursor se restablezca a0
.
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
prompt
<string>
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
.
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ón | Cambios |
---|---|
v11.14.0, v10.17.0 | El soporte de Symbol.asyncIterator ya no es experimental. |
v11.4.0, v10.16.0 | Añadido en: v11.4.0, v10.16.0 |
- Devuelve: <AsyncIterator>
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.
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ón | Cambios |
---|---|
v15.8.0, v14.18.0 | El valor siempre será una cadena, nunca indefinido. |
v0.1.98 | Añ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:
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>
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
- Extiende: <readline.InterfaceConstructor>
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 enoutput
, antepuesta al mensaje.options
<Object>signal
<AbortSignal> Opcionalmente permite cancelar laquestion()
usando unAbortSignal
.
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:
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.
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
stream
<stream.Writable> Un flujo TTY.options
<Objeto>autoCommit
<boolean> Si estrue
, no es necesario llamar arl.commit()
.
rl.clearLine(dir)
Agregado en: v17.0.0
dir
<entero>-1
: a la izquierda del cursor1
: a la derecha del cursor0
: 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
- Devuelve: <Promise>
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 streamsinput
youtput
deben tratarse como un TTY, y se deben escribir códigos de escape ANSI/VT100 en él. Por defecto: verificarisTTY
en el streamoutput
al instanciar.history
<string[]> Lista inicial de líneas del historial. Esta opción tiene sentido solo siterminal
está establecido entrue
por el usuario o por una verificación interna deoutput
, 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 en0
. Esta opción tiene sentido solo siterminal
está establecido entrue
por el usuario o por una verificación interna deoutput
, de lo contrario, el mecanismo de almacenamiento en caché del historial no se inicializa en absoluto. Por defecto:30
.removeHistoryDuplicates
<boolean> Si estrue
, 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
excedecrlfDelay
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 que100
. Se puede establecer enInfinity
, 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 quereadlinePromises
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
.
import { createInterface } from 'node:readline/promises'
import { stdin, stdout } from 'node:process'
const rl = createInterface({
input: stdin,
output: stdout,
})
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'
:
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]
.
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:
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ón | Cambios |
---|---|
v17.0.0 | La clase readline.Interface ahora hereda de Interface . |
v0.1.104 | Añadido en: v0.1.104 |
- Extiende: <readline.InterfaceConstructor>
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 enoutput
, antepuesta al indicador.options
<Object>signal
<AbortSignal> Permite opcionalmente quequestion()
se cancele usando unAbortController
.
callback
<Function> Una función de callback que se invoca con la entrada del usuario en respuesta a laquery
.
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:
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.
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ón | Cambios |
---|---|
v18.0.0 | Pasar 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.0 | Se exponen la devolución de llamada write() del flujo y el valor de retorno. |
v0.7.7 | Añadido en: v0.7.7 |
stream
<stream.Writable>dir
<number>-1
: a la izquierda del cursor1
: a la derecha del cursor0
: toda la línea
callback
<Function> Se invoca una vez que la operación se completa.Devuelve: <boolean>
false
sistream
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ón | Cambios |
---|---|
v18.0.0 | Pasar 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.0 | Se exponen la devolución de llamada write() y el valor de retorno del flujo. |
v0.7.7 | Añadido en: v0.7.7 |
stream
<stream.Writable>callback
<Function> Se invoca una vez que se completa la operación.- Devuelve: <boolean>
false
sistream
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ón | Cambios |
---|---|
v15.14.0, v14.18.0 | Ahora se admite la opción signal . |
v15.8.0, v14.18.0 | Ahora se admite la opción history . |
v13.9.0 | Ahora se admite la opción tabSize . |
v8.3.0, v6.11.4 | Eliminar el límite máximo de la opción crlfDelay . |
v6.6.0 | Ahora se admite la opción crlfDelay . |
v6.3.0 | Ahora se admite la opción prompt . |
v6.0.0 | La opción historySize ahora puede ser 0 . |
v0.1.98 | Añ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 flujosinput
youtput
deben tratarse como un TTY, y se deben escribir códigos de escape ANSI/VT100 en él. Predeterminado: comprobarisTTY
en el flujooutput
al instanciarse.history
<string[]> Lista inicial de líneas de historial. Esta opción tiene sentido solo siterminal
se establece entrue
por el usuario o mediante una verificación interna deoutput
, 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 en0
. Esta opción tiene sentido solo siterminal
se establece entrue
por el usuario o mediante una verificación interna deoutput
, de lo contrario, el mecanismo de almacenamiento en caché del historial no se inicializa en absoluto. Predeterminado:30
.removeHistoryDuplicates
<boolean> Si estrue
, 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
excedecrlfDelay
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 a100
. Se puede establecer enInfinity
, 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 quereadline
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 aclose
en la interfaz.
- Devuelve: <readline.Interface>
El método readline.createInterface()
crea una nueva instancia de readline.Interface
.
import { createInterface } from 'node:readline'
import { stdin, stdout } from 'node:process'
const rl = createInterface({
input: stdin,
output: stdout,
})
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'
:
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]
.
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:
function completer(linePartial, callback) {
callback(null, [['123'], linePartial])
}
readline.cursorTo(stream, x[, y][, callback])
[Historial]
Versión | Cambios |
---|---|
v18.0.0 | Pasar un callback inválido al argumento callback ahora lanza ERR_INVALID_ARG_TYPE en lugar de ERR_INVALID_CALLBACK . |
v12.7.0 | El callback write() del stream y el valor de retorno se exponen. |
v0.7.7 | Agregado 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
sistream
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ón | Cambios |
---|---|
v18.0.0 | Pasar 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.0 | Se exponen la devolución de llamada write() y el valor de retorno de la secuencia. |
v0.7.7 | Añ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
sistream
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
stream
<stream.Readable>interface
<readline.InterfaceConstructor>
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
.
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:
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)
})
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
:
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()
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'
:
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}`)
})
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:
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)
}
})()
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 teclado | Descripción | Notas |
---|---|---|
+ + | Eliminar línea a la izquierda | No funciona en Linux, Mac ni Windows |
+ + | Eliminar línea a la derecha | No 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 / EOF | No 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 previamente | Solo funciona con texto eliminado mediante + o + |
+ | Ciclar entre textos eliminados previamente | Solo 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 anterior | Cualquier 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 anterior | Muchas 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 palabra | No 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 izquierda | No funciona en Mac |