at backyard

Color my life with the chaos of trouble.

Denoの標準入力で1文字ずつの入力に対して処理を動かしたい

昨日Node.jsでキーボードで一文字打つたびに処理を実行するための備忘録を書いた。

shinshin86.hateblo.jp

今回これのDeno版を書いてみた。

といっても、Node.jsとは少々コードが変わっている。
(実際、手探り手探りの実装という形である)

Denoでキーストロークを読むためのコード

Deno.setRaw(0, true);

const bufferSize = 16;
const buf = new Uint8Array(bufferSize);

let output = "";

while (true) {
  const nread = await Deno.stdin.read(buf);

  if (nread === null) {
    console.log("nread is null");
    console.log("Exit");
    break;
  }

  // Ctrl + C を押したら終了
  if (buf && buf[0] === 0x03) {
    console.log("Ctrl+C");
    console.log("Exit");
    break;
  }

  // Enterキーを押した場合、outputのテキストを表示して処理を終了
  if (buf && buf[0] === 13) {
    console.log("Ouput: ", output);
    break;
  }

  const text = new TextDecoder().decode(buf.subarray(0, nread));
  output = output + text;
  console.log(output);
}

Deno.setRaw(0, false);

Node.jsのときに用意されていたprocess.stdin.setRawMode(true); のようなものがDenoにも用意されているのでこちらを利用する。

ただし、これを利用する場合、--unstable オプションを付けた形で実行する必要がある。

実際に実行する場合は下記のコマンドを叩く。

deno run --unstable sample.ts

上のコードの挙動だが、

  • 1文字ずつの入力に対して変数 output に入力した文字列が蓄積されていく
  • Ctrl + C で処理を抜ける
  • Enterキーを押すことで同じく処理を抜ける(こちらは決定的なニュアンスを想定)
  • 変数 nread がどういうときに null を返すのかまでは追えていないが、 null を返す可能性があるので、一応そちらの処理も入れている。
  • bufferSize が16なのは適当
  • 英語入力の場合、1文字ずつの入力の度に処理が動くが、日本語入力のような場合、例えば こんにちは と入力してEnterキーを押すような場合、こんにちは という文字が処理されていく。

以上、備忘録でした。