Readline#

安定性: 2 - Stable

ソースコード: lib/readline.js

node:readline モジュールは、Readable ストリーム (例えば process.stdin) からデータを一行ずつ読み込むためのインターフェースを提供します。

Promise ベースの 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();
});

このコードが実行されると、readline.Interfaceinput ストリームでデータを受信するのを待つため、インターフェースが閉じられるまで Node.js アプリケーションは終了しません。

クラス: InterfaceConstructor#

InterfaceConstructor クラスのインスタンスは readlinePromises.createInterface() または readline.createInterface() メソッドを使って構築されます。各インスタンスは、単一の input Readable ストリームと単一の output Writable ストリームに関連付けられています。output ストリームは、input ストリームに到着し、そこから読み取られるユーザー入力のためのプロンプトを表示するために使用されます。

イベント: 'close'#

'close' イベントは、以下のいずれかが発生したときに発行されます。

  • rl.close() メソッドが呼び出され、InterfaceConstructor インスタンスが inputoutput ストリームの制御を解放したとき。
  • input ストリームが 'end' イベントを受け取ったとき。
  • input ストリームが送信終了(EOT)を知らせる Ctrl+D を受け取ったとき。
  • input ストリームが SIGINT を知らせる Ctrl+C を受け取り、かつ InterfaceConstructor インスタンスに 'SIGINT' イベントリスナーが登録されていないとき。

リスナー関数は引数なしで呼び出されます。

'close' イベントが発行されると、InterfaceConstructor インスタンスは終了します。

イベント: 'line'#

'line' イベントは、input ストリームが改行入力 (\n, \r, または \r\n) を受け取るたびに発行されます。これは通常、ユーザーが Enter または Return を押したときに発生します。

'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'#

'resume' イベントは、input ストリームが再開されるたびに発行されます。

リスナー関数は引数なしで呼び出されます。

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

イベント: 'SIGCONT'#

'SIGCONT' イベントは、以前に Ctrl+Z (すなわち SIGTSTP) を使ってバックグラウンドに移動した Node.js プロセスが、fg(1p) を使ってフォアグラウンドに戻されたときに発行されます。

SIGTSTP リクエストの *前* に input ストリームが一時停止されていた場合、このイベントは発行されません。

リスナー関数は引数なしで呼び出されます。

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

'SIGCONT' イベントは Windows ではサポートされて *いません*。

イベント: 'SIGINT'#

