-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Read one byte from Deno.stdin without hitting ENTER. #3614
Comments
No, not right now. This is a good point though - it's not possible due to how stdin is implemented internally. We use For files we also read line by line rather than char by char, so at least this behaviour is consistent across readers. For reference, Go also does not have a way to read single characters from stdin in the standard library - you need external modules for that. /cc @ry |
I think we need something like Deno.stdin.set_raw() to disable the line buffering |
I don't know if a method on stdin would be the best option as we would then have to replace the underlying StreamResource in the resource table, something that currently is not supported by the resource table atm. Maybe instead we should open a raw version of stdin on rid 4 on startup, and make it available as Deno.stdin.raw. An alternate approach would be to make raw an async method on Deno.stdin, and only open the raw reader once it is needed. If any of that sounds good I can implement it. |
Won't |
No, the buffering happens at the lowest level, inside Rust's std::io::stdin(). If you read with a 1-byte buffer you only get one char, but only after the whole line has passed the buffer (i.e. when you press ENTER or linebreak). Example here: const decoder = new TextDecoder()
const file = Deno.stdin;
while (true) {
const c = new Uint8Array(1)
if (await file.read(c) == Deno.EOF) {
break
}
const char = decoder.decode(c);
console.log(char.toUpperCase())
} |
All clear, thanks for great example 👍 |
Related: #3416 |
As temporary solution, would it be possible to simulate |
Hy, A terminal by default is set to work in canonical mode.
if you want / need to change this behavior; you need to update the setup of the terminal (and not forget to reset it at the end) by using termcap command. But in our case we do not need to take care of that. For instance with this exemples which read a buffer of 20 bytes we should be able to see data incoming in the buffer as soon as they are sent: // main.ts
async function main() {
const fd = Deno.stdin;
const buffer = new Uint8Array(20);
let readed: number | null = null;
while (true) {
readed = await fd.read(buffer);
if (readed === null || readed === 0) {
break;
}
console.log(buffer);
buffer.fill(0);
}
}
main(); in this following example you program will receive 'hello' then '\n' then 'world'. >(echo -ne 'hello'; sleep 1; echo -ne '\n'; sleep 1; echo 'world') | deno run main.ts in the following one; it will receive 'hello\nwor' then 'ld' >(echo -ne 'hello\nwor'; sleep 1; echo 'ld') | deno run main.ts this two example illustrate that the read is not in cause. you could also simulate this behavior in a terminal (by hand) without a pipe by hitting ctrl-d; so if you want to read one byte from stdin, you should set the terminal to no canonical and read a buffer of if we want to be able to control the terminal behavior from Deno we might need to implement a terminal interface like in rust here or here maybe some readings about terminals and termcaps: Thanks for reading. |
I'm just starting with deno and have no experience with rust, but it seems like #3958 is a step towards this, no? Although it might only be unstable for now #4925. Coming from nodejs, I am looking for the equivalent of https://github.com/TooTallNate/keypress. |
With the current limitations, am I correct in assuming there's no way to get a user's password in the terminal? It appears that there isn't currently any capabilities available to mask or hide |
For now you may rely on unstable
|
For future readers: this is part of stable as of Deno 1.27, and it's moved to Deno.stdin.setRaw(true);
let chunk = new Uint8Array(0);
const reader = Deno.stdin.readable.getReader();
while (true) {
if (chunk.length === 0) {
const readResult = await reader.read();
if (readResult.done) break;
chunk = readResult.value;
continue;
}
const key = chunk[0];
chunk = chunk.slice(1);
console.log(key);
if (key === 3) break; // ctrl-c
} |
Hi,
Is there a way to read from Deno.stdin without hitting Enter? similar to process.stdin.on('EVENT' ... in node js?
For example, writing a program that print the uppercase of the char the user enters
a->A b->B .... just as an example.
Thanks
The text was updated successfully, but these errors were encountered: