Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

user.cpp

Go to the documentation of this file.
00001 //  ======================================================================== //
00002 //                                                                           //
00003 //    File      : user.cpp                                                   //
00004 //    Purpose   :                                                            //
00005 //    Time-stamp: <Wed Nov/13/2002 06:10 MET Coder@ReallySoft.de>            //
00006 //                                                                           //
00007 //    (C) February 2002 by Ralf Westram                                      //
00008 //                                                                           //
00009 //    Permission to use, copy, modify, distribute and sell this software     //
00010 //    and its documentation for any purpose is hereby granted without fee,   //
00011 //    provided that the above copyright notice appear in all copies and      //
00012 //    that both that copyright notice and this permission notice appear      //
00013 //    in supporting documentation.                                           //
00014 //                                                                           //
00015 //    Ralf Westram makes no representations about the suitability of this    //
00016 //    software for any purpose.  It is provided "as is" without express or   //
00017 //    implied warranty.                                                      //
00018 //                                                                           //
00019 //  ======================================================================== //
00020 
00021 #include "user.h"
00022 #include <Tools.h>
00023 #include <rs_assert.h>
00024 #include <Err.h>
00025 
00026 using namespace std;
00027 using namespace rs;
00028 using namespace rs::str;
00029 using namespace rs::err;
00030 
00031 #define OUT cerr
00032 #define IN  cin
00033 
00034 namespace rs {
00035     namespace user {
00036         // --------------------------------------------------------------
00037         //      string ask(const string& question, bool allow_empty)
00038         // --------------------------------------------------------------
00039         string ask(const string& question, bool allow_empty) {
00040             string answer;
00041             if (question.length()) OUT << question << endl;
00042             while (1) {
00043                 getline(IN, answer, '\n');
00044                 if (allow_empty || answer.length()) break;
00045                 OUT << "Enter your answer and press ENTER (or press Ctrl-C to abort)" << endl;
00046             };
00047 
00048             return answer;
00049         }
00050 
00051         // ------------------------------------------------------------------
00052         //      bool ask_yn(string question, const char *default_answer)
00053         // ------------------------------------------------------------------
00054         bool ask_yn(string question, const char *default_answer) {
00055             while (1) {
00056                 string answer = ask(default_answer ? (question+" ["+default_answer+"]") : question, true);
00057                 if (answer.empty() && default_answer) answer = default_answer;
00058                 strlwr(answer);
00059 
00060                 if (answer == "yes" || answer == "y") return true;
00061                 if (answer == "no" || answer == "n") return false;
00062                 question = "Please answer with yes or no (y/n)";
00063             }
00064         }
00065         // ------------------------------------------------------------
00066         //      int ask_number(string question, int low, int high)
00067         // ------------------------------------------------------------
00068         int ask_number(string question, int low, int high) {
00069             int num = 0;
00070             assert(low <= high);
00071             while (1) {
00072                 string answer = ask(question, true);
00073                 num           = atoi(answer.c_str());
00074 
00075                 if (num >= low && num <= high) break;
00076                 question = strf("Please enter a number between %i and %i", low, high);
00077             }
00078             return num;
00079         }
00080         // ---------------------------------------------------------------------------
00081         //      size_t choose(const string& title, const vector<string>& answers)
00082         // ---------------------------------------------------------------------------
00083         size_t choose(const string& title, const vector<string>& answers) {
00084             int count     = 1;
00085             int max_width = 0;
00086 
00087             for (vector<string>::const_iterator s = answers.begin(); s != answers.end(); ++s, ++count) {
00088                 int width                      = 3+(count<10 ? 1 : (count<100 ? 2 : 3)) + s->length() + 1;
00089                 if (width>max_width) max_width = width;
00090             }
00091 
00092             size_t size    = answers.size();
00093             int    rows    = size;
00094             int    columns = 1;
00095 
00096             int tty_rows    = 50; // @@@ how can I detect the real TTY size ?
00097             int tty_columns = 80;
00098 
00099             if (rows>(tty_rows-3)) {
00100                 columns = tty_columns/max_width;
00101                 rows    = size/columns + !!(size%columns);
00102             }
00103 
00104             OUT << title;
00105             for (count = 0; count < rows; ++count) {
00106                 OUT << '\n';
00107                 for (int c = 0; c<columns; ++c) {
00108                     unsigned idx = count + c*rows;
00109                     if (idx<size) {
00110                         OUT << strf("%-*s", max_width, strf("(%i) %s", idx+1, answers[idx].c_str()).c_str());
00111                     }
00112                 }
00113             }
00114 
00115             OUT << endl;
00116 
00117             if (!size) throw InternalError("No choices to choose from");
00118             if (size == 1) {
00119                 OUT << "[Only one choice => autoselected!]\n";
00120                 return 1;
00121             }
00122             return ask_number("", 1, size);
00123         }
00124         // -----------------------------------------------------------------------------------
00125         //      size_t choose(const string& title, const string& answers, char separator)
00126         // -----------------------------------------------------------------------------------
00127         size_t choose(const string& title, const string& answers, char separator) {
00128             vector<string> a;
00129             size_t         start = 0;
00130 
00131             while (1) {
00132                 size_t sep = answers.find_first_of(separator, start);
00133                 if (sep == string::npos) {
00134                     a.push_back(answers.substr(start));
00135                     break;
00136                 }
00137                 a.push_back(answers.substr(start, sep-start));
00138                 start = sep+1;
00139             }
00140             return choose(title, a);
00141         }
00142         // -------------------------------------------
00143         //      void pause(const string& message)
00144         // -------------------------------------------
00145         void pause(const string& message) {
00146             ask(message+" -- Press ENTER when ready", true);
00147         }
00148     };
00149 };
00150 
00151 
00152 
00153 
00154 

Contact me in case of errors or questions.
This documentation is powered by Doxygen.
(C) 2000-2002 Doxygen