'SIGINT' イベントは、input ストリームが Ctrl+C 入力 (通常 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'#

'SIGTSTP' イベントは、input ストリームが Ctrl+Z 入力 (通常 SIGTSTP として知られる) を受け取ったときに発行されます。input ストリームが SIGTSTP を受け取ったときに 'SIGTSTP' イベントリスナーが登録されていない場合、Node.js プロセスはバックグラウンドに送られます。

プログラムが fg(1p) を使って再開されると、'pause''SIGCONT' イベントが発行されます。これらは input ストリームを再開するために使用できます。

プロセスがバックグラウンドに送られる前に input が一時停止されていた場合、'pause''SIGCONT' イベントは発行されません。

リスナー関数は引数なしで呼び出されます。

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

'SIGTSTP' イベントは Windows ではサポートされて *いません*。

rl.close()#

rl.close() メソッドは InterfaceConstructor インスタンスを閉じ、inputoutput ストリームの制御を解放します。呼び出されると、'close' イベントが発行されます。

rl.close() を呼び出しても、InterfaceConstructor インスタンスによる他のイベント ('line' を含む) の発行が直ちに停止するわけではありません。

rl[Symbol.dispose]()#

rl.close() のエイリアスです。

rl.pause()#

rl.pause() メソッドは input ストリームを一時停止し、後で必要に応じて再開できるようにします。

rl.pause() を呼び出しても、InterfaceConstructor インスタンスによる他のイベント ('line' を含む) の発行が直ちに停止するわけではありません。

rl.prompt([preserveCursor])#

  • preserveCursor <boolean> true の場合、カーソル位置が 0 にリセットされるのを防ぎます。

rl.prompt() メソッドは、InterfaceConstructor インスタンスに設定された promptoutput の新しい行に書き込み、ユーザーが入力を行うための新しい場所を提供します。

rl.prompt() を呼び出すと、一時停止されていた場合、input ストリームが再開されます。

InterfaceConstructoroutputnull または undefined に設定して作成された場合、プロンプトは書き込まれません。

rl.resume()#

rl.resume() メソッドは、一時停止されている場合に input ストリームを再開します。

rl.setPrompt(prompt)#

rl.setPrompt() メソッドは、rl.prompt() が呼び出されるたびに output に書き込まれるプロンプトを設定します。

rl.getPrompt()#

  • 戻り値: <string> 現在のプロンプト文字列

rl.getPrompt() メソッドは、rl.prompt() で使用される現在のプロンプトを返します。

rl.write(data[, key])#

rl.write() メソッドは data または key によって識別されるキーシーケンスを output に書き込みます。key 引数は、outputTTY テキストターミナルである場合にのみサポートされます。キーの組み合わせのリストについては TTY キーバインディング を参照してください。

key が指定された場合、data は無視されます。

rl.write() を呼び出すと、一時停止されていた場合、input ストリームが再開されます。

InterfaceConstructoroutputnull または undefined に設定して作成された場合、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 オブジェクトの非同期反復が可能になります。

入力ストリームのエラーは転送されません。

ループが breakthrow、または return で終了した場合、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#

node によって処理されている現在の入力データです。

これは、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()#

  • 戻り値: <Object>
    • rows <number> カーソルが現在置かれているプロンプトの行
    • cols <number> カーソルが現在置かれている画面の列

入力プロンプト+文字列に関連するカーソルの実際の位置を返します。長い入力(折り返し)文字列や複数行のプロンプトも計算に含まれます。

Promises API#

クラス: readlinePromises.Interface#

readlinePromises.Interface クラスのインスタンスは readlinePromises.createInterface() メソッドを使って構築されます。各インスタンスは、単一の input Readable ストリームと単一の output Writable ストリームに関連付けられています。output ストリームは、input ストリームに到着し、そこから読み取られるユーザー入力のためのプロンプトを表示するために使用されます。

rl.question(query[, options])#
  • query <string> output に書き込む文または質問。プロンプトの前に付加されます。
  • options <Object>
    • signal <AbortSignal> オプションで、AbortSignal を使用して question() をキャンセルできます。
  • 戻り値: <Promise> query に応答したユーザーの入力で解決される Promise。

rl.question() メソッドは、queryoutput に書き込むことで表示し、ユーザー入力が input で提供されるのを待ち、提供された入力を最初の引数として callback 関数を呼び出します。

rl.question() を呼び出すと、一時停止されていた場合、input ストリームが再開されます。

readlinePromises.Interfaceoutputnull または undefined に設定して作成された場合、query は書き込まれません。

rl.close() の後に question が呼び出されると、拒否された promise を返します。

使用例

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: 行全体
  • 戻り値: this

rl.clearLine() メソッドは、関連付けられた stream の現在の行を dir で指定された方向にクリアするアクションを、保留中のアクションの内部リストに追加します。コンストラクターに autoCommit: true が渡されていない限り、このメソッドの効果を確認するには rl.commit() を呼び出してください。

rl.clearScreenDown()#
  • 戻り値: this

rl.clearScreenDown() メソッドは、関連付けられたストリームをカーソルの現在位置から下に向かってクリアするアクションを、保留中のアクションの内部リストに追加します。コンストラクターに autoCommit: true が渡されていない限り、このメソッドの効果を確認するには rl.commit() を呼び出してください。

rl.commit()#

rl.commit() メソッドは、保留中のすべてのアクションを関連付けられた stream に送信し、保留中のアクションの内部リストをクリアします。

rl.cursorTo(x[, y])#

rl.cursorTo() メソッドは、カーソルを関連付けられた stream 内の指定された位置に移動するアクションを、保留中のアクションの内部リストに追加します。コンストラクターに autoCommit: true が渡されていない限り、このメソッドの効果を確認するには rl.commit() を呼び出してください。

rl.moveCursor(dx, dy)#

rl.moveCursor() メソッドは、カーソルを関連付けられた stream 内の現在位置から *相対的に* 移動するアクションを、保留中のアクションの内部リストに追加します。コンストラクターに autoCommit: true が渡されていない限り、このメソッドの効果を確認するには rl.commit() を呼び出してください。

rl.rollback()#
  • 戻り値: this

rl.rollback メソッドは、保留中のアクションを関連付けられた stream に送信せずに内部リストからクリアします。

readlinePromises.createInterface(options)#

  • options <Object>
    • input <stream.Readable> リッスンする Readable ストリーム。このオプションは *必須* です。
    • output <stream.Writable> readline データを書き込む Writable ストリーム。
    • completer <Function> タブのオートコンプリートに使用されるオプションの関数。
    • terminal <boolean> inputoutput ストリームを TTY のように扱い、ANSI/VT100 エスケープコードを書き込む場合は trueデフォルト: インスタンス化時に output ストリームで isTTY をチェックします。
    • history <string[]> 履歴行の初期リスト。このオプションは、terminal がユーザーによって、または内部の output チェックによって true に設定されている場合にのみ意味があります。そうでない場合、履歴キャッシュメカニズムはまったく初期化されません。デフォルト: []
    • historySize <number> 保持される履歴行の最大数。履歴を無効にするには、この値を 0 に設定します。このオプションは、terminal がユーザーによって、または内部の output チェックによって true に設定されている場合にのみ意味があります。そうでない場合、履歴キャッシュメカニズムはまったく初期化されません。デフォルト: 30
    • removeHistoryDuplicates <boolean> true の場合、履歴リストに追加された新しい入力行が古いものと重複する場合、古い行をリストから削除します。デフォルト: false
    • prompt <string> 使用するプロンプト文字列。デフォルト: '> '
    • crlfDelay <number> \r\n の間の遅延が crlfDelay ミリ秒を超える場合、\r\n の両方が別々の改行入力として扱われます。crlfDelay100 以上の数値に強制されます。Infinity に設定することもでき、その場合、\r に続く \n は常に単一の改行と見なされます (これは \r\n 行区切り文字でファイルを読み取る場合に合理的かもしれません)。デフォルト: 100
    • escapeCodeTimeout <number> 曖昧なキーシーケンス (これまでの入力で完全なキーシーケンスを形成でき、かつより長いキーシーケンスを完成させるため追加の入力を受け取ることができるもの) を読み取る際に、readlinePromises が文字を待機する時間 (ミリ秒単位)。デフォルト: 500
    • tabSize <integer> タブが等しいスペースの数 (最小 1)。デフォルト: 8
    • signal <AbortSignal> AbortSignal を使用してインターフェースを閉じることができます。
  • 戻り値: <readlinePromises.Interface>

readlinePromises.createInterface() メソッドは、新しい 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,
});

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 <Function> query に応答したユーザーの入力で呼び出されるコールバック関数。

