version(Posix): import core.sys.posix.termios; import core.sys.posix.unistd; import core.sys.posix.sys.types; import core.sys.posix.sys.time; import core.stdc.stdio; enum ConsoleInputFlags { raw = 0, echo = 1 } struct RealTimeConsoleInput { @disable this(); @disable this(this); private int fd; private termios old; this(ConsoleInputFlags flags) { this.fd = 0; // stdin tcgetattr(fd, &old); auto n = old; auto f = ICANON; if(!(flags & ConsoleInputFlags.echo)) f |= ECHO; n.c_lflag &= ~f; tcsetattr(fd, TCSANOW, &n); } ~this() { tcsetattr(fd, TCSANOW, &old); } bool kbhit() { timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; fd_set fs; FD_ZERO(&fs); FD_SET(fd, &fs); select(fd + 1, &fs, null, null, &tv); return FD_ISSET(fd, &fs); } char getch() { return cast(char) .fgetc(.stdin); } } void main() { auto input = new RealTimeConsoleInput(ConsoleInputFlags.raw); while(true) { if(input.kbhit()) { auto c = input.getch(); if(c == 'q' || c == 'Q') break; printf("%c", c); fflush(stdout); } usleep(10000); } }