Ask YN

/*
 * ask_yn - Wait for a user to press Y or N.
 *
 * By default, standard input in C++ (and most terminals) is line-buffered:
 * the terminal waits until you press Enter before sending the input to your
 * program.
 *
 * Getting a character immediately is not part of standard C++; it requires
 * platform-specific APIs. On Windows, you can use _getch() from <conio.h>.
 * It reads a character immediately without waiting for Enter.
 * On Linux, you need termios to switch the terminal to raw mode (disable
 * canonical input buffering) and read a single character immediately.
 * Note that anything send to stdout while in raw mode is buffered and
 * printed after leaving raw mode.
 *
 * If any type of portability is needed, use ncurses. It is a programming
 * library for creating textual user interfaces (TUIs) that work across a
 * wide variety of terminals.
 *
 * g++ -std=c++17 -Wpedantic -Wall -Wextra ask_yn.cpp -o ask_yn
*/

#include <iostream>

#if defined(_WIN32) || defined(_WIN64)
// -------------------- WINDOWS VERSION --------------------
#include <conio.h>
#else
// -------------------- LINUX / POSIX VERSION --------------------
#include <unistd.h>
#include <termios.h>

class BlockingRawModeScope {
public:
    BlockingRawModeScope() {
        tcgetattr(STDIN_FILENO, &orig_termios);
        termios raw = orig_termios;
        raw.c_lflag &= ~(ICANON | ECHO);   // disable canonical mode and echo
        tcsetattr(STDIN_FILENO, TCSANOW, &raw);
    }

    ~BlockingRawModeScope() {
        tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
    }

private:
    termios orig_termios;
};
#endif


bool get_yn()
{
#if defined(_WIN32) || defined(_WIN64)
// -------------------- WINDOWS VERSION --------------------
    for(;;) {
        char c = _getch();
        if (c == 'Y' || c == 'y') {
            return true;
        }
        if (c == 'N' || c == 'n') {
            return false;
        }
    }
#else
// -------------------- LINUX / POSIX VERSION --------------------
    BlockingRawModeScope rawMode;
    for(;;) {
        char c;
        if (read(STDIN_FILENO, &c, 1) > 0) {
            if (c == 'Y' || c == 'y') {
                return true;
            }
            if (c == 'N' || c == 'n') {
                return false;
            }
        }
    }
#endif
}

int main() {
    std::cout << "Press Y or N: " << std::flush;

    if (get_yn())
        std::cout << "\nYou pressed Y\n";
    else
        std::cout << "\nYou pressed N\n";

    return 0;
}