Getting values from Deno stdin
Asked Answered
D

9

21

How can we get values from standard input in Deno?

I don't know how to use Deno.stdin.

An example would be appreciated.

Dissonancy answered 19/9, 2019 at 22:23 Comment(3)
It's as easy as this single line: const stdin = new TextDecoder().decode(await Deno.readAll(Deno.stdin));Tamarah
Since writing the comment above, Deno.readAll has been deprecated and moved to deno.land/std/io/util.ts as readAll.Tamarah
As for now, Deno.readAll has been moved to deno.land/std/streams/conversion.ts. Deno.readAll will be removed in Deno 2.0.Amazonas
G
21

We can use prompt in deno.

const input = prompt('Please enter input');

In case input has to be a number. We can use Number.parseInt(input);

Gujranwala answered 6/3, 2021 at 17:29 Comment(0)
L
10

Deno.stdin is of type File, thus you can read from it by providing a Uint8Array as buffer and call Deno.stdin.read(buf)

window.onload = async function main() {
  const buf = new Uint8Array(1024);
  /* Reading into `buf` from start.
   * buf.subarray(0, n) is the read result.
   * If n is instead Deno.EOF, then it means that stdin is closed.
   */
  const n = await Deno.stdin.read(buf); 
  if (n == Deno.EOF) {
    console.log("Standard input closed")
  } else {
    console.log("READ:", new TextDecoder().decode(buf.subarray(0, n)));
  }
}
Lozada answered 20/9, 2019 at 18:32 Comment(3)
This doesn't necessarily read a (whole) single line. For example, when stdin is redirected from a file, it will read a large block not just one line. If the line is very long, it will read less than the whole line. Also it might not necessarily read entire utf-8 runes, so it could break the text encoding.Freezedrying
Property 'EOF' does not exist on type 'typeof Deno', deno 1.34.3Tortoiseshell
I think we must use null now instead of Deno.EOF: github.com/denoland/deno/pull/4953Tortoiseshell
S
9

A simple confirmation which can be answered with y or n:

import { readLines } from "https://deno.land/std/io/buffer.ts";

async function confirm(question) {
    console.log(question);

    for await (const line of readLines(Deno.stdin)) {
        if (line === "y") {
            return true;
        } else if (line === "n") {
            return false;
        }
    }
}

const answer = await confirm("Do you want to go on? [y/n]");

Or if you want to prompt the user for a string:

import { readLines } from "https://deno.land/std/io/buffer.ts";

async function promptString(question) {
    console.log(question);

    for await (const line of readLines(Deno.stdin)) {
        return line;
    }
}

const userName = await promptString("Enter your name:");
Salmonberry answered 15/5, 2020 at 21:56 Comment(3)
unfortunately, not applicable to Deno 1.0 anymoreHedrick
@Hedrick it was using 0.51.0 of std, which is already deprecated. bumped the version in the answer, it should be working now.Mccaskill
unfortunately, not applicable to Deno 1.4 anymore (:/)Hedrick
P
4

I have a solution 100% pure Deno, but not intensively tested

async function ask(question: string = '', stdin = Deno.stdin, stdout = Deno.stdout) {
  const buf = new Uint8Array(1024);

  // Write question to console
  await stdout.write(new TextEncoder().encode(question));

  // Read console's input into answer
  const n = <number>await stdin.read(buf);
  const answer = new TextDecoder().decode(buf.subarray(0, n));

  return answer.trim();
}

const answer = await ask(`Tell me your name? `);
console.log(`Your name is ${answer}`);

Parts of the above code was taken from answer of Kevin Qian

Piccoloist answered 5/4, 2020 at 20:22 Comment(1)
This doesn't necessarily read whole lines, see my other comment.Freezedrying
H
2

I would suggest using the Input-Deno module. This is an example from the docs:

// For a single question:
const input = new InputLoop();
const nodeName = await input.question('Enter the label for the node:');
        
// output:
        
// Enter the label for the node:
        
// Return Value:
// 'a'
Hiding answered 13/8, 2020 at 10:56 Comment(0)
N
1

With the switch from Reader to the web standard Stream API, Deno.stdin has a readable field which is a ReadableStream. Input from stdin can then be read fully as text with:

const input = await new Response(Deno.stdin.readable).text();

Similarly, if input is json, it can be read accordingly:

const input = await new Response(Deno.stdin.readable).json();

The more correct way to do it is a little more verbose:

for await (
  const text of Deno.stdin.readable.pipeThrough(new TextDecoderStream())
) {
  // do something with the text
}
Nash answered 20/3, 2024 at 19:59 Comment(0)
D
0

I have a small terminal sample to test with the Deno TCP echo server. It's something like:

private input = new TextProtoReader(new BufReader(Deno.stdin));
while (true) {
    const line = await this.input.readLine();
    if (line === Deno.EOF) {
        console.log(red('Bye!'));
        break;
    } else {
        // display the line
    }
}

The full project is on Github.

Dekaliter answered 12/2, 2020 at 6:40 Comment(0)
F
0

To read all of the input to count lines and words:

import { toArrayBuffer } from "https://deno.land/[email protected]/streams/mod.ts";

const inputData = new TextDecoder().decode(
  await toArrayBuffer(Deno.stdin.readable),
);

// https://mcmap.net/q/181018/-how-to-count-the-number-of-lines-of-a-string-in-javascript
const numberOfLines = inputData.split(/\r\n|\r|\n/).length;

// https://mcmap.net/q/158650/-counting-words-in-string
const numberOfWords = inputData.trim().split(/\s+/).length;

console.log(numberOfLines);
console.log(numberOfWords);

This would be useful if you want to create a script that e.g. reads a file content from stdin:

$ cat some_file.txt | util.ts
28
70
Fishhook answered 10/1, 2024 at 23:3 Comment(0)
T
-1

Use

const userInput = window.prompt("type here: ")

window.prompt on deno.land

Toweling answered 12/1, 2024 at 13:8 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.