rl.question() メソッドは、queryoutput に書き込むことで表示し、ユーザー入力が input で提供されるのを待ち、提供された入力を最初の引数として callback 関数を呼び出します。

rl.question() を呼び出すと、一時停止されていた場合、input ストリームが再開されます。

readline.Interfaceoutputnull または undefined に設定して作成された場合、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 <number>
    • -1: カーソルから左側
    • 1: カーソルから右側
    • 0: 行全体
  • callback <Function> 操作が完了したときに呼び出されます。
  • 戻り値: <boolean> stream が、追加のデータを書き続ける前に 'drain' イベントが発行されるのを呼び出し元コードに待機させたい場合は false。それ以外は true

readline.clearLine() メソッドは、指定された TTY ストリームの現在の行を dir で指定された方向にクリアします。

readline.clearScreenDown(stream[, callback])#

  • stream <stream.Writable>
  • callback <Function> 操作が完了したときに呼び出されます。
  • 戻り値: <boolean> stream が、追加のデータを書き続ける前に 'drain' イベントが発行されるのを呼び出し元コードに待機させたい場合は false。それ以外は true

readline.clearScreenDown() メソッドは、指定された TTY ストリームをカーソルの現在位置から下に向かってクリアします。

readline.createInterface(options)#

  • options <Object>
    • input <stream.Readable> リッスンする Readable ストリーム。このオプションは *必須* です。
    • output <stream.Writable> readline データを書き込む Writable ストリーム。
    • completer <Function> タブのオートコンプリートに使用されるオプションの関数。
    • terminal <boolean> inputoutput ストリームを TTY のように扱い、ANSI/VT100 エスケープコードを書き込む場合は trueデフォルト: インスタンス化時に output ストリームで isTTY をチェックします。
    • history <string[]> 履歴行の初期リスト。このオプションは、terminal がユーザーによって、または内部の output チェックによって true に設定されている場合にのみ意味があります。そうでない場合、履歴キャッシュメカニズムはまったく初期化されません。デフォルト: []
    • historySize <number> 保持される履歴行の最大数。履歴を無効にするには、この値を 0 に設定します。このオプションは、terminal がユーザーによって、または内部の output チェックによって true に設定されている場合にのみ意味があります。そうでない場合、履歴キャッシュメカニズムはまったく初期化されません。デフォルト: 30
    • removeHistoryDuplicates <boolean> true の場合、履歴リストに追加された新しい入力行が古いものと重複する場合、古い行をリストから削除します。デフォルト: false
    • prompt <string> 使用するプロンプト文字列。デフォルト: '> '
    • crlfDelay <number> \r\n の間の遅延が crlfDelay ミリ秒を超える場合、\r\n の両方が別々の改行入力として扱われます。crlfDelay100 以上の数値に強制されます。Infinity に設定することもでき、その場合、\r に続く \n は常に単一の改行と見なされます (これは \r\n 行区切り文字でファイルを読み取る場合に合理的かもしれません)。デフォルト: 100
    • escapeCodeTimeout <number> 曖昧なキーシーケンス (これまでの入力で完全なキーシーケンスを形成でき、かつより長いキーシーケンスを完成させるため追加の入力を受け取ることができるもの) を読み取る際に、readline が文字を待機する時間 (ミリ秒単位)。デフォルト: 500
    • tabSize <integer> タブが等しいスペースの数 (最小 1)。デフォルト: 8
    • signal <AbortSignal> AbortSignal を使用してインターフェースを閉じることができます。シグナルを中止すると、内部的にインターフェースで close が呼び出されます。
  • 戻り値: <readline.Interface>

