Readline#

穩定性:2 - 穩定

原始碼: lib/readline.js

node:readline 模組提供了一個介面,用於一次從 可讀取 串流(例如 process.stdin)讀取資料。

若要使用基於承諾的 API

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

若要使用回呼和同步 API

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

以下簡單範例說明 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('What do you think of Node.js? ');

console.log(`Thank you for your valuable 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('What do you think of Node.js? ', (answer) => {
  // TODO: Log the answer in a database
  console.log(`Thank you for your valuable feedback: ${answer}`);

  rl.close();
});

呼叫此程式碼後,Node.js 應用程式不會終止,直到 readline.Interface 關閉,因為介面會等到在 input 串流中收到資料。

類別:InterfaceConstructor#

InterfaceConstructor 類別的執行個體是使用 readlinePromises.createInterface()readline.createInterface() 方法建構的。每個執行個體都與單一 input 可讀取 串流和單一 output 可寫入 串流關聯。output 串流用於列印使用者輸入的提示,而使用者輸入會到達 input 串流並從中讀取。

事件:'close'#

在發生下列其中一項情況時,會發出 'close' 事件

  • 呼叫 rl.close() 方法,且 InterfaceConstructor 執行個體已放棄對 inputoutput 串流的控制;
  • input 串流收到其 'end' 事件;
  • input 串流收到 Ctrl+D 以表示傳輸結束 (EOT);
  • input 串流收到 Ctrl+C 以表示 SIGINT,且在 InterfaceConstructor 執行個體上未註冊 'SIGINT' 事件監聽器。

呼叫監聽器函式時不傳遞任何引數。

發出 'close' 事件後,InterfaceConstructor 實例便會完成。

事件:'line'#

每當 input 串流收到換行輸入 (\n\r\r\n) 時,便會發出 'line' 事件。這通常會在使用者按下 EnterReturn 時發生。

如果從串流中讀取新資料,且該串流在沒有最後換行標記的情況下結束,也會發出 'line' 事件。

呼叫監聽器函式時,會傳遞包含單一行接收輸入的字串。

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

事件:'history'#

每當歷史記錄陣列變更時,便會發出 'history' 事件。

呼叫監聽器函式時,會傳遞包含歷史記錄陣列的陣列。它會反映所有變更,包括新增行和因 historySizeremoveHistoryDuplicates 而移除的行。

主要目的是讓監聽器保留歷史記錄。監聽器也有可能變更歷史記錄物件。這可能有助於防止某些行(例如密碼)加入歷史記錄。

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

事件:'pause'#

在發生下列情況之一時,會發出 'pause' 事件

  • input 串流已暫停。
  • input 串流未暫停,且收到 'SIGCONT' 事件。(請參閱事件 'SIGTSTP''SIGCONT'。)

呼叫監聽器函式時不傳遞任何引數。

rl.on('pause', () => {
  console.log('Readline paused.');
}); 

事件:'resume'#

每當 input 串流恢復時,就會發出 'resume' 事件。

呼叫監聽器函式時不傳遞任何引數。

rl.on('resume', () => {
  console.log('Readline resumed.');
}); 

事件:'SIGCONT'#

當先前使用 Ctrl+Z (即 SIGTSTP) 移至背景的 Node.js 程序,再使用 fg(1p) 移回前景時,會發出 'SIGCONT' 事件。

如果 input 串流在 SIGTSTP 要求之前暫停,則不會發出此事件。

呼叫監聽器函式時不會傳遞任何引數。

rl.on('SIGCONT', () => {
  // `prompt` will automatically resume the stream
  rl.prompt();
}); 

Windows 不支援 'SIGCONT' 事件。

事件:'SIGINT'#

每當 input 串流收到 Ctrl+C 輸入(通常稱為 SIGINT)時,就會發出 'SIGINT' 事件。如果當 input 串流收到 SIGINT 時,沒有註冊 'SIGINT' 事件監聽器,則會發出 'pause' 事件。

呼叫監聽器函式時不會傳遞任何引數。

rl.on('SIGINT', () => {
  rl.question('Are you sure you want to exit? ', (answer) => {
    if (answer.match(/^y(es)?$/i)) rl.pause();
  });
}); 

事件:'SIGTSTP'#

input 串流收到 Ctrl+Z 輸入(通常稱為 SIGTSTP)時,就會發出 'SIGTSTP' 事件。如果當 input 串流收到 SIGTSTP 時,沒有註冊 'SIGTSTP' 事件監聽器,則會將 Node.js 程序傳送至背景。

當使用 fg(1p) 恢復程式時,會發出 'pause''SIGCONT' 事件。這些事件可用於恢復 input 串流。

如果在程序送至背景之前暫停輸入,則不會發出 'pause''SIGCONT' 事件。

呼叫監聽器函式時不會傳遞任何引數。

rl.on('SIGTSTP', () => {
  // This will override SIGTSTP and prevent the program from going to the
  // background.
  console.log('Caught SIGTSTP.');
}); 

Windows 不支援 'SIGTSTP' 事件。

rl.close()#

rl.close() 方法會關閉 InterfaceConstructor 執行個體,並放棄對 inputoutput 串流的控制權。呼叫時,會發出 'close' 事件。

呼叫 rl.close() 並不會立即停止 InterfaceConstructor 執行個體發出其他事件(包括 'line')。

rl.pause()#

rl.pause() 方法會暫停 input 串流,讓它在必要時可以繼續。

呼叫 rl.pause() 並不會立即停止 InterfaceConstructor 執行個體發出其他事件(包括 'line')。

rl.prompt([preserveCursor])#

  • preserveCursor <boolean> 如果為 true,會防止游標位置重設為 0

rl.prompt() 方法會將 InterfaceConstructor 執行個體設定的 prompt 寫入 output 中的新行,以提供使用者新的輸入位置。

呼叫時,rl.prompt() 會在 input 串流暫停時繼續串流。

如果 InterfaceConstructor 是使用設定為 nullundefinedoutput 建立的,則不會寫入提示。

rl.resume()#

rl.resume() 方法會在 input 串流暫停時繼續串流。

rl.setPrompt(prompt)#

rl.setPrompt() 方法會設定提示字串,當呼叫 rl.prompt() 時,會寫入 output

rl.getPrompt()#

  • 傳回:<字串> 目前的提示字串

rl.getPrompt() 方法會傳回 rl.prompt() 目前使用的提示字串。

rl.write(data[, key])#

rl.write() 方法會將 data 或由 key 識別的按鍵順序寫入 output。只有當 outputTTY 文字終端機時,才支援 key 參數。請參閱 TTY 按鍵繫結 以取得按鍵組合清單。

如果指定 key,則會忽略 data

呼叫時,rl.write() 會在暫停後繼續 input 串流。

如果 InterfaceConstructor 是使用設定為 nullundefinedoutput 所建立,則不會寫入 datakey

rl.write('Delete this!');
// Simulate Ctrl+U to delete the line written previously
rl.write(null, { ctrl: true, name: 'u' }); 

rl.write() 方法會將資料寫入 readline Interfaceinput就像使用者提供的資料一樣

rl[Symbol.asyncIterator]()#

建立一個 AsyncIterator 物件,以字串形式逐行迭代輸入串流。此方法允許透過 for await...of 迴圈非同步迭代 InterfaceConstructor 物件。

輸入串流中的錯誤不會轉送。

如果迴圈以 breakthrowreturn 終止,將會呼叫 rl.close()。換句話說,迭代 InterfaceConstructor 永遠會完整使用輸入串流。

效能無法與傳統的 'line' 事件 API 相提並論。對於效能敏感的應用程式,請改用 'line'

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

  for await (const line of rl) {
    // Each line in the readline input will be successively available here as
    // `line`.
  }
} 

readline.createInterface() 呼叫後,將開始使用輸入串流。在建立介面和非同步迭代之間進行非同步操作可能會導致遺漏行。

rl.line#

節點目前處理中的輸入資料。

這可在從 TTY 串流收集輸入時使用,以在發出 `line` 事件之前,擷取迄今已處理的目前值。一旦發出 `line` 事件,此屬性將會是空字串。

請注意,如果沒有同時控制 `rl.cursor`,在執行個體執行期間修改值可能會造成意外後果。

如果沒有使用 TTY 串流作為輸入,請使用 `'line'` 事件。

一個可能的用例如下

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#

相對於 `rl.line` 的游標位置。

這會追蹤從 TTY 串流讀取輸入時,目前游標在輸入字串中的位置。游標位置會決定在處理輸入時,輸入字串中將修改的部分,以及終端插入符號將呈現的欄位。

rl.getCursorPos()#

傳回游標相對於輸入提示字串的實際位置。計算時會包含長輸入(換行)字串,以及多行提示。

Promises API#

穩定性:1 - 實驗性

類別:readlinePromises.Interface#

readlinePromises.Interface 類別的執行個體是使用 readlinePromises.createInterface() 方法建構的。每個執行個體都與單一 input 可讀取 串流和單一 output 可寫入 串流關聯。output 串流用於列印使用者輸入的提示,而使用者輸入會傳送到 input 串流並從中讀取。

rl.question(query[, options])#
  • query <string> 要寫入 output 的陳述或查詢,附加在提示之前。
  • options <Object>
    • signal <AbortSignal> 選擇性地允許使用 AbortSignal 取消 question()
  • 傳回:<Promise> Promise,在使用者輸入回應 query 後會以使用者的輸入兌現。

rl.question() 方法透過將 query 寫入 output 來顯示,等待使用者在 input 上提供輸入,然後呼叫 callback 函式,並將提供的輸入作為第一個引數傳遞。

呼叫時,如果 input 串流已暫停,rl.question() 會繼續串流。

如果 readlinePromises.Interface 是使用設定為 nullundefinedoutput 建立的,則不會寫入 query

如果在 rl.close() 之後呼叫問題,則會傳回一個遭拒絕的承諾。

範例用法

const answer = await rl.question('What is your favorite food? ');
console.log(`Oh, so your favorite food is ${answer}`); 

使用 AbortSignal 取消問題。

const signal = AbortSignal.timeout(10_000);

signal.addEventListener('abort', () => {
  console.log('The food question timed out');
}, { once: true });

const answer = await rl.question('What is your favorite food? ', { signal });
console.log(`Oh, so your favorite food is ${answer}`); 

類別:readlinePromises.Readline#

new readlinePromises.Readline(stream[, options])#
rl.clearLine(dir)#
  • dir <integer>
    • -1:從游標向左
    • 1:從游標向右
    • 0:整行
  • 傳回:這個

rl.clearLine() 方法會將清除與指定 dir 識別的方向相關聯的 stream 的目前行動作新增至待處理動作的內部清單。呼叫 rl.commit() 以查看此方法的效果,除非將 autoCommit: true 傳遞給建構函式。

rl.clearScreenDown()#
  • 傳回:這個

rl.clearScreenDown() 方法會將清除游標目前位置以下的關聯串流的動作加入到待處理動作的內部清單中。呼叫 rl.commit() 以查看此方法的效果,除非建構函式傳遞了 autoCommit: true

rl.commit()#

rl.commit() 方法會將所有待處理的動作傳送至關聯的 stream,並清除待處理動作的內部清單。

rl.cursorTo(x[, y])#

rl.cursorTo() 方法會將將游標移至關聯 stream 中指定位置的動作加入到待處理動作的內部清單中。呼叫 rl.commit() 以查看此方法的效果,除非建構函式傳遞了 autoCommit: true

rl.moveCursor(dx, dy)#

rl.moveCursor() 方法會將將游標相對於其在關聯 stream 中的目前位置移動的動作加入到待處理動作的內部清單中。呼叫 rl.commit() 以查看此方法的效果,除非建構函式傳遞了 autoCommit: true

rl.rollback()#
  • 傳回:這個

rl.rollback 方法會清除待處理動作的內部清單,而不會將其傳送至關聯的 stream

readlinePromises.createInterface(options)#

  • options <Object>
    • input <stream.Readable> 要監聽的 Readable 串流。此選項為必要
    • output <stream.Writable> 要將 readline 資料寫入的 Writable 串流。
    • completer <Function> 用於 Tab 自動完成的選用函式。
    • terminal <boolean> 如果 inputoutput 串流應視為 TTY,並寫入 ANSI/VT100 逸出碼,則為 true預設:建立執行個體時檢查 output 串流上的 isTTY
    • history <string[]> 歷程記錄行之初始清單。此選項僅在使用者或內部 output 檢查將 terminal 設為 true 時才有意義,否則歷程記錄快取機制根本不會初始化。預設:[]
    • historySize <number> 保留的最大歷程記錄行數。若要停用歷程記錄,請將此值設為 0。此選項僅在使用者或內部 output 檢查將 terminal 設為 true 時才有意義,否則歷程記錄快取機制根本不會初始化。預設:30
    • removeHistoryDuplicates <boolean> 如果為 true,當新增至歷程記錄清單的新輸入行與舊行重複時,會從清單中移除舊行。預設:false
    • prompt <字串> 要使用的提示字串。預設:'> '
    • crlfDelay <數字> 如果 \r\n 之間的延遲超過 crlfDelay 毫秒,\r\n 都將被視為獨立的行尾輸入。crlfDelay 將被強制轉換為不小於 100 的數字。它可以設定為 Infinity,這種情況下,\r 後接 \n 將始終被視為單一換行符(對於使用 \r\n 行分隔符讀取檔案可能是合理的)。預設:100
    • escapeCodeTimeout <數字> readlinePromises 將等待字元(以毫秒為單位讀取有歧義的按鍵順序時,可以使用到目前為止讀取的輸入形成完整按鍵順序,也可以採用額外的輸入來完成更長的按鍵順序)的持續時間。預設:500
    • tabSize <整數> 標籤等於的空格數(最小 1)。預設:8
  • 傳回:<readlinePromises.Interface>

readlinePromises.createInterface() 方法會建立新的 readlinePromises.Interface 執行個體。

const readlinePromises = require('node:readline/promises');
const rl = readlinePromises.createInterface({
  input: process.stdin,
  output: process.stdout,
}); 

建立 readlinePromises.Interface 執行個體後,最常見的狀況是監聽 'line' 事件

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

如果這個執行個體的 terminaltrue,則 output 串流將獲得最佳相容性,如果它定義 output.columns 屬性,並且在欄位變更時或變更後發出 output 上的 'resize' 事件(process.stdout 在它是 TTY 時會自動執行此動作)。

使用 completer 函數#

completer 函數將使用者輸入的目前列作為引數,並傳回包含 2 個條目的 Array

  • 包含與完成相符條目的 Array
  • 用於配對的子字串。

例如:[[substr1, substr2, ...], originalsubstring]

function completer(line) {
  const completions = '.help .error .exit .quit .q'.split(' ');
  const hits = completions.filter((c) => c.startsWith(line));
  // Show all completions if none found
  return [hits.length ? hits : completions, line];
} 

completer 函數也可以傳回 <Promise>,或為非同步

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

回呼 API#

類別:readline.Interface#

readline.Interface 類別的執行個體是使用 readline.createInterface() 方法建構的。每個執行個體都與單一 input Readable 串流和單一 output Writable 串流關聯。output 串流用於列印使用者輸入提示,而輸入提示會出現在 input 串流上並從中讀取。

rl.question(query[, options], callback)#
  • query <string> 要寫入 output 的陳述或查詢,附加在提示之前。
  • options <Object>
    • signal <AbortSignal> 選擇性地允許使用 AbortController 取消 question()
  • callback <函式> 呼叫函式,會在回應 query 時呼叫,並帶有使用者的輸入。

rl.question() 方法透過將 query 寫入 output 來顯示,等待使用者在 input 上提供輸入,然後呼叫 callback 函式,並將提供的輸入作為第一個引數傳遞。

呼叫時,如果 input 串流已暫停,rl.question() 會繼續串流。

如果 readline.Interface 是使用 output 設定為 nullundefined 建立的,則不會寫入 query

傳遞給 rl.question()callback 函式不遵循接受 Error 物件或 null 作為第一個引數的典型模式。callback 會呼叫,並將提供的答案作為唯一的引數。

如果在 rl.close() 之後呼叫 rl.question(),將會擲回錯誤。

範例用法

rl.question('What is your favorite food? ', (answer) => {
  console.log(`Oh, so your favorite food is ${answer}`);
}); 

使用 AbortController 取消問題。

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

rl.question('What is your favorite food? ', { signal }, (answer) => {
  console.log(`Oh, so your favorite food is ${answer}`);
});

signal.addEventListener('abort', () => {
  console.log('The food question timed out');
}, { once: true });

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

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

  • stream <stream.Writable>
  • dir <數字>
    • -1:從游標向左
    • 1:從游標向右
    • 0:整行
  • callback <函式> 在作業完成後呼叫。
  • 傳回:<布林> 如果 stream 希望呼叫程式碼等待 'drain' 事件發出後再繼續寫入其他資料,則為 false;否則為 true

readline.clearLine() 方法會清除指定 TTY 串流中由 dir 識別的特定方向的目前行。

readline.clearScreenDown(stream[, callback])#

  • stream <stream.Writable>
  • callback <函式> 在作業完成後呼叫。
  • 傳回:<布林> 如果 stream 希望呼叫程式碼等待 'drain' 事件發出後再繼續寫入其他資料,則為 false;否則為 true

readline.clearScreenDown() 方法會清除給定的 TTY 串流中,從游標目前位置向下開始的部分。

readline.createInterface(options)#

  • options <Object>
    • input <stream.Readable> 要監聽的 Readable 串流。此選項為必要
    • output <stream.Writable> 要將 readline 資料寫入的 Writable 串流。
    • completer <Function> 用於 Tab 自動完成的選用函式。
    • terminal <boolean> 如果 inputoutput 串流應視為 TTY,並寫入 ANSI/VT100 逸出碼,則為 true預設:建立執行個體時檢查 output 串流上的 isTTY
    • history <string[]> 歷程記錄行之初始清單。此選項僅在使用者或內部 output 檢查將 terminal 設為 true 時才有意義,否則歷程記錄快取機制根本不會初始化。預設:[]
    • historySize <number> 保留的最大歷程記錄行數。若要停用歷程記錄,請將此值設為 0。此選項僅在使用者或內部 output 檢查將 terminal 設為 true 時才有意義,否則歷程記錄快取機制根本不會初始化。預設:30
    • removeHistoryDuplicates <boolean> 如果為 true,當新增至歷程記錄清單的新輸入行與舊行重複時,會從清單中移除舊行。預設:false
    • prompt <字串> 要使用的提示字串。預設:'> '
    • crlfDelay <數字> 如果 \r\n 之間的延遲超過 crlfDelay 毫秒,\r\n 都將被視為獨立的行尾輸入。crlfDelay 將被強制轉換為不小於 100 的數字。它可以設定為 Infinity,這種情況下,\r 後接 \n 將始終被視為單一換行符(對於使用 \r\n 行分隔符讀取檔案可能是合理的)。預設:100
    • escapeCodeTimeout <number> readline 會等待字元的時間(以毫秒為單位,在讀取模稜兩可的按鍵順序時,該順序既可以使用到目前為止讀取的輸入,形成完整的按鍵順序,也可以接受其他輸入,完成更長的按鍵順序)。預設值:500
    • tabSize <整數> 標籤等於的空格數(最小 1)。預設:8
    • signal <AbortSignal> 允許使用 AbortSignal 關閉介面。中斷訊號會在內部對介面上呼叫 close
  • 傳回:<readline.Interface>

readline.createInterface() 方法會建立新的 readline.Interface 執行個體。

const readline = require('node:readline');
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
}); 

建立 readline.Interface 執行個體後,最常見的狀況是聆聽 'line' 事件

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

如果這個執行個體的 terminaltrue,則 output 串流將獲得最佳相容性,如果它定義 output.columns 屬性,並且在欄位變更時或變更後發出 output 上的 'resize' 事件(process.stdout 在它是 TTY 時會自動執行此動作)。

使用 stdin 作為輸入建立 readline.Interface 時,程式不會終止,直到收到 EOF 字元。若要退出而不等候使用者輸入,請呼叫 process.stdin.unref()

completer 函數的使用#

completer 函數將使用者輸入的目前列作為引數,並傳回包含 2 個條目的 Array

  • 包含與完成相符條目的 Array
  • 用於配對的子字串。

例如:[[substr1, substr2, ...], originalsubstring]

function completer(line) {
  const completions = '.help .error .exit .quit .q'.split(' ');
  const hits = completions.filter((c) => c.startsWith(line));
  // Show all completions if none found
  return [hits.length ? hits : completions, line];
} 

如果 completer 函數接受兩個參數,則可以非同步呼叫

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

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

readline.cursorTo() 方法將游標移至給定 TTY stream 中指定的位置。

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

readline.moveCursor() 方法將游標相對於其在給定 TTY stream 中的目前位置進行移動。

readline.emitKeypressEvents(stream[, interface])#

readline.emitKeypressEvents() 方法會讓給定的 Readable stream 開始發出與接收輸入相應的 'keypress' 事件。

interface 選擇性地指定一個 readline.Interface 實例,當偵測到貼上輸入時,此實例會停用自動完成。

如果 streamTTY,則它必須處於原始模式。

如果 input 是終端機,則任何 readline 實例都會在 input 上自動呼叫此方法。關閉 readline 實例不會阻止 input 發出 'keypress' 事件。

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

範例:微型 CLI#

以下範例說明如何使用 readline.Interface 類別來實作小型命令列介面

const readline = require('node:readline');
const rl = readline.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);
}); 

範例:逐行讀取檔案串流#

readline 的常見使用案例是逐行使用輸入檔案。最簡單的方法是利用 fs.ReadStream API 以及 for await...of 迴圈

const fs = require('node:fs');
const readline = require('node:readline');

async function processLineByLine() {
  const fileStream = fs.createReadStream('input.txt');

  const rl = readline.createInterface({
    input: fileStream,
    crlfDelay: Infinity,
  });
  // Note: we use the crlfDelay option to recognize all instances of CR LF
  // ('\r\n') in input.txt as a single line break.

  for await (const line of rl) {
    // Each line in input.txt will be successively available here as `line`.
    console.log(`Line from file: ${line}`);
  }
}

processLineByLine(); 

或者,可以使用 'line' 事件

const fs = require('node:fs');
const readline = require('node:readline');

const rl = readline.createInterface({
  input: fs.createReadStream('sample.txt'),
  crlfDelay: Infinity,
});

rl.on('line', (line) => {
  console.log(`Line from file: ${line}`);
}); 

目前,for await...of 迴圈可能會慢一些。如果 async / await 流程和速度都很重要,則可以套用混合方法

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) => {
      // Process the line.
    });

    await once(rl, 'close');

    console.log('File processed.');
  } catch (err) {
    console.error(err);
  }
})(); 

TTY 鍵盤繫結#

鍵盤繫結 說明 注意事項
Ctrl+Shift+Backspace 刪除左邊一行 不適用於 Linux、Mac 和 Windows
Ctrl+Shift+Delete 刪除右邊一行 不適用於 Mac
Ctrl+C 發出 SIGINT 或關閉 readline 實例
Ctrl+H 刪除左邊
Ctrl+D 刪除右邊或在目前行為空值/EOF 時關閉 readline 實例 不適用於 Windows
Ctrl+U 從目前位置刪除到行首
Ctrl+K 從目前位置刪除到行尾
Ctrl+Y Yank(還原)先前刪除的文字 僅適用於使用 Ctrl+UCtrl+K 刪除的文字
Meta+Y 在先前刪除的文字之間循環 僅在最後按下的按鍵為 Ctrl+YMeta+Y 時可用
Ctrl+A 移至行首
Ctrl+E 移至行尾
Ctrl+B 向後一個字元
Ctrl+F 向前一個字元
Ctrl+L 清除畫面
Ctrl+N 下一項歷史記錄
Ctrl+P 上一項歷史記錄
Ctrl+- 復原上一次變更 任何發出鍵碼 0x1F 的按鍵都會執行此動作。在許多終端機中,例如 xterm,此鍵碼會繫結至 Ctrl+-
Ctrl+6 重做上一次變更 許多終端機沒有預設的重做按鍵。我們選擇鍵碼 0x1E 來執行重做。在 xterm 中,預設會將其繫結至 Ctrl+6
Ctrl+Z 將正在執行的程序移至背景。輸入 fg 並按下 Enter 以返回。 不適用於 Windows
Ctrl+WCtrl +Backspace 向後刪除至字詞邊界 Ctrl+Backspace 在 Linux、Mac 和 Windows 上無法使用
Ctrl+Delete 向前刪除至字詞邊界 不適用於 Mac
Ctrl+向左箭頭Meta+B 字詞向左 Ctrl+向左箭頭 在 Mac 上無法使用
Ctrl+向右箭頭Meta+F 字詞向右 Ctrl+向右箭頭 在 Mac 上無法使用
Meta+DMeta +Delete 刪除字詞向右 Meta+Delete 在 Windows 上無法使用
Meta+Backspace 刪除字詞向左 不適用於 Mac