Readline
[Stabile: 2 - Stabile]
Stabile: 2 Stabilità: 2 - Stabile
Codice Sorgente: lib/readline.js
Il modulo node:readline
fornisce un'interfaccia per la lettura dei dati da uno stream Readable (come process.stdin
) riga per riga.
Per utilizzare le API basate su promise:
import * as readline from 'node:readline/promises'
const readline = require('node:readline/promises')
Per utilizzare le API con callback e sincrona:
import * as readline from 'node:readline'
const readline = require('node:readline')
Il seguente semplice esempio illustra l'uso di base del modulo 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('Cosa ne pensi di Node.js? ')
console.log(`Grazie per il tuo prezioso feedback: ${answer}`)
rl.close()
const readline = require('node:readline')
const { stdin: input, stdout: output } = require('node:process')
const rl = readline.createInterface({ input, output })
rl.question('Cosa ne pensi di Node.js? ', answer => {
// TODO: Registra la risposta in un database
console.log(`Grazie per il tuo prezioso feedback: ${answer}`)
rl.close()
})
Una volta invocato questo codice, l'applicazione Node.js non terminerà finché l'interfaccia readline.Interface
non sarà chiusa, perché l'interfaccia attende la ricezione dei dati dallo stream input
.
Classe: InterfaceConstructor
Aggiunto in: v0.1.104
- Estensione: <EventEmitter>
Le istanze della classe InterfaceConstructor
sono costruite usando il metodo readlinePromises.createInterface()
o readline.createInterface()
. Ogni istanza è associata a un singolo stream input
Readable e a un singolo stream output
Writable. Lo stream output
viene utilizzato per stampare i prompt per l'input utente che arriva e viene letto dallo stream input
.
Evento: 'close'
Aggiunto in: v0.1.98
L'evento 'close'
viene emesso quando si verifica uno dei seguenti eventi:
- Viene chiamato il metodo
rl.close()
e l'istanzaInterfaceConstructor
ha rilasciato il controllo sui flussiinput
eoutput
; - Il flusso
input
riceve il suo evento'end'
; - Il flusso
input
riceve + per segnalare la fine della trasmissione (EOT); - Il flusso
input
riceve + per segnalareSIGINT
e non è registrato alcun listener per l'evento'SIGINT'
sull'istanzaInterfaceConstructor
.
La funzione listener viene chiamata senza passare alcun argomento.
L'istanza InterfaceConstructor
termina una volta emesso l'evento 'close'
.
Evento: 'line'
Aggiunto in: v0.1.98
L'evento 'line'
viene emesso ogni volta che il flusso input
riceve un input di fine riga (\n
, \r
, o \r\n
). Questo di solito si verifica quando l'utente preme o .
L'evento 'line'
viene emesso anche se sono stati letti nuovi dati da un flusso e quel flusso termina senza un marcatore di fine riga finale.
La funzione listener viene chiamata con una stringa contenente l'unica riga di input ricevuta.
rl.on('line', input => {
console.log(`Ricevuto: ${input}`)
})
Evento: 'history'
Aggiunto in: v15.8.0, v14.18.0
L'evento 'history'
viene emesso ogni volta che la matrice history è cambiata.
La funzione listener viene chiamata con una matrice contenente la matrice history. Rifletterà tutte le modifiche, le righe aggiunte e le righe rimosse a causa di historySize
e removeHistoryDuplicates
.
Lo scopo principale è quello di permettere a un listener di persistere la cronologia. È anche possibile per il listener modificare l'oggetto history. Questo potrebbe essere utile per impedire che determinate righe vengano aggiunte alla cronologia, come una password.
rl.on('history', history => {
console.log(`Ricevuto: ${history}`)
})
Evento: 'pause'
Aggiunto in: v0.7.5
L'evento 'pause'
viene emesso quando si verifica uno dei seguenti eventi:
- Il flusso
input
è in pausa. - Il flusso
input
non è in pausa e riceve l'evento'SIGCONT'
. (Vedi eventi'SIGTSTP'
e'SIGCONT'
.)
La funzione listener viene chiamata senza passare alcun argomento.
rl.on('pause', () => {
console.log('Readline in pausa.')
})
Evento: 'resume'
Aggiunto in: v0.7.5
L'evento 'resume'
viene emesso ogni volta che lo stream input
viene ripreso.
La funzione listener viene chiamata senza passare alcun argomento.
rl.on('resume', () => {
console.log('Readline ripreso.')
})
Evento: 'SIGCONT'
Aggiunto in: v0.7.5
L'evento 'SIGCONT'
viene emesso quando un processo Node.js precedentemente spostato in background usando + (cioè SIGTSTP
) viene poi riportato in primo piano usando fg(1p)
.
Se lo stream input
è stato messo in pausa prima della richiesta SIGTSTP
, questo evento non verrà emesso.
La funzione listener viene invocata senza passare alcun argomento.
rl.on('SIGCONT', () => {
// `prompt` riprenderà automaticamente lo stream
rl.prompt()
})
L'evento 'SIGCONT'
non è supportato su Windows.
Evento: 'SIGINT'
Aggiunto in: v0.3.0
L'evento 'SIGINT'
viene emesso ogni volta che lo stream input
riceve un input, tipicamente noto come SIGINT
. Se non sono registrati listener per l'evento 'SIGINT'
quando lo stream input
riceve un SIGINT
, verrà emesso l'evento 'pause'
.
La funzione listener viene invocata senza passare alcun argomento.
rl.on('SIGINT', () => {
rl.question('Sei sicuro di voler uscire? ', answer => {
if (answer.match(/^y(es)?$/i)) rl.pause()
})
})
Evento: 'SIGTSTP'
Aggiunto in: v0.7.5
L'evento 'SIGTSTP'
viene emesso quando lo stream input
riceve un input +, tipicamente noto come SIGTSTP
. Se non sono registrati listener per l'evento 'SIGTSTP'
quando lo stream input
riceve un SIGTSTP
, il processo Node.js verrà inviato in background.
Quando il programma viene ripreso usando fg(1p)
, verranno emessi gli eventi 'pause'
e 'SIGCONT'
. Questi possono essere utilizzati per riprendere lo stream input
.
Gli eventi 'pause'
e 'SIGCONT'
non verranno emessi se l'input è stato messo in pausa prima che il processo venisse inviato in background.
La funzione listener viene invocata senza passare alcun argomento.
rl.on('SIGTSTP', () => {
// Questo sovrascriverà SIGTSTP e impedirà al programma di andare in
// background.
console.log('SIGTSTP intercettato.')
})
L'evento 'SIGTSTP'
non è supportato su Windows.
rl.close()
Aggiunto in: v0.1.98
Il metodo rl.close()
chiude l'istanza InterfaceConstructor
e rilascia il controllo sui flussi input
e output
. Quando viene chiamato, viene emesso l'evento 'close'
.
Chiamare rl.close()
non interrompe immediatamente l'emissione di altri eventi (incluso 'line'
) dall'istanza InterfaceConstructor
.
rl.pause()
Aggiunto in: v0.3.4
Il metodo rl.pause()
mette in pausa il flusso input
, permettendo di riprenderlo in seguito se necessario.
Chiamare rl.pause()
non interrompe immediatamente l'emissione di altri eventi (incluso 'line'
) dall'istanza InterfaceConstructor
.
rl.prompt([preserveCursor])
Aggiunto in: v0.1.98
preserveCursor
<boolean> Setrue
, impedisce che il posizionamento del cursore venga ripristinato a0
.
Il metodo rl.prompt()
scrive il prompt
configurato dell'istanza InterfaceConstructor
su una nuova riga in output
per fornire all'utente una nuova posizione in cui fornire input.
Quando viene chiamato, rl.prompt()
riprende il flusso input
se è stato messo in pausa.
Se InterfaceConstructor
è stato creato con output
impostato su null
o undefined
, il prompt non viene scritto.
rl.resume()
Aggiunto in: v0.3.4
Il metodo rl.resume()
riprende il flusso input
se è stato messo in pausa.
rl.setPrompt(prompt)
Aggiunto in: v0.1.98
prompt
<string>
Il metodo rl.setPrompt()
imposta il prompt che verrà scritto su output
ogni volta che viene chiamato rl.prompt()
.
rl.getPrompt()
Aggiunto in: v15.3.0, v14.17.0
- Restituisce: <string> la stringa del prompt corrente
Il metodo rl.getPrompt()
restituisce il prompt corrente utilizzato da rl.prompt()
.
rl.write(data[, key])
Aggiunto in: v0.1.98
Il metodo rl.write()
scriverà data
o una sequenza di tasti identificata da key
sull'output
. L'argomento key
è supportato solo se output
è un terminale di testo TTY. Vedi combinazioni di tasti TTY per un elenco di combinazioni di tasti.
Se key
è specificato, data
viene ignorato.
Quando viene chiamato, rl.write()
riprende il flusso input
se è stato messo in pausa.
Se InterfaceConstructor
è stato creato con output
impostato su null
o undefined
, data
e key
non vengono scritti.
rl.write('Elimina questo!')
// Simula Ctrl+U per eliminare la riga scritta precedentemente
rl.write(null, { ctrl: true, name: 'u' })
Il metodo rl.write()
scriverà i dati nell'input dell'Interface
readline
come se fossero forniti dall'utente.
rl[Symbol.asyncIterator]()
[Cronologia]
Versione | Modifiche |
---|---|
v11.14.0, v10.17.0 | Il supporto di Symbol.asyncIterator non è più sperimentale. |
v11.4.0, v10.16.0 | Aggiunto in: v11.4.0, v10.16.0 |
- Restituisce: <AsyncIterator>
Crea un oggetto AsyncIterator
che itera su ogni riga nel flusso di input come stringa. Questo metodo consente l'iterazione asincrona di oggetti InterfaceConstructor
tramite cicli for await...of
.
Gli errori nel flusso di input non vengono inoltrati.
Se il ciclo viene terminato con break
, throw
o return
, verrà chiamato rl.close()
. In altre parole, l'iterazione su un InterfaceConstructor
consumerà sempre completamente il flusso di input.
Le prestazioni non sono paragonabili all'API tradizionale dell'evento 'line'
. Utilizzare 'line'
per applicazioni sensibili alle prestazioni.
async function processLineByLine() {
const rl = readline.createInterface({
// ...
})
for await (const line of rl) {
// Ogni riga nell'input readline sarà successivamente disponibile qui come
// `line`.
}
}
readline.createInterface()
inizia a consumare il flusso di input una volta invocato. Avere operazioni asincrone tra la creazione dell'interfaccia e l'iterazione asincrona può comportare la perdita di righe.
rl.line
[Cronologia]
Versione | Modifiche |
---|---|
v15.8.0, v14.18.0 | Il valore sarà sempre una stringa, mai indefinito. |
v0.1.98 | Aggiunto in: v0.1.98 |
I dati di input correnti in elaborazione da parte di Node.
Questo può essere utilizzato quando si raccolgono input da un flusso TTY per recuperare il valore corrente che è stato elaborato finora, prima che venga emesso l'evento line
. Una volta emesso l'evento line
, questa proprietà sarà una stringa vuota.
Essere consapevoli che la modifica del valore durante l'esecuzione dell'istanza può avere conseguenze impreviste se rl.cursor
non viene anche controllato.
Se non si utilizza un flusso TTY per l'input, utilizzare l'evento 'line'
.
Un possibile caso d'uso sarebbe il seguente:
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
Aggiunto in: v0.1.98
La posizione del cursore relativa a rl.line
.
Questo tiene traccia di dove si posiziona il cursore corrente nella stringa di input, durante la lettura dell'input da un flusso TTY. La posizione del cursore determina la parte della stringa di input che verrà modificata durante l'elaborazione dell'input, nonché la colonna in cui verrà visualizzato il caret del terminale.
rl.getCursorPos()
Aggiunto in: v13.5.0, v12.16.0
- Restituisce: <Object>
Restituisce la posizione reale del cursore in relazione al prompt di input + stringa. Stringhe di input lunghe (a capo), così come i prompt a più righe sono inclusi nei calcoli.
Promises API
Aggiunto in: v17.0.0
[Stabile: 1 - Sperimentale]
Stabile: 1 Stabilità: 1 - Sperimentale
Classe: readlinePromises.Interface
Aggiunto in: v17.0.0
- Estende: <readline.InterfaceConstructor>
Le istanze della classe readlinePromises.Interface
sono costruite usando il metodo readlinePromises.createInterface()
. Ogni istanza è associata a un singolo flusso input
Readable e a un singolo flusso output
Writable. Il flusso output
viene utilizzato per stampare i prompt per l'input dell'utente che arriva e viene letto dal flusso input
.
rl.question(query[, options])
Aggiunto in: v17.0.0
query
<string> Un'istruzione o una query da scrivere suoutput
, anteposta al prompt.options
<Object>signal
<AbortSignal> Consente facoltativamente di annullarequestion()
usando unAbortSignal
.
Restituisce: <Promise> Una promessa che viene soddisfatta con l'input dell'utente in risposta alla
query
.
Il metodo rl.question()
visualizza la query
scrivendola su output
, attende che l'input dell'utente venga fornito su input
, quindi invoca la funzione callback
passando l'input fornito come primo argomento.
Quando viene chiamato, rl.question()
riprenderà il flusso input
se è stato messo in pausa.
Se readlinePromises.Interface
è stato creato con output
impostato su null
o undefined
, la query
non viene scritta.
Se la domanda viene effettuata dopo rl.close()
, viene restituita una promessa rifiutata.
Esempio di utilizzo:
const answer = await rl.question('Qual è il tuo cibo preferito? ')
console.log(`Oh, quindi il tuo cibo preferito è ${answer}`)
Utilizzo di AbortSignal
per annullare una domanda.
const signal = AbortSignal.timeout(10_000)
signal.addEventListener(
'abort',
() => {
console.log('La domanda sul cibo è scaduta')
},
{ once: true }
)
const answer = await rl.question('Qual è il tuo cibo preferito? ', { signal })
console.log(`Oh, quindi il tuo cibo preferito è ${answer}`)
Classe: readlinePromises.Readline
Aggiunto in: v17.0.0
new readlinePromises.Readline(stream[, options])
Aggiunto in: v17.0.0
stream
<stream.Writable> Un flusso TTY.options
<Object>autoCommit
<boolean> Setrue
, non è necessario chiamarerl.commit()
.
rl.clearLine(dir)
Aggiunto in: v17.0.0
dir
<intero>-1
: a sinistra del cursore1
: a destra del cursore0
: l'intera riga
Restituisce: this
Il metodo rl.clearLine()
aggiunge all'elenco interno delle azioni in sospeso un'azione che cancella la riga corrente dello stream
associato in una direzione specifica identificata da dir
. Chiamare rl.commit()
per vedere l'effetto di questo metodo, a meno che autoCommit: true
non sia stato passato al costruttore.
rl.clearScreenDown()
Aggiunto in: v17.0.0
- Restituisce: this
Il metodo rl.clearScreenDown()
aggiunge all'elenco interno delle azioni in sospeso un'azione che cancella lo stream
associato dalla posizione corrente del cursore in giù. Chiamare rl.commit()
per vedere l'effetto di questo metodo, a meno che autoCommit: true
non sia stato passato al costruttore.
rl.commit()
Aggiunto in: v17.0.0
- Restituisce: <Promise>
Il metodo rl.commit()
invia tutte le azioni in sospeso allo stream
associato e cancella l'elenco interno delle azioni in sospeso.
rl.cursorTo(x[, y])
Aggiunto in: v17.0.0
Il metodo rl.cursorTo()
aggiunge all'elenco interno delle azioni in sospeso un'azione che sposta il cursore nella posizione specificata nello stream
associato. Chiamare rl.commit()
per vedere l'effetto di questo metodo, a meno che autoCommit: true
non sia stato passato al costruttore.
rl.moveCursor(dx, dy)
Aggiunto in: v17.0.0
Il metodo rl.moveCursor()
aggiunge all'elenco interno delle azioni in sospeso un'azione che sposta il cursore relativamente alla sua posizione corrente nello stream
associato. Chiamare rl.commit()
per vedere l'effetto di questo metodo, a meno che autoCommit: true
non sia stato passato al costruttore.
rl.rollback()
Aggiunto in: v17.0.0
- Restituisce: this
Il metodo rl.rollback
cancella l'elenco interno delle azioni in sospeso senza inviarlo allo stream
associato.
readlinePromises.createInterface(options)
Aggiunto in: v17.0.0
options
<Object>input
<stream.Readable> Lo stream Readable da ascoltare. Questa opzione è obbligatoria.output
<stream.Writable> Lo stream Writable su cui scrivere i dati readline.completer
<Function> Una funzione opzionale utilizzata per il completamento automatico con Tab.terminal
<boolean>true
se gli streaminput
eoutput
devono essere trattati come un TTY e devono avere codici di escape ANSI/VT100 scritti su di essi. Default: verificaisTTY
sullo streamoutput
al momento dell'istanza.history
<string[]> Elenco iniziale di righe di cronologia. Questa opzione ha senso solo seterminal
è impostato sutrue
dall'utente o da un controllooutput
interno, altrimenti il meccanismo di memorizzazione nella cache della cronologia non viene inizializzato affatto. Default:[]
.historySize
<number> Numero massimo di righe di cronologia mantenute. Per disabilitare la cronologia impostare questo valore su0
. Questa opzione ha senso solo seterminal
è impostato sutrue
dall'utente o da un controllooutput
interno, altrimenti il meccanismo di memorizzazione nella cache della cronologia non viene inizializzato affatto. Default:30
.removeHistoryDuplicates
<boolean> Setrue
, quando una nuova riga di input aggiunta all'elenco cronologia ne duplica una più vecchia, questa rimuove la riga più vecchia dall'elenco. Default:false
.prompt
<string> La stringa di prompt da utilizzare. Default:'\> '
.crlfDelay
<number> Se il ritardo tra\r
e\n
superacrlfDelay
millisecondi, sia\r
che\n
saranno trattati come input di fine riga separati.crlfDelay
sarà forzato a un numero non inferiore a100
. Può essere impostato suInfinity
, nel qual caso\r
seguito da\n
sarà sempre considerato una singola nuova riga (il che potrebbe essere ragionevole per leggere file con delimitatore di riga\r\n
). Default:100
.escapeCodeTimeout
<number> La durata in cuireadlinePromises
attenderà un carattere (durante la lettura di una sequenza di tasti ambigua in millisecondi, una che può sia formare una sequenza di tasti completa usando l'input letto finora e può richiedere input aggiuntivi per completare una sequenza di tasti più lunga). Default:500
.tabSize
<integer> Il numero di spazi a cui equivale un tab (minimo 1). Default:8
.
Restituisce: <readlinePromises.Interface>
Il metodo readlinePromises.createInterface()
crea una nuova istanza 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 volta creata l'istanza readlinePromises.Interface
, il caso più comune è quello di ascoltare l'evento 'line'
:
rl.on('line', line => {
console.log(`Ricevuto: ${line}`)
})
Se terminal
è true
per questa istanza, lo stream output
otterrà la migliore compatibilità se definisce una proprietà output.columns
ed emette un evento 'resize'
sull' output
se o quando le colonne cambiano (process.stdout
lo fa automaticamente quando è un TTY).
Uso della funzione completer
La funzione completer
accetta come argomento la riga corrente inserita dall'utente e restituisce un Array
con 2 elementi:
- Un
Array
con le voci corrispondenti per il completamento. - La sottostringa utilizzata per la corrispondenza.
Ad esempio: [[substr1, substr2, ...], originalsubstring]
.
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ')
const hits = completions.filter(c => c.startsWith(line))
// Mostra tutti i completamenti se non ne vengono trovati
return [hits.length ? hits : completions, line]
}
La funzione completer
può anche restituire una <Promise>, o essere asincrona:
async function completer(linePartial) {
await someAsyncWork()
return [['123'], linePartial]
}
API Callback
Aggiunto in: v0.1.104
Classe: readline.Interface
[Cronologia]
Versione | Modifiche |
---|---|
v17.0.0 | La classe readline.Interface ora eredita da Interface . |
v0.1.104 | Aggiunto in: v0.1.104 |
- Estensioni: <readline.InterfaceConstructor>
Le istanze della classe readline.Interface
vengono costruite usando il metodo readline.createInterface()
. Ogni istanza è associata a un singolo flusso input
Readable e a un singolo flusso output
Writable. Il flusso output
viene utilizzato per stampare i prompt per l'input dell'utente che arriva e viene letto dal flusso input
.
rl.question(query[, options], callback)
Aggiunto in: v0.3.3
query
<string> Un'affermazione o una query da scrivere suoutput
, anteposta al prompt.options
<Object>signal
<AbortSignal> Consente facoltativamente di annullarequestion()
usando unAbortController
.
callback
<Function> Una funzione di callback che viene invocata con l'input dell'utente in risposta allaquery
.
Il metodo rl.question()
visualizza la query
scrivendola su output
, attende che l'input dell'utente venga fornito su input
, quindi invoca la funzione callback
passando l'input fornito come primo argomento.
Quando viene chiamato, rl.question()
riprenderà il flusso input
se è stato messo in pausa.
Se readline.Interface
è stato creato con output
impostato su null
o undefined
, la query
non viene scritta.
La funzione callback
passata a rl.question()
non segue il modello tipico di accettazione di un oggetto Error
o null
come primo argomento. La callback
viene chiamata con la risposta fornita come unico argomento.
Verra generato un errore se si chiama rl.question()
dopo rl.close()
.
Esempio di utilizzo:
rl.question('Qual è il tuo cibo preferito? ', answer => {
console.log(`Oh, quindi il tuo cibo preferito è ${answer}`)
})
Utilizzo di un AbortController
per annullare una domanda.
const ac = new AbortController()
const signal = ac.signal
rl.question('Qual è il tuo cibo preferito? ', { signal }, answer => {
console.log(`Oh, quindi il tuo cibo preferito è ${answer}`)
})
signal.addEventListener(
'abort',
() => {
console.log('La domanda sul cibo è scaduta')
},
{ once: true }
)
setTimeout(() => ac.abort(), 10000)
readline.clearLine(stream, dir[, callback])
[Cronologia]
Versione | Modifiche |
---|---|
v18.0.0 | Passare un callback non valido all'argomento callback ora genera ERR_INVALID_ARG_TYPE invece di ERR_INVALID_CALLBACK . |
v12.7.0 | Il callback e il valore di ritorno di stream.write() sono esposti. |
v0.7.7 | Aggiunto in: v0.7.7 |
stream
<stream.Writable>dir
<number>-1
: a sinistra del cursore1
: a destra del cursore0
: l'intera riga
callback
<Function> Viene invocato una volta completata l'operazione.Restituisce: <boolean>
false
sestream
desidera che il codice chiamante attenda l'emissione dell'evento'drain'
prima di continuare a scrivere dati aggiuntivi; altrimentitrue
.
Il metodo readline.clearLine()
cancella la riga corrente del flusso TTY specificato in una direzione specificata da dir
.
readline.clearScreenDown(stream[, callback])
[Cronologia]
Versione | Modifiche |
---|---|
v18.0.0 | Passare un callback non valido all'argomento callback ora genera ERR_INVALID_ARG_TYPE invece di ERR_INVALID_CALLBACK . |
v12.7.0 | Il callback e il valore di ritorno di stream.write() sono esposti. |
v0.7.7 | Aggiunto in: v0.7.7 |
stream
<stream.Writable>callback
<Function> Viene invocato una volta completata l'operazione.- Restituisce: <boolean>
false
sestream
desidera che il codice chiamante attenda l'emissione dell'evento'drain'
prima di continuare a scrivere dati aggiuntivi; altrimentitrue
.
Il metodo readline.clearScreenDown()
cancella il flusso TTY specificato dalla posizione corrente del cursore in giù.
readline.createInterface(options)
[Cronologia]
Versione | Modifiche |
---|---|
v15.14.0, v14.18.0 | Ora è supportata l'opzione signal . |
v15.8.0, v14.18.0 | Ora è supportata l'opzione history . |
v13.9.0 | Ora è supportata l'opzione tabSize . |
v8.3.0, v6.11.4 | Rimosso il limite massimo dell'opzione crlfDelay . |
v6.6.0 | Ora è supportata l'opzione crlfDelay . |
v6.3.0 | Ora è supportata l'opzione prompt . |
v6.0.0 | L'opzione historySize può ora essere 0 . |
v0.1.98 | Aggiunto in: v0.1.98 |
options
<Oggetto>input
<stream.Readable> Il flusso Readable da ascoltare. Questa opzione è obbligatoria.output
<stream.Writable> Il flusso Writable su cui scrivere i dati readline.completer
<Funzione> Una funzione opzionale utilizzata per il completamento automatico tramite Tab.terminal
<booleano>true
se i flussiinput
eoutput
devono essere trattati come un TTY e avere codici di escape ANSI/VT100 scritti su di essi. Predefinito: controllo diisTTY
sul flussooutput
al momento dell'istanza.history
<string[]> Elenco iniziale delle righe di cronologia. Questa opzione ha senso solo seterminal
è impostato sutrue
dall'utente o da un controllooutput
interno, altrimenti il meccanismo di memorizzazione nella cache della cronologia non viene inizializzato affatto. Predefinito:[]
.historySize
<numero> Numero massimo di righe di cronologia conservate. Per disabilitare la cronologia impostare questo valore su0
. Questa opzione ha senso solo seterminal
è impostato sutrue
dall'utente o da un controllooutput
interno, altrimenti il meccanismo di memorizzazione nella cache della cronologia non viene inizializzato affatto. Predefinito:30
.removeHistoryDuplicates
<booleano> Setrue
, quando una nuova riga di input aggiunta all'elenco della cronologia ne duplica una più vecchia, questa rimuove la riga più vecchia dall'elenco. Predefinito:false
.prompt
<stringa> La stringa di prompt da utilizzare. Predefinito:'\> '
.crlfDelay
<numero> Se il ritardo tra\r
e\n
supera icrlfDelay
millisecondi, sia\r
che\n
saranno trattati come input di fine riga separati.crlfDelay
sarà convertito in un numero non inferiore a100
. Può essere impostato suInfinity
, nel qual caso\r
seguito da\n
sarà sempre considerato un singolo carattere di nuova riga (il che potrebbe essere ragionevole per leggere file con delimitatore di riga\r\n
). Predefinito:100
.escapeCodeTimeout
<numero> La durata in cuireadline
attenderà un carattere (durante la lettura di una sequenza di tasti ambigua in millisecondi, una che può sia formare una sequenza di tasti completa usando l'input letto finora e può accettare input aggiuntivi per completare una sequenza di tasti più lunga). Predefinito:500
.tabSize
<intero> Il numero di spazi a cui equivale un tab (minimo 1). Predefinito:8
.signal
<AbortSignal> Consente la chiusura dell'interfaccia usando un AbortSignal. L'interruzione del segnale chiamerà internamenteclose
sull'interfaccia.
Restituisce: <readline.Interface>
Il metodo readline.createInterface()
crea una nuova istanza 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 volta creata l'istanza readline.Interface
, il caso più comune è quello di ascoltare l'evento 'line'
:
rl.on('line', line => {
console.log(`Ricevuto: ${line}`)
})
Se terminal
è true
per questa istanza, il flusso output
otterrà la migliore compatibilità se definisce una proprietà output.columns
ed emette un evento 'resize'
sull'output se o quando le colonne cambiano (process.stdout
lo fa automaticamente quando è un TTY).
Quando si crea un readline.Interface
usando stdin
come input, il programma non terminerà finché non riceverà un carattere EOF. Per uscire senza attendere l'input dell'utente, chiamare process.stdin.unref()
.
Uso della funzione completer
La funzione completer
accetta come argomento la riga corrente inserita dall'utente e restituisce un Array
con 2 elementi:
- Un
Array
con le voci corrispondenti per il completamento. - La sottostringa utilizzata per la corrispondenza.
Ad esempio: [[substr1, substr2, ...], originalsubstring]
.
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ')
const hits = completions.filter(c => c.startsWith(line))
// Mostra tutti i completamenti se nessuno trovato
return [hits.length ? hits : completions, line]
}
La funzione completer
può essere chiamata in modo asincrono se accetta due argomenti:
function completer(linePartial, callback) {
callback(null, [['123'], linePartial])
}
readline.cursorTo(stream, x[, y][, callback])
[Cronologia]
Versione | Modifiche |
---|---|
v18.0.0 | Passare un callback non valido all'argomento callback ora genera ERR_INVALID_ARG_TYPE invece di ERR_INVALID_CALLBACK . |
v12.7.0 | Il callback e il valore di ritorno di stream.write() sono esposti. |
v0.7.7 | Aggiunto in: v0.7.7 |
stream
<stream.Writable>x
<number>y
<number>callback
<Function> Viene invocato una volta completata l'operazione.- Restituisce: <boolean>
false
sestream
desidera che il codice chiamante aspetti che venga emesso l'evento'drain'
prima di continuare a scrivere dati aggiuntivi; altrimentitrue
.
Il metodo readline.cursorTo()
sposta il cursore nella posizione specificata in un dato flusso stream
TTY.
readline.moveCursor(stream, dx, dy[, callback])
[Cronologia]
Versione | Modifiche |
---|---|
v18.0.0 | Passare un callback non valido all'argomento callback ora genera ERR_INVALID_ARG_TYPE invece di ERR_INVALID_CALLBACK . |
v12.7.0 | Il callback e il valore di ritorno di stream.write() sono esposti. |
v0.7.7 | Aggiunto in: v0.7.7 |
stream
<stream.Writable>dx
<number>dy
<number>callback
<Function> Viene invocato una volta completata l'operazione.- Restituisce: <boolean>
false
sestream
desidera che il codice chiamante aspetti che venga emesso l'evento'drain'
prima di continuare a scrivere dati aggiuntivi; altrimentitrue
.
Il metodo readline.moveCursor()
sposta il cursore relativamente alla sua posizione corrente in un dato flusso stream
TTY.
readline.emitKeypressEvents(stream[, interface])
Aggiunto in: v0.7.7
stream
<stream.Readable>interface
<readline.InterfaceConstructor>
Il metodo readline.emitKeypressEvents()
fa sì che il flusso Readable dato inizi a emettere eventi 'keypress'
corrispondenti all'input ricevuto.
Opzionalmente, interface
specifica un'istanza readline.Interface
per cui il completamento automatico è disabilitato quando viene rilevato un input copiato e incollato.
Se stream
è un TTY, allora deve essere in modalità raw.
Questo viene chiamato automaticamente da qualsiasi istanza readline sul suo input
se l'input
è un terminale. La chiusura dell'istanza readline
non impedisce all'input
di emettere eventi 'keypress'
.
readline.emitKeypressEvents(process.stdin)
if (process.stdin.isTTY) process.stdin.setRawMode(true)
Esempio: Tiny CLI
Il seguente esempio illustra l'utilizzo della classe readline.Interface
per implementare una piccola interfaccia a riga di comando:
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(`Say what? I might have heard '${line.trim()}'`)
break
}
rl.prompt()
}).on('close', () => {
console.log('Have a great day!')
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(`Say what? I might have heard '${line.trim()}'`)
break
}
rl.prompt()
}).on('close', () => {
console.log('Have a great day!')
process.exit(0)
})
Esempio: Lettura di un flusso di file riga per riga
Un caso d'uso comune per readline
è consumare un file di input una riga alla volta. Il modo più semplice per farlo è sfruttare l'API fs.ReadStream
e un ciclo 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: utilizziamo l'opzione crlfDelay per riconoscere tutte le istanze di CR LF
// ('\r\n') in input.txt come un singolo ritorno a capo.
for await (const line of rl) {
// Ogni riga in input.txt sarà successivamente disponibile qui come `line`.
console.log(`Riga dal file: ${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: utilizziamo l'opzione crlfDelay per riconoscere tutte le istanze di CR LF
// ('\r\n') in input.txt come un singolo ritorno a capo.
for await (const line of rl) {
// Ogni riga in input.txt sarà successivamente disponibile qui come `line`.
console.log(`Riga dal file: ${line}`)
}
}
processLineByLine()
In alternativa, si potrebbe utilizzare l'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(`Riga dal file: ${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(`Riga dal file: ${line}`)
})
Attualmente, il ciclo for await...of
può essere un po' più lento. Se il flusso async
/await
e la velocità sono entrambi essenziali, è possibile applicare un approccio misto:
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 => {
// Processa la riga.
})
await once(rl, 'close')
console.log('File elaborato.')
} 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 => {
// Processa la riga.
})
await once(rl, 'close')
console.log('File elaborato.')
} catch (err) {
console.error(err)
}
})()
Tasti di scelta rapida TTY
Tasti di scelta rapida | Descrizione | Note |
---|---|---|
+ + | Elimina riga a sinistra | Non funziona su Linux, Mac e Windows |
+ + | Elimina riga a destra | Non funziona su Mac |
+ | Invia SIGINT o chiude l'istanza readline | |
+ | Elimina a sinistra | |
+ | Elimina a destra o chiude l'istanza readline se la riga corrente è vuota / EOF | Non funziona su Windows |
+ | Elimina dalla posizione corrente all'inizio della riga | |
+ | Elimina dalla posizione corrente alla fine della riga | |
+ | Incolla (Recupera) il testo precedentemente eliminato | Funziona solo con il testo eliminato da + o + |
+ | Passa tra i testi precedentemente eliminati | Disponibile solo quando l'ultimo colpo di tasto è + o + |
+ | Vai all'inizio della riga | |
+ | Vai alla fine della riga | |
+ | Indietro di un carattere | |
+ | Avanti di un carattere | |
+ | Pulisci schermo | |
+ | Elemento cronologia successivo | |
+ | Elemento cronologia precedente | |
+ | Annulla la modifica precedente | Qualsiasi colpo di tasto che emette il codice chiave 0x1F eseguirà questa azione. In molti terminali, ad esempio xterm , questo è associato a + . |
+ | Ripristina la modifica precedente | Molti terminali non hanno un tasto di scelta rapida di ripristino predefinito. Scegliamo il codice chiave 0x1E per eseguire il ripristino. In xterm , è associato a + per impostazione predefinita. |
+ | Sposta il processo in esecuzione in background. Digitare fg e premere per tornare. | Non funziona su Windows |
+ o + | Elimina all'indietro fino a un limite di parola | + Non funziona su Linux, Mac e Windows |
+ | Elimina in avanti fino a un limite di parola | Non funziona su Mac |
+ o + | Parola a sinistra | + Non funziona su Mac |
+ o + | Parola a destra | + Non funziona su Mac |
+ o + | Elimina parola a destra | + Non funziona su Windows |
+ | Elimina parola a sinistra | Non funziona su Mac |