readline.createInterface() メソッドは、新しい 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,
});

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 関数が 2 つの引数を受け入れる場合、非同期に呼び出すことができます。

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

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

  • stream <stream.Writable>
  • x <number>
  • y <number>
  • callback <Function> 操作が完了したときに呼び出されます。
  • 戻り値: <boolean> stream が、追加のデータを書き続ける前に 'drain' イベントが発行されるのを呼び出し元コードに待機させたい場合は false。それ以外は true

readline.cursorTo() メソッドは、指定された TTY stream 内でカーソルを指定された位置に移動します。

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

  • stream <stream.Writable>
  • dx <number>
  • dy <number>
  • callback <Function> 操作が完了したときに呼び出されます。
  • 戻り値: <boolean> stream が、追加のデータを書き続ける前に 'drain' イベントが発行されるのを呼び出し元コードに待機させたい場合は false。それ以外は true

readline.moveCursor() メソッドは、指定された TTY stream 内でカーソルを現在位置から *相対的に* 移動します。

readline.emitKeypressEvents(stream[, interface])#

readline.emitKeypressEvents() メソッドは、指定された Readable ストリームに、受信した入力に対応する 'keypress' イベントを発行させ始めます。

オプションで、interface はコピー&ペーストされた入力が検出されたときにオートコンプリートが無効になる readline.Interface インスタンスを指定します。

streamTTY である場合、それは raw モードでなければなりません。

これは、input がターミナルである場合、その input 上の任意の readline インスタンスによって自動的に呼び出されます。readline インスタンスを閉じても、input'keypress' イベントを発行するのは停止しません。

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

例: 小さな CLI#

次の例は、readline.Interface クラスを使用して小さなコマンドラインインターフェースを実装する方法を示しています。

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);
});

例: ファイルストリームを一行ずつ読み込む#

readline の一般的な使用例は、入力ファイルを一度に一行ずつ消費することです。それを行う最も簡単な方法は、fs.ReadStream API と 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,
  });
  // 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();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,
  });
  // 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' イベントを使用することもできます。

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(`Line from 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(`Line from file: ${line}`);
});

現在、for await...of ループは少し遅くなる可能性があります。async / await のフローと速度の両方が不可欠な場合は、混合アプローチを適用できます。

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

    await once(rl, 'close');

    console.log('File processed.');
  } 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) => {
      // 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 右側を削除 (デリート)、または現在の行が空の場合は readline インスタンスを閉じる / EOF Windows では動作しません
Ctrl+U 現在位置から行頭まで削除
Ctrl+K 現在位置から行末まで削除
Ctrl+Y ヤンク (以前に削除されたテキストを貼り付け) Ctrl+U または Ctrl+K で削除されたテキストでのみ動作します
Meta+Y 以前に削除されたテキストを順番に表示 最後のキーストロークが Ctrl+Y または Meta+Y の場合のみ利用可能
Ctrl+A 行頭に移動
Ctrl+E 行末に移動
Ctrl+B 1文字戻る
Ctrl+F 1文字進む
Ctrl+L 画面をクリア
Ctrl+N 次の履歴項目
Ctrl+P 前の履歴項目
Ctrl+- 前の変更を元に戻す キーコード 0x1F を発行するキーストロークはこのアクションを実行します。多くのターミナル (例: xterm) では、これは Ctrl+- にバインドされています。
Ctrl+6 前の変更をやり直す 多くのターミナルにはデフォルトのやり直しキーストロークがありません。やり直しを実行するためにキーコード 0x1E を選択しました。xterm では、デフォルトで Ctrl+6 にバインドされています。
Ctrl+Z 実行中のプロセスをバックグラウンドに移動します。fg と入力して Enter を押すと戻ります。 Windows では動作しません
Ctrl+W または Ctrl +Backspace 単語の境界まで後方に削除 Ctrl+Backspace は Linux, Mac, Windows では動作しません
Ctrl+Delete 単語の境界まで前方に削除 Mac では動作しません
Ctrl+Left arrow または Meta+B 左に一単語移動 Ctrl+Left arrow は Mac では動作しません
Ctrl+Right arrow または Meta+F 右に一単語移動 Ctrl+Right arrow は Mac では動作しません
Meta+D または Meta +Delete 右側の単語を削除 Meta+Delete は Windows では動作しません
Meta+Backspace 左側の単語を削除 Mac では動作しません