|
|
Now that the Calendar is loaded with appointment data from the ASCII file, we must deal with the queries themselves. The Args(C++) component is used to parse command line options, and the Regex(C++) component is used to handle regular expressions (which are only used if the -r option is specified). Here is process_queries(), called originally from main():
void process_queries(const Calendar& cal, int argc, const char*const* argv) { Args args(argc, argv, "tnr:"); Regex r("); // matches everything if (args.isset('r')) { r.assign(args.value('r'), Regex::case_insensitive);
if (args.isset('t')) show_todays_appts(cal, r); if (args.isset('n')) show_next_appt(cal, r); }Here is the code to show today's Appointments:
void show_todays_appts(const Calendar& cal, const Regex& r) { Time now = make_time("now"); Date today(now);
if (!cal.element(today)) cout << "cal: no appointments for today" << endl; else { cout << "your appointments for " << today << ":" << endl; show_appts(cal[today], r); } }All the above does is compute the current date, check whether that is a key in the Map, and if so, call a function show_appts() to show the Appts at that key. In the process, it prints today's Date using the following function:
ostream& operator<<(ostream& os, Date d) { os << d.midnight.make_string("%x"); return os; }Here is show_appts():
void show_appts(const Appts& appts,const Regex& r){ for (int i = 0; i < appts.num(); ++i) if (r.match(appts[i].desc)) cout << "\t" << appts[i] << endl; }Notice this invokes the output operation for an Appointment. Here it is:
ostream& operator<<(ostream& os, const Appointment& a) { show_clock_part(os, a.time); os << "\t" << a.desc; return os; }The function show_clock_part() just shows the clock part of the given Time in the appropriate format:
void show_clock_part(ostream& os, const Time& t) { os << t.clock_part().make_string("%X"); }This completes the code for the -t query. Here now is the code for the -n query:
void show_next_appt(const Calendar& cal, const Regex& r) { Time now = make_time("now"); Date today(now);
Calendariter i = cal.element(today); if (!i) i = cal.first(); search_forward_in_cal(i, now, r); }If there is an entry in the Calendar for today, we search forward from that entry for the first Appointment whose time is later than now. If there is no entry in the Calendar for today, we must begin our search at the earliest entry in the Calendar.
The function search_forward_in_cal() searches forward in the Calendar starting at the day indexed by i, looking for the first appointment after now matching the given regular expression:
void search_forward_in_cal(Calendariter& i, Time now, const Regex& r) { for ( ; i; i.next()) if (search_in_appts(i.curr()->value, now, r)) return; }The function search_in_appts() searches forward in the given Appts for the first appointment after now matching the regular expression. It returns true if such an Appointment was found (in which case it shows it).
int search_in_appts(const Appts& appts, Time now, const Regex& r) { for (int i = 0; i < appts.num(); ++i) { const Appointment& a = appts[i]; if (a.time > now && r.match(a.desc)) { cout << "Your next appointment is on " << appts[i].make_string("%x:") << endl; cout << "\t" << a << endl; return 1; } } return 0; }
Notice the similarity between this function and show_appts() above; with a little effort we could factor out common code, making them parameterized versions of a single function. (We leave it to the reader to do this.)