Deno: Add sync version of std/io readLines

Created on 18 Feb 2019  路  15Comments  路  Source: denoland/deno

It would be useful to provide a function that can read a line of input from stdin that has a simple interface. It would probably good to support both async and sync versions, something like

const name: string = await Deno.readLine('What is your name? ');
const age: string = Deno.readLineSync('What is your age? ');

I think readLine might be too close to the file functions, so maybe something like getInput or ttyReadLine

feat good first issue l-typescript std

Most helpful comment

It's now possible to do that using readLines from std/io/bufio.ts

import { readLines } from "https://deno.land/[email protected]/io/bufio.ts";

async function main() {
   for await (const line of readLines(Deno.stdin)) {
      console.log("read line", line);
  }
}

console.log("reading lines from stdin");
main();
$ deno index.ts
Compile file:///Users/biwanczuk/dev/deno/index.ts
reading lines from stdin
asdf
read line asdf
qwer
read line qwer
tryu
read line tryu

All 15 comments

I believe this could be implemented in pure TS with Deno.stdin, so we should probably put this in deno_std

I made an async implementation of readLine named input that uses a method lines which is an iterator that yields lines from an input source. Here's an example of it being used. I think I'll make a pull request to add it to Deno's std lib, but I think I want to make a synchronous version first. The only thing that I need first is a version of BufReader (from denoland/deno_std/io/bufio.ts) that is synchronous.

It's now possible to do that using readLines from std/io/bufio.ts

import { readLines } from "https://deno.land/[email protected]/io/bufio.ts";

async function main() {
   for await (const line of readLines(Deno.stdin)) {
      console.log("read line", line);
  }
}

console.log("reading lines from stdin");
main();
$ deno index.ts
Compile file:///Users/biwanczuk/dev/deno/index.ts
reading lines from stdin
asdf
read line asdf
qwer
read line qwer
tryu
read line tryu

I'd really appreciate having a synchronous version like johnsonjo4531 suggested. I'll just put that out there. :)

Curious if there's any interest in having a synchronous version of BufReader? To enable a synchronous implementation of readLine?

Yes having a synchronous version would be useful. It seems to me like it would unfortunately require a lot of duplicated code...

I'd like to work on this issue (synchronous version of BufReader to enable a synchronous implementation of readLine).

I actually needed this feature, so I've been toying/working on a proof of concept.

It does require a bit of duplicated code. I think there's ways to reduce the duplicate code but I'm not sure it's practical.

Thoughts?

I have some thoughts on one way this could be done although I'm not sold on them either at the moment and not sure if they are practical or not as I'm not sure how far reaching changes would be for it. I recently read a tweet about this. Apparently babel/core deduplicates async and sync code with generators (reference). After some searching it appears babel uses a package called gensync. Gensync isn't a perfect fit for this scenario as far as I'm aware though, because it doesn't out of the box wrap async generators only async functions and sync functions, but I believe it might be possible to wrap the promise based api with the asyncIterator protocol.

While it might be worth it to go the generator route to not duplicate code, it does seem like it could come with more complexity and unseen caveats, and at the moment I'm not sure how much added complexity it adds because I have not ever used the library (this is my first time looking into it). I'm definitely going to look more into this library and try to report some findings. We should probably get a deno maintainer's thoughts on this matter though at the same time. Something similar to gensync could be put into deno std to help finish this if the deno team thought it would be good to go the generator route (although maybe it's best deno tries to hide the gensync implementation from the public much like babel does, so std might not be the right spot.).

You can look through some of the examples of gensync used throughout babel/core if your curious on how it would be used. Also some may want to look at the main pull-request that put gensync into babel/core, because it has added information on how it affected babel's code base.

Thanks for the references! That's really interesting. Definitely would like to know deno maintainer's thoughts on this.

I wonder what their thoughts are on having duplicated code for this one feature for now, and the possibility of gensync which could be useful here and elsewhere in future refactoring and de-duplication of a/sync versions of code.

I may have been a bit rash suggesting gensync so soon because I know for sure it does deduplication of sync generators to async functions, but I'm unsure how much work it would take to make gensync do sync generators to async generators deduplication, or whether that's even possible...

I'll definitely have to keep you updated if I figure out more about gensync (whether it applies well in this scenario), but as for now I think duplicating the code is probably the right choice.

what was done regarding this?

Well I actually needed this feature for work, so I've done it and am using it. Went the path of having duplicated code. Don't know what deno maintainer's thoughts are on having duplicated code, but perhaps I should get motivated on making a PR so it can be discussed?

Looked at gensync possibility but don't think it'll work for a/sync functions.

@ccheng feel free to open a PR - it's fine to duplicate code for sync version.

Seeing that the stdlib is heavily inspired by go, I'd recommend a similar approach:

scanner := bufio.NewReader(os.Stdin)
scanner.Scan() // advance in input
line := scanner.Text() // get the input

@fr3fou Yes we ideally would have code exactly like that but in TS.

Could this not be achieved by using the new prompts feature?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

watilde picture watilde  路  3Comments

JosephAkayesi picture JosephAkayesi  路  3Comments

ry picture ry  路  3Comments

davidbarratt picture davidbarratt  路  3Comments

doutchnugget picture doutchnugget  路  3Comments