Read one char from stdin without pressing enter (getch)

I tried this:

const std = @import("std");

pub fn main(init: std.process.Init) !void {
    var buf: [1024]u8 = undefined;
    var stdin_reader = std.Io.File.stdin().reader(init.io, &buf);
    const stdin = &stdin_reader.interface;
    const input = try stdin.takeByte();
    std.log.debug("input: {any}", .{input});
}

…but it waits for me to press enter. I think it has been asked here already, but the answer there didn’t return the char immediately either on the older 0.13 version of Zig

Also I barely have any idea how to program in Zig and absolutely no idea how getch works in any other language. pls help

Terminals don’t send data until enter is pressed. This is called canonical mode. you can change this behavior by taking the terminal out of canonical mode, but that is usually done in the context of a TUI app.

If you pipe input from a file into your process stdin, I think you’ll see the behavior you are looking for.

This thread goes into discussions about how to poll for key down events and non-cannoncial modes, if that is what interests you.

As Calder said, this is not something you can do from within your program, regardless of the programming language. Only the shell itself can do that.

this is so oversimplified as to be obviously false, since in C for example, ncurses implements a getch that works like this. what would be more correct is to say that in order to get a single character, you have to negotiate with the shell to not buffer input. Userland programs absolutely can do that.