//////////////////////////////////////////////////////////////////////////////// // // Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // // http://www.opensource.org/licenses/mit-license.php // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include extern Context context; //////////////////////////////////////////////////////////////////////////////// DOM::DOM () { } //////////////////////////////////////////////////////////////////////////////// DOM::~DOM () { } //////////////////////////////////////////////////////////////////////////////// const std::vector DOM::get_references () const { std::vector refs; refs.push_back ("context.program"); refs.push_back ("context.args"); refs.push_back ("context.width"); refs.push_back ("context.height"); refs.push_back ("system.version"); refs.push_back ("system.os"); return refs; } //////////////////////////////////////////////////////////////////////////////// // DOM Supported References: // rc. // // context.program // context.args // context.width // context.height // // TODO stats. <-- context.stats // // system.version // system.os // bool DOM::get (const std::string& name, Variant& value) { int len = name.length (); Nibbler n (name); // rc. --> context.config if (len > 3 && name.substr (0, 3) == "rc.") { std::string key = name.substr (3); std::map ::iterator c = context.config.find (key); if (c != context.config.end ()) { value = Variant (c->second); return true; } return false; } // context.* if (len > 8 && name.substr (0, 8) == "context.") { if (name == "context.program") { value = Variant (context.cli.getBinary ()); return true; } else if (name == "context.args") { std::string commandLine; join (commandLine, " ", context.cli._original_args); value = Variant (commandLine); return true; } else if (name == "context.width") { value = Variant (context.terminal_width ? context.terminal_width : context.getWidth ()); return true; } else if (name == "context.height") { value = Variant (context.terminal_height ? context.terminal_height : context.getHeight ()); return true; } else throw format (STRING_DOM_UNREC, name); } // TODO stats. // system. --> Implement locally. if (len > 7 && name.substr (0, 7) == "system.") { // Taskwarrior version number. if (name == "system.version") { value = Variant (VERSION); return true; } // OS type. else if (name == "system.os") { #if defined (DARWIN) value = Variant ("Darwin"); #elif defined (SOLARIS) value = Variant ("Solaris"); #elif defined (CYGWIN) value = Variant ("Cygwin"); #elif defined (HAIKU) value = Variant ("Haiku"); #elif defined (OPENBSD) value = Variant ("OpenBSD"); #elif defined (FREEBSD) value = Variant ("FreeBSD"); #elif defined (NETBSD) value = Variant ("NetBSD"); #elif defined (LINUX) value = Variant ("Linux"); #elif defined (KFREEBSD) value = Variant ("GNU/kFreeBSD"); #elif defined (GNUHURD) value = Variant ("GNU/Hurd"); #else value = Variant (STRING_DOM_UNKNOWN); #endif return true; } else throw format (STRING_DOM_UNREC, name); } // Empty string if nothing is found. return false; } //////////////////////////////////////////////////////////////////////////////// // DOM Supported References: // // // . // . // // For certain attributes: // .year // .month // .day // .week // .weekday // .julian // .hour // .minute // .second // // tags. Includes virtual tags // // annotations..entry // annotations..entry.year // annotations..entry.month // annotations..entry.day // annotations..entry.week // annotations..entry.weekday // annotations..entry.julian // annotations..entry.hour // annotations..entry.minute // annotations..entry.second // annotations..description // bool DOM::get (const std::string& name, const Task& task, Variant& value) { // if (task.size () && name == "id") { value = Variant (task.id); return true; } if (task.size () && name == "urgency") { value = Variant (task.urgency_c ()); return true; } // split name on '.' std::vector elements; split (elements, name, '.'); if (elements.size () == 1) { std::string canonical; if (task.size () && context.cli.canonicalize (canonical, "attribute", name)) { Column* column = context.columns[canonical]; if (column) { if (column->is_uda () && ! task.has (canonical)) { value = Variant ("''"); return true; } if (column->type () == "date") value = Variant (task.get_date (canonical), Variant::type_date); else if (column->type () == "duration" || canonical == "recur") value = Variant ((time_t) Duration (task.get (canonical)), Variant::type_duration); else if (column->type () == "numeric") value = Variant (task.get_float (canonical)); else // string value = Variant (task.get (canonical)); return true; } } } else if (elements.size () > 1) { Task ref; Nibbler n (elements[0]); n.save (); int id; std::string uuid; bool proceed = false; if (n.getInt (id) && n.depleted ()) { if (id == task.id) ref = task; else context.tdb2.get (id, ref); proceed = true; } else { n.restore (); if (n.getUUID (uuid) && n.depleted ()) { if (uuid == task.get ("uuid")) ref = task; else context.tdb2.get (uuid, ref); proceed = true; } } if (proceed) { if (elements[1] == "id") { value = Variant (ref.id); return true; } else if (elements[1] == "urgency") { value = Variant (ref.urgency_c ()); return true; } std::string canonical; if (context.cli.canonicalize (canonical, "attribute", elements[1])) { if (elements.size () == 2) { Column* column = context.columns[canonical]; if (column) { if (column->is_uda () && ! task.has (canonical)) { value = Variant ("''"); return true; } if (column->type () == "date") value = Variant (ref.get_date (canonical), Variant::type_date); else if (column->type () == "duration") value = Variant ((time_t) Duration (ref.get (canonical)), Variant::type_duration); else if (column->type () == "numeric") value = Variant (ref.get_float (canonical)); else value = Variant (ref.get (canonical)); return true; } } else if (elements.size () == 3) { // tags. if (canonical == "tags") { value = Variant (ref.hasTag (elements[2]) ? elements[2] : ""); return true; } Column* column = context.columns[canonical]; if (column && column->type () == "date") { // .year // .month // .day // .week // .weekday // .julian // .hour // .minute // .second Date date (ref.get_date (canonical)); if (elements[2] == "year") { value = Variant (date.year ()); return true; } else if (elements[2] == "month") { value = Variant (date.month ()); return true; } else if (elements[2] == "day") { value = Variant (date.day ()); return true; } else if (elements[2] == "week") { value = Variant (date.week ()); return true; } else if (elements[2] == "weekday") { value = Variant (date.dayOfWeek ()); return true; } else if (elements[2] == "julian") { value = Variant (date.dayOfYear ()); return true; } else if (elements[2] == "hour") { value = Variant (date.hour ()); return true; } else if (elements[2] == "minute") { value = Variant (date.minute ()); return true; } else if (elements[2] == "second") { value = Variant (date.second ()); return true; } } } } else if (elements[1] == "annotations") { if (elements.size () == 4) { std::map annos; ref.getAnnotations (annos); int a = strtol (elements[2].c_str (), NULL, 10); int count = 0; // Count off the 'a'th annotation. std::map ::iterator i; for (i = annos.begin (); i != annos.end (); ++i) { if (++count == a) { if (elements[3] == "entry") { // annotation_1234567890 // 0 ^11 value = Variant ((time_t) strtol (i->first.substr (11).c_str (), NULL, 10), Variant::type_date); return true; } else if (elements[3] == "description") { value = Variant (i->second); return true; } } } } else if (elements.size () == 5) { std::map annos; ref.getAnnotations (annos); int a = strtol (elements[2].c_str (), NULL, 10); int count = 0; // Count off the 'a'th annotation. std::map ::iterator i; for (i = annos.begin (); i != annos.end (); ++i) { if (++count == a) { // ..entry.year // ..entry.month // ..entry.day // ..entry.week // ..entry.weekday // ..entry.julian // ..entry.hour // ..entry.minute // ..entry.second Date date (i->first.substr (11)); if (elements[4] == "year") { value = Variant (date.year ()); return true; } else if (elements[4] == "month") { value = Variant (date.month ()); return true; } else if (elements[4] == "day") { value = Variant (date.day ()); return true; } else if (elements[4] == "week") { value = Variant (date.week ()); return true; } else if (elements[4] == "weekday") { value = Variant (date.dayOfWeek ()); return true; } else if (elements[4] == "julian") { value = Variant (date.dayOfYear ()); return true; } else if (elements[4] == "hour") { value = Variant (date.hour ()); return true; } else if (elements[4] == "minute") { value = Variant (date.minute ()); return true; } else if (elements[4] == "second") { value = Variant (date.second ()); return true; } } } } } } } // Delegate to the context-free version of DOM::get. return this->get (name, value); } //////////////////////////////////////////////////////////////////////////////// void DOM::set (const std::string& name, const Variant& value) { int len = name.length (); // rc. --> context.config if (len > 3 && name.substr (0, 3) == "rc.") { context.config.set (name.substr (3), (std::string) value); } // Unrecognized --> error. else throw format (STRING_DOM_CANNOT_SET, name); } ////////////////////////////////////////////////////////////////////////////////