#include "MenuDriver.h" #include #include #include /* #include #include #include #include #include */ using namespace std; MenuDriver::MenuDriver(int argc, const char* argv[]) : MENU("(Q) Quit."), isr(&cin), cinFail(false), limit(-1), pass(0) { // choose between keyboard input or mock-keyboard file input if (argc>1) { inputfile.open(argv[1],ios::in); if (inputfile.is_open()) { isr = &inputfile; } else { cout << "Input file '" << argv[1] << "' not found.\n"; cout << "Defaulting to keyboard input.\n\n"; } } // is there a limit on the number of lines to read? if (argc>2) { limit = atoi(argv[2]); if (limit < 1) { limit = -1; cout << "Second argument (" << argv[2] << ") ignored.\n\n"; } } } bool MenuDriver::readYN(const string& prompt) { bool result = false; bool done = false; do { string s = read(prompt); if ((s == "y") || (s == "Y") || (s == "yes") || (s == "Yes")) { result = true; done = true; } else if ((s == "n") || (s == "N") || (s == "no") || (s == "No")) { result = false; done = true; } } while (!done); return(result); } string MenuDriver::readLine(const string& prompt, bool forceNonEmpty, bool clearStream) { if (prompt.size()) std::cout << prompt; if (clearStream) { // isr->ignore(numeric_limits::max(), '\n'); // problem is this may throw away partial line bool clearing = true; while (clearing) { char p = isr->peek(); switch (p) { case ' ': case '\t': isr->get(); break; case '\n': isr->get(); // intentionally NO break here. Want to end this loop when newline is cleared default: clearing = false; // reached non-whitespace } } } std::string response = ""; do { getline(*isr, response); if (isr != &std::cin) // echo input std::cout << response << "\n"; if (response.size() && response[response.size()-1]!='\n' && isr->eof()) response += '\n'; // good enough else if (isr->eof() || (isr->bad())) { response = ""; switchInput(); } } while (forceNonEmpty && (response == "" || response == "\n")); return(response); } /** Switches from file input to console input. * This is typically called after receving an eof. * @throws runtime_error when EOF was reached from cin. */ void MenuDriver::switchInput() { // called after reaching EOF on isr if (isr != &cin) isr = &cin; else if (isr->eof()) throw runtime_error("unexpected end of input reached on console."); else if (isr->bad()) throw runtime_error("critical failure on console input."); } int MenuDriver::run() { bool again = true; while (again && (limit < 0 || pass < limit)) again = menuOnce(); return 0; } bool MenuDriver::menuOnce() { pass++; if (isr == &cin) // only print menu when working from console cout << endl << MENU << endl; cout << "Command #" << pass << "> " << flush; string response = read(); return( handleChoice(response) ); }