簡単に使えますが 単にループで読み取るだけだとプロンプトは自動で出力されません
import readline from "node:readline"
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
})
for await (const line of rl) {
console.log({ line })
}
これを実行して文字を入力すると エンターを押すたびに { line: "入力値" } のようなのが表示されます
user@DESKTOP03 ~> node rl.js
a
{ line: 'a' }
123
{ line: '123' }
入力するとき何も表示されていないので入力していい状態なのか分かりづらいです
createInterface の prompt の初期値は "> " になっているので紛らわしいのですが 手動で prompt メソッドを呼び出さないとプロンプトは出力されません
また output を標準出力に指定していないと prompt メソッドを呼び出しても画面に表示できません
こうすることで表示されます
import readline from "node:readline"
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
})
rl.prompt()
for await (const line of rl) {
console.log({ line })
rl.prompt()
}
user@DESKTOP03 ~> node rl.js
> 1
{ line: '1' }
> xx
{ line: 'xx' }
> ⏎
ただこれだと prompt の呼び出しが分かれますし なんか気持ち悪いです
自分でこれを書きたくないし 自動で内部的にやってほしいものなので asyncIterator を置き換えることにしました
[auto-prompt.js]
const org_async_iterator = Symbol("org-async-iterator")
async function* asyncIterator(...args) {
this.prompt()
for await (const item of this[org_async_iterator].call(this, ...args)) {
yield item
this.prompt()
}
}
const autoPrompt = (rl) => {
rl[org_async_iterator] = rl[Symbol.asyncIterator]
rl[Symbol.asyncIterator] = asyncIterator
}
export default autoPrompt
import readline from "node:readline"
import autoPrompt from "./auto-prompt.js"
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
})
autoPrompt(rl)
for await (const line of rl) {
console.log({ line })
}
user@DESKTOP03 ~> node rl.js
> foo
{ line: 'foo' }
> bar
{ line: 'bar' }
> ⏎
autoPrompt 側は仕方ないとして 普段使う部分ではスッキリと書けます
標準入力を使うならこの使い方で十分そうですが 全インスタンスに反映させるなら Interface の prototype の方を書き換えることもできます
autoPrompt(readline.Interface.prototype)