diff --git a/AUTHORS b/AUTHORS index 5598ef1f2..dd53e279d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -141,6 +141,7 @@ The following submitted code, packages or analysis, and deserve special thanks: Øyvind A. Holm Paul J. Fenwick Michael Neumann + Mark Scannell Thanks to the following, who submitted detailed bug reports and excellent suggestions: diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f6d91b5a..044daaf9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,13 @@ include (CXXSniffer) set (PROJECT_VERSION "2.6.0") +OPTION (ENABLE_WASM "Enable 'wasm' support" OFF) + +if (ENABLE_WASM) + message ("Enabling WASM support.") + set(CMAKE_EXECUTABLE_SUFFIX ".js") +endif (ENABLE_WASM) + OPTION (ENABLE_SYNC "Enable 'task sync' support" ON) if (ENABLE_SYNC) diff --git a/INSTALL b/INSTALL index 5893488ee..7aad45280 100644 --- a/INSTALL +++ b/INSTALL @@ -158,6 +158,14 @@ OpenBSD See: https://bug.tasktools.org/browse/TW-1579 +WASM + Using the Emscripten compiler, you can achieve it like this: + + cmake -DCMAKE_CXX_COMPILER=emcc -DENABLE_SYNC=OFF -DCMAKE_BUILD_TYPE=release -DENABLE_WASM=ON \ + -DCMAKE_EXE_LINKER_FLAGS="-m32 -s NO_DYNAMIC_EXECUTION=1 -s WASM=1 -s NO_EXIT_RUNTIME=1 -s INVOKE_RUN=0" \ + -DCMAKE_CXX_FLAGS_RELEASE="-O2 -m32" + + This will produce an optimized WASM with a main() that is callable multiple times. Troubleshooting --------------- diff --git a/src/CLI2.cpp b/src/CLI2.cpp index b5719f5a6..484527c34 100644 --- a/src/CLI2.cpp +++ b/src/CLI2.cpp @@ -35,8 +35,6 @@ #include #include -extern Context context; - // Overridden by rc.abbreviation.minimum. int CLI2::minimumMatchLength = 3; @@ -235,7 +233,7 @@ void CLI2::getOverride (int argc, const char** argv, std::string& home, File& rc if (last_slash != std::string::npos) home = rc.parent (); - context.header (format ("Using alternate .taskrc file {1}", rc._data)); + Context::getContext ().header (format ("Using alternate .taskrc file {1}", rc._data)); // Keep looping, because if there are multiple rc:file arguments, the last // one should dominate. @@ -248,7 +246,7 @@ void CLI2::getOverride (int argc, const char** argv, std::string& home, File& rc // Static method. void CLI2::getDataLocation (int argc, const char** argv, Path& data) { - std::string location = context.config.get ("data.location"); + std::string location = Context::getContext ().config.get ("data.location"); if (location != "") data = location; @@ -262,7 +260,7 @@ void CLI2::getDataLocation (int argc, const char** argv, Path& data) raw.substr (0, 16) == "rc.data.location") { data = Directory (raw.substr (17)); - context.header (format ("Using alternate data.location {1}", (std::string) data)); + Context::getContext ().header (format ("Using alternate data.location {1}", (std::string) data)); // Keep looping, because if there are multiple rc:file arguments, the last // one should dominate. @@ -297,10 +295,10 @@ void CLI2::applyOverrides (int argc, const char** argv) { std::string name = raw.substr (3, sep - 3); std::string value = raw.substr (sep + 1); - context.config.set (name, value); + Context::getContext ().config.set (name, value); - if (context.verbose("override")) - context.footnote (format ("Configuration override rc.{1}:{2}", name, value)); + if (Context::getContext ().verbose("override")) + Context::getContext ().footnote (format ("Configuration override rc.{1}:{2}", name, value)); } } } @@ -469,8 +467,8 @@ void CLI2::lexArguments () } } - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze lexArguments")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze lexArguments")); } //////////////////////////////////////////////////////////////////////////////// @@ -500,7 +498,7 @@ void CLI2::demotion () else if (a._lextype == Lexer::Type::pair && canonicalize (canonical, "pseudo", a.attribute ("name"))) { - context.config.set (canonical, a.attribute ("value")); + Context::getContext ().config.set (canonical, a.attribute ("value")); changes = true; // Equivalent to erasing 'a'. @@ -511,16 +509,16 @@ void CLI2::demotion () } if (changes && - context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze demotion")); + Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze demotion")); } //////////////////////////////////////////////////////////////////////////////// // Intended to be called after ::add() to perform the final analysis. void CLI2::analyze () { - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze")); // Process _original_args. _args.clear (); @@ -577,10 +575,10 @@ void CLI2::addContextFilter () return; // Detect if any context is set, and bail out if not - std::string contextName = context.config.get ("context"); + std::string contextName = Context::getContext ().config.get ("context"); if (contextName == "") { - context.debug ("No context."); + Context::getContext ().debug ("No context."); return; } @@ -591,23 +589,23 @@ void CLI2::addContextFilter () a._lextype == Lexer::Type::number || a._lextype == Lexer::Type::set) { - context.debug (format ("UUID/ID argument found '{1}', not applying context.", a.attribute ("raw"))); + Context::getContext ().debug (format ("UUID/ID argument found '{1}', not applying context.", a.attribute ("raw"))); return; } } // Apply context - context.debug ("Applying context: " + contextName); - std::string contextFilter = context.config.get ("context." + contextName); + Context::getContext ().debug ("Applying context: " + contextName); + std::string contextFilter = Context::getContext ().config.get ("context." + contextName); if (contextFilter == "") - context.debug ("Context '" + contextName + "' not defined."); + Context::getContext ().debug ("Context '" + contextName + "' not defined."); else { _context_filter_added = true; addFilter (contextFilter); - if (context.verbose ("context")) - context.footnote (format ("Context '{1}' set. Use 'task context none' to remove.", contextName)); + if (Context::getContext ().verbose ("context")) + Context::getContext ().footnote (format ("Context '{1}' set. Use 'task context none' to remove.", contextName)); } } @@ -633,7 +631,7 @@ void CLI2::prepareFilter () desugarFilterPatterns (); insertJunctions (); // Deliberately after all desugar calls. - if (context.verbose ("filter")) + if (Context::getContext ().verbose ("filter")) { std::string combined; for (const auto& a : _args) @@ -648,7 +646,7 @@ void CLI2::prepareFilter () } if (combined.size ()) - context.footnote (std::string ("Filter: ") + combined); + Context::getContext ().footnote (std::string ("Filter: ") + combined); } } @@ -661,13 +659,13 @@ const std::vector CLI2::getWords () if (a.hasTag ("MISCELLANEOUS")) words.push_back (a.attribute ("raw")); - if (context.config.getInteger ("debug.parser") >= 2) + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) { Color colorOrigArgs ("gray10 on gray4"); std::string message = " "; for (const auto& word : words) message += colorOrigArgs.colorize (word) + ' '; - context.debug ("CLI2::getWords" + message); + Context::getContext ().debug ("CLI2::getWords" + message); } return words; @@ -854,11 +852,11 @@ void CLI2::aliasExpansion () while (action && counter++ < safetyValveDefault); if (counter >= safetyValveDefault) - context.debug (format ("Nested alias limit of {1} reached.", safetyValveDefault)); + Context::getContext ().debug (format ("Nested alias limit of {1} reached.", safetyValveDefault)); if (changes && - context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze aliasExpansion")); + Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze aliasExpansion")); } //////////////////////////////////////////////////////////////////////////////// @@ -892,8 +890,8 @@ void CLI2::canonicalizeNames () } if (changes && - context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze canonicalizeNames")); + Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze canonicalizeNames")); } //////////////////////////////////////////////////////////////////////////////// @@ -902,7 +900,7 @@ void CLI2::categorizeArgs () { // Context is only applied for commands that request it. std::string command = getCommand (); - Command* cmd = context.commands[command]; + Command* cmd = Context::getContext ().commands[command]; if (cmd && cmd->uses_context ()) addContextFilter (); @@ -1013,8 +1011,8 @@ void CLI2::categorizeArgs () } if (changes && - context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze categorizeArgs")); + Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze categorizeArgs")); } //////////////////////////////////////////////////////////////////////////////// @@ -1082,8 +1080,8 @@ void CLI2::parenthesizeOriginalFilter () _args = reconstructed; - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze parenthesizeOriginalFilter")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze parenthesizeOriginalFilter")); } } @@ -1114,7 +1112,7 @@ bool CLI2::findCommand () a.tag ("CMD"); // Apply command DNA as tags. - Command* command = context.commands[canonical]; + Command* command = Context::getContext ().commands[canonical]; if (command->read_only ()) a.tag ("READONLY"); if (command->displays_id ()) a.tag ("SHOWSID"); if (command->needs_gc ()) a.tag ("RUNSGC"); @@ -1123,8 +1121,8 @@ bool CLI2::findCommand () if (command->accepts_modifications ()) a.tag ("ALLOWSMODIFICATIONS"); if (command->accepts_miscellaneous ()) a.tag ("ALLOWSMISC"); - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze findCommand")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze findCommand")); // Stop and indicate command found. return true; @@ -1185,8 +1183,8 @@ void CLI2::desugarFilterTags () { _args = reconstructed; - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter desugarFilterTags")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter desugarFilterTags")); } } @@ -1211,8 +1209,8 @@ void CLI2::findStrayModifications () } if (changes) - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter findStrayModifications")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter findStrayModifications")); } //////////////////////////////////////////////////////////////////////////////// @@ -1249,12 +1247,12 @@ void CLI2::desugarFilterAttributes () // ) // Use this sequence in place of a single value. std::vector values = lexExpression (value); - if (context.config.getInteger ("debug.parser") >= 2) + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) { - context.debug ("CLI2::lexExpression " + name + ':' + value); + Context::getContext ().debug ("CLI2::lexExpression " + name + ':' + value); for (auto& v : values) - context.debug (" " + v.dump ()); - context.debug (" "); + Context::getContext ().debug (" " + v.dump ()); + Context::getContext ().debug (" "); } bool found = false; @@ -1267,7 +1265,7 @@ void CLI2::desugarFilterAttributes () // date --> yes // duration --> yes bool evalSupported = true; - Column* col = context.columns[canonical]; + Column* col = Context::getContext ().columns[canonical]; if (col && col->type () == "string") evalSupported = false; @@ -1413,8 +1411,8 @@ void CLI2::desugarFilterAttributes () { _args = reconstructed; - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter desugarFilterAttributes")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter desugarFilterAttributes")); } } @@ -1452,8 +1450,8 @@ void CLI2::desugarFilterPatterns () { _args = reconstructed; - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter desugarFilterPatterns")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter desugarFilterPatterns")); } } @@ -1470,7 +1468,7 @@ void CLI2::findIDs () { bool changes = false; - if (context.config.getBoolean ("sugar")) + if (Context::getContext ().config.getBoolean ("sugar")) { bool previousFilterArgWasAnOperator = false; int filterCount = 0; @@ -1590,8 +1588,8 @@ void CLI2::findIDs () } if (changes) - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter findIDs")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter findIDs")); } //////////////////////////////////////////////////////////////////////////////// @@ -1599,7 +1597,7 @@ void CLI2::findUUIDs () { bool changes = false; - if (context.config.getBoolean ("sugar")) + if (Context::getContext ().config.getBoolean ("sugar")) { for (const auto& a : _args) { @@ -1651,8 +1649,8 @@ void CLI2::findUUIDs () } if (changes) - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter findUUIDs")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter findUUIDs")); } //////////////////////////////////////////////////////////////////////////////// @@ -1798,8 +1796,8 @@ void CLI2::insertIDExpr () { _args = reconstructed; - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter insertIDExpr")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter insertIDExpr")); } } @@ -1835,8 +1833,8 @@ void CLI2::lexFilterArgs () { _args = reconstructed; - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter lexFilterArgs")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter lexFilterArgs")); } } @@ -1942,8 +1940,8 @@ void CLI2::desugarFilterPlainArgs () { _args = reconstructed; - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter desugarFilterPlainArgs")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter desugarFilterPlainArgs")); } } @@ -1996,8 +1994,8 @@ void CLI2::insertJunctions () { _args = reconstructed; - if (context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::prepareFilter insertJunctions")); + if (Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::prepareFilter insertJunctions")); } } @@ -2037,7 +2035,7 @@ void CLI2::defaultCommand () if (! found_sequence) { // Apply overrides, if any. - std::string defaultCommand = context.config.get ("default.command"); + std::string defaultCommand = Context::getContext ().config.get ("default.command"); if (defaultCommand != "") { // Modify _args, _original_args to be: @@ -2080,8 +2078,8 @@ void CLI2::defaultCommand () } if (changes && - context.config.getInteger ("debug.parser") >= 2) - context.debug (dump ("CLI2::analyze defaultCommand")); + Context::getContext ().config.getInteger ("debug.parser") >= 2) + Context::getContext ().debug (dump ("CLI2::analyze defaultCommand")); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Context.cpp b/src/Context.cpp index 4b8f4ff19..94f39eab4 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -414,6 +414,20 @@ static const char* modifierNames[] = #define NUM_MODIFIER_NAMES (sizeof (modifierNames) / sizeof (modifierNames[0])) +Context* Context::context; + +//////////////////////////////////////////////////////////////////////////////// +Context& Context::getContext () +{ + return *Context::context; +} + +//////////////////////////////////////////////////////////////////////////////// +void Context::setContext (Context* context) +{ + Context::context = context; +} + //////////////////////////////////////////////////////////////////////////////// Context::~Context () { diff --git a/src/Context.h b/src/Context.h index f83fe2057..9b9b7346c 100644 --- a/src/Context.h +++ b/src/Context.h @@ -47,6 +47,9 @@ public: Context (const Context&); Context& operator= (const Context&); + static Context& getContext (); + static void setContext (Context*); + int initialize (int, const char**); // all startup int run (); int dispatch (std::string&); // command handler dispatch @@ -76,6 +79,8 @@ private: void loadAliases (); void propagateDebug (); + static Context* context; + public: CLI2 cli2 {}; std::string home_dir {}; diff --git a/src/DOM.cpp b/src/DOM.cpp index dd7b8c524..aa677de51 100644 --- a/src/DOM.cpp +++ b/src/DOM.cpp @@ -38,8 +38,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// // DOM Supported References: // @@ -75,8 +73,8 @@ bool getDOM (const std::string& name, Variant& value) ! name.compare (0, 3, "rc.", 3)) { auto key = name.substr (3); - auto c = context.config.find (key); - if (c != context.config.end ()) + auto c = Context::getContext ().config.find (key); + if (c != Context::getContext ().config.end ()) { value = Variant (c->second); return true; @@ -92,7 +90,7 @@ bool getDOM (const std::string& name, Variant& value) if (name == "tw.syncneeded") { value = Variant (0); - for (const auto& line : context.tdb2.backlog.get_lines ()) + for (const auto& line : Context::getContext ().tdb2.backlog.get_lines ()) { if (line[0] == '{') { @@ -105,13 +103,13 @@ bool getDOM (const std::string& name, Variant& value) } else if (name == "tw.program") { - value = Variant (context.cli2.getBinary ()); + value = Variant (Context::getContext ().cli2.getBinary ()); return true; } else if (name == "tw.args") { std::string commandLine; - for (auto& arg : context.cli2._original_args) + for (auto& arg : Context::getContext ().cli2._original_args) { if (commandLine != "") commandLine += ' '; @@ -124,16 +122,16 @@ bool getDOM (const std::string& name, Variant& value) } else if (name == "tw.width") { - value = Variant (static_cast (context.terminal_width - ? context.terminal_width - : context.getWidth ())); + value = Variant (static_cast (Context::getContext ().terminal_width + ? Context::getContext ().terminal_width + : Context::getContext ().getWidth ())); return true; } else if (name == "tw.height") { - value = Variant (static_cast (context.terminal_height - ? context.terminal_height - : context.getHeight ())); + value = Variant (static_cast (Context::getContext ().terminal_height + ? Context::getContext ().terminal_height + : Context::getContext ().getHeight ())); return true; } @@ -152,13 +150,13 @@ bool getDOM (const std::string& name, Variant& value) { if (name == "context.program") { - value = Variant (context.cli2.getBinary ()); + value = Variant (Context::getContext ().cli2.getBinary ()); return true; } else if (name == "context.args") { std::string commandLine; - for (auto& arg : context.cli2._original_args) + for (auto& arg : Context::getContext ().cli2._original_args) { if (commandLine != "") commandLine += ' '; @@ -171,16 +169,16 @@ bool getDOM (const std::string& name, Variant& value) } else if (name == "context.width") { - value = Variant (static_cast (context.terminal_width - ? context.terminal_width - : context.getWidth ())); + value = Variant (static_cast (Context::getContext ().terminal_width + ? Context::getContext ().terminal_width + : Context::getContext ().getWidth ())); return true; } else if (name == "context.height") { - value = Variant (static_cast (context.terminal_height - ? context.terminal_height - : context.getHeight ())); + value = Variant (static_cast (Context::getContext ().terminal_height + ? Context::getContext ().terminal_height + : Context::getContext ().getHeight ())); return true; } @@ -273,7 +271,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) token.length () == elements[0].length ()) { if (token != ref.get ("uuid")) - context.tdb2.get (token, ref); + Context::getContext ().tdb2.get (token, ref); // Eat elements[0]/UUID. elements.erase (elements.begin ()); @@ -283,7 +281,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) { auto id = strtol (token.c_str (), NULL, 10); if (id && id != ref.id) - context.tdb2.get (id, ref); + Context::getContext ().tdb2.get (id, ref); // Eat elements[0]/ID. elements.erase (elements.begin ()); @@ -293,7 +291,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) auto size = elements.size (); std::string canonical; - if ((size == 1 || size == 2) && context.cli2.canonicalize (canonical, "attribute", elements[0])) + if ((size == 1 || size == 2) && Context::getContext ().cli2.canonicalize (canonical, "attribute", elements[0])) { // Now that 'ref' is the contextual task, and any ID/UUID is chopped off the // elements vector, DOM resolution is now simple. @@ -309,7 +307,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) return true; } - Column* column = context.columns[canonical]; + Column* column = Context::getContext ().columns[canonical]; if (ref.data.size () && size == 1 && column) { diff --git a/src/Eval.cpp b/src/Eval.cpp index bc9f62031..53013f46b 100644 --- a/src/Eval.cpp +++ b/src/Eval.cpp @@ -36,7 +36,6 @@ #define STRING_EVAL_NO_EVAL "The expression could not be evaluated." -extern Context context; extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// @@ -129,15 +128,15 @@ void Eval::evaluateInfixExpression (const std::string& e, Variant& v) const // Parse for syntax checking and operator replacement. if (_debug) - context.debug ("FILTER Infix " + dump (tokens)); + Context::getContext ().debug ("FILTER Infix " + dump (tokens)); infixParse (tokens); if (_debug) - context.debug ("FILTER Infix parsed " + dump (tokens)); + Context::getContext ().debug ("FILTER Infix parsed " + dump (tokens)); // Convert infix --> postfix. infixToPostfix (tokens); if (_debug) - context.debug ("FILTER Postfix " + dump (tokens)); + Context::getContext ().debug ("FILTER Postfix " + dump (tokens)); // Call the postfix evaluator. evaluatePostfixStack (tokens, v); @@ -155,7 +154,7 @@ void Eval::evaluatePostfixExpression (const std::string& e, Variant& v) const tokens.push_back (std::pair (token, type)); if (_debug) - context.debug ("FILTER Postfix " + dump (tokens)); + Context::getContext ().debug ("FILTER Postfix " + dump (tokens)); // Call the postfix evaluator. evaluatePostfixStack (tokens, v); @@ -169,15 +168,15 @@ void Eval::compileExpression ( // Parse for syntax checking and operator replacement. if (_debug) - context.debug ("FILTER Infix " + dump (_compiled)); + Context::getContext ().debug ("FILTER Infix " + dump (_compiled)); infixParse (_compiled); if (_debug) - context.debug ("FILTER Infix parsed " + dump (_compiled)); + Context::getContext ().debug ("FILTER Infix parsed " + dump (_compiled)); // Convert infix --> postfix. infixToPostfix (_compiled); if (_debug) - context.debug ("FILTER Postfix " + dump (_compiled)); + Context::getContext ().debug ("FILTER Postfix " + dump (_compiled)); } //////////////////////////////////////////////////////////////////////////////// @@ -240,7 +239,7 @@ void Eval::evaluatePostfixStack ( Variant result = ! right; values.push_back (result); if (_debug) - context.debug (format ("Eval {1} ↓'{2}' → ↑'{3}'", token.first, (std::string) right, (std::string) result)); + Context::getContext ().debug (format ("Eval {1} ↓'{2}' → ↑'{3}'", token.first, (std::string) right, (std::string) result)); } else if (token.second == Lexer::Type::op && token.first == "_neg_") @@ -256,14 +255,14 @@ void Eval::evaluatePostfixStack ( values.push_back (result); if (_debug) - context.debug (format ("Eval {1} ↓'{2}' → ↑'{3}'", token.first, (std::string) right, (std::string) result)); + Context::getContext ().debug (format ("Eval {1} ↓'{2}' → ↑'{3}'", token.first, (std::string) right, (std::string) result)); } else if (token.second == Lexer::Type::op && token.first == "_pos_") { // The _pos_ operator is a NOP. if (_debug) - context.debug (format ("[{1}] eval op {2} NOP", values.size (), token.first)); + Context::getContext ().debug (format ("[{1}] eval op {2} NOP", values.size (), token.first)); } // Binary operators. @@ -309,7 +308,7 @@ void Eval::evaluatePostfixStack ( values.push_back (result); if (_debug) - context.debug (format ("Eval ↓'{1}' {2} ↓'{3}' → ↑'{4}'", (std::string) left, token.first, (std::string) right, (std::string) result)); + Context::getContext ().debug (format ("Eval ↓'{1}' {2} ↓'{3}' → ↑'{4}'", (std::string) left, token.first, (std::string) right, (std::string) result)); } // Literals and identifiers. @@ -323,13 +322,13 @@ void Eval::evaluatePostfixStack ( { v.cast (Variant::type_integer); if (_debug) - context.debug (format ("Eval literal number ↑'{1}'", (std::string) v)); + Context::getContext ().debug (format ("Eval literal number ↑'{1}'", (std::string) v)); } else { v.cast (Variant::type_real); if (_debug) - context.debug (format ("Eval literal decimal ↑'{1}'", (std::string) v)); + Context::getContext ().debug (format ("Eval literal decimal ↑'{1}'", (std::string) v)); } break; @@ -346,7 +345,7 @@ void Eval::evaluatePostfixStack ( if ((*source) (token.first, v)) { if (_debug) - context.debug (format ("Eval identifier source '{1}' → ↑'{2}'", token.first, (std::string) v)); + Context::getContext ().debug (format ("Eval identifier source '{1}' → ↑'{2}'", token.first, (std::string) v)); found = true; break; } @@ -357,7 +356,7 @@ void Eval::evaluatePostfixStack ( { v.cast (Variant::type_string); if (_debug) - context.debug (format ("Eval identifier source failed '{1}'", token.first)); + Context::getContext ().debug (format ("Eval identifier source failed '{1}'", token.first)); } } break; @@ -365,20 +364,20 @@ void Eval::evaluatePostfixStack ( case Lexer::Type::date: v.cast (Variant::type_date); if (_debug) - context.debug (format ("Eval literal date ↑'{1}'", (std::string) v)); + Context::getContext ().debug (format ("Eval literal date ↑'{1}'", (std::string) v)); break; case Lexer::Type::duration: v.cast (Variant::type_duration); if (_debug) - context.debug (format ("Eval literal duration ↑'{1}'", (std::string) v)); + Context::getContext ().debug (format ("Eval literal duration ↑'{1}'", (std::string) v)); break; // Nothing to do. case Lexer::Type::string: default: if (_debug) - context.debug (format ("Eval literal string ↑'{1}'", (std::string) v)); + Context::getContext ().debug (format ("Eval literal string ↑'{1}'", (std::string) v)); break; } diff --git a/src/Filter.cpp b/src/Filter.cpp index 211d7defd..238dfea16 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -35,8 +35,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// // Const iterator that can be derefenced into a Task by domSource. static Task dummy; @@ -61,10 +59,10 @@ void Filter::subset (const std::vector & input, std::vector & output Timer timer; _startCount = (int) input.size (); - context.cli2.prepareFilter (); + Context::getContext ().cli2.prepareFilter (); std::vector > precompiled; - for (auto& a : context.cli2._args) + for (auto& a : Context::getContext ().cli2._args) if (a.hasTag ("FILTER")) precompiled.push_back (std::pair (a.getToken (), a._lextype)); @@ -75,7 +73,7 @@ void Filter::subset (const std::vector & input, std::vector & output // Debug output from Eval during compilation is useful. During evaluation // it is mostly noise. - eval.debug (context.config.getInteger ("debug.parser") >= 3 ? true : false); + eval.debug (Context::getContext ().config.getInteger ("debug.parser") >= 3 ? true : false); eval.compileExpression (precompiled); for (auto& task : input) @@ -95,8 +93,8 @@ void Filter::subset (const std::vector & input, std::vector & output output = input; _endCount = (int) output.size (); - context.debug (format ("Filtered {1} tasks --> {2} tasks [list subset]", _startCount, _endCount)); - context.time_filter_us += timer.total_us (); + Context::getContext ().debug (format ("Filtered {1} tasks --> {2} tasks [list subset]", _startCount, _endCount)); + Context::getContext ().time_filter_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -104,10 +102,10 @@ void Filter::subset (const std::vector & input, std::vector & output void Filter::subset (std::vector & output) { Timer timer; - context.cli2.prepareFilter (); + Context::getContext ().cli2.prepareFilter (); std::vector > precompiled; - for (auto& a : context.cli2._args) + for (auto& a : Context::getContext ().cli2._args) if (a.hasTag ("FILTER")) precompiled.push_back (std::pair (a.getToken (), a._lextype)); @@ -117,8 +115,8 @@ void Filter::subset (std::vector & output) if (precompiled.size ()) { Timer timer_pending; - auto pending = context.tdb2.pending.get_tasks (); - context.time_filter_us -= timer_pending.total_us (); + auto pending = Context::getContext ().tdb2.pending.get_tasks (); + Context::getContext ().time_filter_us -= timer_pending.total_us (); _startCount = (int) pending.size (); Eval eval; @@ -126,7 +124,7 @@ void Filter::subset (std::vector & output) // Debug output from Eval during compilation is useful. During evaluation // it is mostly noise. - eval.debug (context.config.getInteger ("debug.parser") >= 3 ? true : false); + eval.debug (Context::getContext ().config.getInteger ("debug.parser") >= 3 ? true : false); eval.compileExpression (precompiled); output.clear (); @@ -145,8 +143,8 @@ void Filter::subset (std::vector & output) if (! shortcut) { Timer timer_completed; - auto completed = context.tdb2.completed.get_tasks (); - context.time_filter_us -= timer_completed.total_us (); + auto completed = Context::getContext ().tdb2.completed.get_tasks (); + Context::getContext ().time_filter_us -= timer_completed.total_us (); _startCount += (int) completed.size (); for (auto& task : completed) @@ -168,23 +166,23 @@ void Filter::subset (std::vector & output) safety (); Timer pending_completed; - for (auto& task : context.tdb2.pending.get_tasks ()) + for (auto& task : Context::getContext ().tdb2.pending.get_tasks ()) output.push_back (task); - for (auto& task : context.tdb2.completed.get_tasks ()) + for (auto& task : Context::getContext ().tdb2.completed.get_tasks ()) output.push_back (task); - context.time_filter_us -= pending_completed.total_us (); + Context::getContext ().time_filter_us -= pending_completed.total_us (); } _endCount = (int) output.size (); - context.debug (format ("Filtered {1} tasks --> {2} tasks [{3}]", _startCount, _endCount, (shortcut ? "pending only" : "all tasks"))); - context.time_filter_us += timer.total_us (); + Context::getContext ().debug (format ("Filtered {1} tasks --> {2} tasks [{3}]", _startCount, _endCount, (shortcut ? "pending only" : "all tasks"))); + Context::getContext ().time_filter_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// bool Filter::hasFilter () const { - for (const auto& a : context.cli2._args) + for (const auto& a : Context::getContext ().cli2._args) if (a.hasTag ("FILTER")) return true; @@ -198,7 +196,7 @@ bool Filter::hasFilter () const bool Filter::pendingOnly () const { // When GC is off, there are no shortcuts. - if (! context.config.getBoolean ("gc")) + if (! Context::getContext ().config.getBoolean ("gc")) return false; // To skip loading completed.data, there should be: @@ -211,13 +209,13 @@ bool Filter::pendingOnly () const int countPending = 0; int countWaiting = 0; int countRecurring = 0; - int countId = (int) context.cli2._id_ranges.size (); - int countUUID = (int) context.cli2._uuid_list.size (); + int countId = (int) Context::getContext ().cli2._id_ranges.size (); + int countUUID = (int) Context::getContext ().cli2._uuid_list.size (); int countOr = 0; int countXor = 0; int countNot = 0; - for (const auto& a : context.cli2._args) + for (const auto& a : Context::getContext ().cli2._args) { if (a.hasTag ("FILTER")) { @@ -263,7 +261,7 @@ void Filter::safety () const { bool readonly = true; bool filter = false; - for (const auto& a : context.cli2._args) + for (const auto& a : Context::getContext ().cli2._args) { if (a.hasTag ("CMD") && ! a.hasTag ("READONLY")) @@ -276,11 +274,11 @@ void Filter::safety () const if (! readonly && ! filter) { - if (! context.config.getBoolean ("allow.empty.filter")) + if (! Context::getContext ().config.getBoolean ("allow.empty.filter")) throw std::string ("You did not specify a filter, and with the 'allow.empty.filter' value, no action is taken."); // If user is willing to be asked, this can be avoided. - if (context.config.getBoolean ("confirmation") && + if (Context::getContext ().config.getBoolean ("confirmation") && confirm ("This command has no filter, and will modify all (including completed and deleted) tasks. Are you sure?")) return; diff --git a/src/Hooks.cpp b/src/Hooks.cpp index e1adf364e..8c5f183d7 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -58,23 +58,21 @@ #define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}, in hook script: {3}" #define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from failing hook script: {1}" -extern Context context; - //////////////////////////////////////////////////////////////////////////////// void Hooks::initialize () { - _debug = context.config.getInteger ("debug.hooks"); + _debug = Context::getContext ().config.getInteger ("debug.hooks"); // Scan // /hooks Directory d; - if (context.config.has ("hooks.location")) + if (Context::getContext ().config.has ("hooks.location")) { - d = Directory (context.config.get ("hooks.location")); + d = Directory (Context::getContext ().config.get ("hooks.location")); } else { - d = Directory (context.config.get ("data.location")); + d = Directory (Context::getContext ().config.get ("data.location")); d += "hooks"; } @@ -96,17 +94,17 @@ void Hooks::initialize () name.substr (0, 9) == "on-modify" || name.substr (0, 9) == "on-launch" || name.substr (0, 7) == "on-exit") - context.debug ("Found hook script " + i); + Context::getContext ().debug ("Found hook script " + i); else - context.debug ("Found misnamed hook script " + i); + Context::getContext ().debug ("Found misnamed hook script " + i); } } } } else if (_debug >= 1) - context.debug ("Hook directory not readable: " + d._data); + Context::getContext ().debug ("Hook directory not readable: " + d._data); - _enabled = context.config.getBoolean ("hooks"); + _enabled = Context::getContext ().config.getBoolean ("hooks"); } //////////////////////////////////////////////////////////////////////////////// @@ -154,20 +152,20 @@ void Hooks::onLaunch () const if (status == 0) { for (auto& message : outputFeedback) - context.footnote (message); + Context::getContext ().footnote (message); } else { assertFeedback (outputFeedback, script); for (auto& message : outputFeedback) - context.error (message); + Context::getContext ().error (message); throw 0; // This is how hooks silently terminate processing. } } } - context.time_hooks_us += timer.total_us (); + Context::getContext ().time_hooks_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -194,7 +192,7 @@ void Hooks::onExit () const { // Get the set of changed tasks. std::vector tasks; - context.tdb2.get_changes (tasks); + Context::getContext ().tdb2.get_changes (tasks); // Convert to a vector of strings. std::vector input; @@ -216,20 +214,20 @@ void Hooks::onExit () const if (status == 0) { for (auto& message : outputFeedback) - context.footnote (message); + Context::getContext ().footnote (message); } else { assertFeedback (outputFeedback, script); for (auto& message : outputFeedback) - context.error (message); + Context::getContext ().error (message); throw 0; // This is how hooks silently terminate processing. } } } - context.time_hooks_us += timer.total_us (); + Context::getContext ().time_hooks_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -278,13 +276,13 @@ void Hooks::onAdd (Task& task) const input[0] = outputJSON[0]; for (auto& message : outputFeedback) - context.footnote (message); + Context::getContext ().footnote (message); } else { assertFeedback (outputFeedback, script); for (auto& message : outputFeedback) - context.error (message); + Context::getContext ().error (message); throw 0; // This is how hooks silently terminate processing. } @@ -294,7 +292,7 @@ void Hooks::onAdd (Task& task) const task = Task (input[0]); } - context.time_hooks_us += timer.total_us (); + Context::getContext ().time_hooks_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -345,13 +343,13 @@ void Hooks::onModify (const Task& before, Task& after) const input[1] = outputJSON[0]; for (auto& message : outputFeedback) - context.footnote (message); + Context::getContext ().footnote (message); } else { assertFeedback (outputFeedback, script); for (auto& message : outputFeedback) - context.error (message); + Context::getContext ().error (message); throw 0; // This is how hooks silently terminate processing. } @@ -360,7 +358,7 @@ void Hooks::onModify (const Task& before, Task& after) const after = Task (input[1]); } - context.time_hooks_us += timer.total_us (); + Context::getContext ().time_hooks_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -420,7 +418,7 @@ void Hooks::assertValidJSON ( i[0] != '{' || i[i.length () - 1] != '}') { - context.error (format (STRING_HOOK_ERROR_OBJECT, Path (script).name ())); + Context::getContext ().error (format (STRING_HOOK_ERROR_OBJECT, Path (script).name ())); throw 0; } @@ -429,19 +427,19 @@ void Hooks::assertValidJSON ( json::value* root = json::parse (i); if (root->type () != json::j_object) { - context.error (format (STRING_HOOK_ERROR_OBJECT, Path (script).name ())); + Context::getContext ().error (format (STRING_HOOK_ERROR_OBJECT, Path (script).name ())); throw 0; } if (((json::object*)root)->_data.find ("description") == ((json::object*)root)->_data.end ()) { - context.error (format (STRING_HOOK_ERROR_NODESC, Path (script).name ())); + Context::getContext ().error (format (STRING_HOOK_ERROR_NODESC, Path (script).name ())); throw 0; } if (((json::object*)root)->_data.find ("uuid") == ((json::object*)root)->_data.end ()) { - context.error (format (STRING_HOOK_ERROR_NOUUID, Path (script).name ())); + Context::getContext ().error (format (STRING_HOOK_ERROR_NOUUID, Path (script).name ())); throw 0; } @@ -450,15 +448,15 @@ void Hooks::assertValidJSON ( catch (const std::string& e) { - context.error (format (STRING_HOOK_ERROR_SYNTAX, i)); + Context::getContext ().error (format (STRING_HOOK_ERROR_SYNTAX, i)); if (_debug) - context.error (STRING_HOOK_ERROR_JSON + e); + Context::getContext ().error (STRING_HOOK_ERROR_JSON + e); throw 0; } catch (...) { - context.error (STRING_HOOK_ERROR_NOPARSE + i); + Context::getContext ().error (STRING_HOOK_ERROR_NOPARSE + i); throw 0; } } @@ -472,7 +470,7 @@ void Hooks::assertNTasks ( { if (input.size () != n) { - context.error (format (STRING_HOOK_ERROR_BAD_NUM, n, (int) input.size (), Path (script).name ())); + Context::getContext ().error (format (STRING_HOOK_ERROR_BAD_NUM, n, (int) input.size (), Path (script).name ())); throw 0; } } @@ -494,7 +492,7 @@ void Hooks::assertSameTask ( if (u == root_obj->_data.end () || u->second->type () != json::j_string) { - context.error (format (STRING_HOOK_ERROR_SAME1, uuid, Path (script).name ())); + Context::getContext ().error (format (STRING_HOOK_ERROR_SAME1, uuid, Path (script).name ())); throw 0; } @@ -504,7 +502,7 @@ void Hooks::assertSameTask ( std::string json_uuid = json::decode (text); if (json_uuid != uuid) { - context.error (format (STRING_HOOK_ERROR_SAME2, uuid, json_uuid, Path (script).name ())); + Context::getContext ().error (format (STRING_HOOK_ERROR_SAME2, uuid, json_uuid, Path (script).name ())); throw 0; } @@ -524,7 +522,7 @@ void Hooks::assertFeedback ( if (! foundSomething) { - context.error (format (STRING_HOOK_ERROR_NOFEEDBACK, Path (script).name ())); + Context::getContext ().error (format (STRING_HOOK_ERROR_NOFEEDBACK, Path (script).name ())); throw 0; } } @@ -542,13 +540,13 @@ std::vector & Hooks::buildHookScriptArgs (std::vector args.push_back ("args:" + std::string (v)); // Command to be executed. - args.push_back ("command:" + context.cli2.getCommand ()); + args.push_back ("command:" + Context::getContext ().cli2.getCommand ()); // rc file used after applying all overrides. - args.push_back ("rc:" + context.rc_file._data); + args.push_back ("rc:" + Context::getContext ().rc_file._data); // Directory containing *.data files. - args.push_back ("data:" + context.data_dir._data); + args.push_back ("data:" + Context::getContext ().data_dir._data); // Taskwarrior version, same as returned by "task --version" args.push_back ("version:" + std::string(VERSION)); @@ -563,13 +561,13 @@ int Hooks::callHookScript ( std::vector & output) const { if (_debug >= 1) - context.debug ("Hook: Calling " + script); + Context::getContext ().debug ("Hook: Calling " + script); if (_debug >= 2) { - context.debug ("Hook: input"); + Context::getContext ().debug ("Hook: input"); for (const auto& i : input) - context.debug (" " + i); + Context::getContext ().debug (" " + i); } std::string inputStr; @@ -580,9 +578,9 @@ int Hooks::callHookScript ( buildHookScriptArgs (args); if (_debug >= 2) { - context.debug ("Hooks: args"); + Context::getContext ().debug ("Hooks: args"); for (const auto& arg: args) - context.debug (" " + arg); + Context::getContext ().debug (" " + arg); } // Measure time for each hook if running in debug @@ -592,7 +590,7 @@ int Hooks::callHookScript ( { Timer timer; status = execute (script, args, inputStr, outputStr); - context.debugTiming (format ("Hooks::execute ({1})", script), timer); + Context::getContext ().debugTiming (format ("Hooks::execute ({1})", script), timer); } else status = execute (script, args, inputStr, outputStr); @@ -601,13 +599,13 @@ int Hooks::callHookScript ( if (_debug >= 2) { - context.debug ("Hook: output"); + Context::getContext ().debug ("Hook: output"); for (const auto& i : output) if (i != "") - context.debug (" " + i); + Context::getContext ().debug (" " + i); - context.debug (format ("Hook: Completed with status {1}", status)); - context.debug (" "); // Blank line + Context::getContext ().debug (format ("Hook: Completed with status {1}", status)); + Context::getContext ().debug (" "); // Blank line } return status; diff --git a/src/TDB2.cpp b/src/TDB2.cpp index e400216d5..ad3e80f6c 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -44,8 +44,6 @@ #define STRING_TDB2_REVERTED "Modified task reverted." -extern Context context; - bool TDB2::debug_mode = false; //////////////////////////////////////////////////////////////////////////////// @@ -171,7 +169,7 @@ void TF2::add_task (Task& task) _added_tasks.push_back (task); // For commit/synch // For faster lookup - if (context.cli2.getCommand () == "import") + if (Context::getContext ().cli2.getCommand () == "import") _tasks_map.insert (std::pair (task.get("uuid"), task)); Task::status status = task.getStatus (); @@ -180,7 +178,7 @@ void TF2::add_task (Task& task) status == Task::recurring || status == Task::waiting)) { - task.id = context.tdb2.next_id (); + task.id = Context::getContext ().tdb2.next_id (); } _I2U[task.id] = task.get ("uuid"); @@ -194,7 +192,7 @@ bool TF2::modify_task (const Task& task) { std::string uuid = task.get ("uuid"); - if (context.cli2.getCommand () == "import") + if (Context::getContext ().cli2.getCommand () == "import") { // Update map used for faster lookup auto i = _tasks_map.find (uuid); @@ -270,7 +268,7 @@ void TF2::commit () { if (_file.open ()) { - if (context.config.getBoolean ("locking")) + if (Context::getContext ().config.getBoolean ("locking")) _file.lock (); // Write out all the added tasks. @@ -292,7 +290,7 @@ void TF2::commit () { if (_file.open ()) { - if (context.config.getBoolean ("locking")) + if (Context::getContext ().config.getBoolean ("locking")) _file.lock (); // Truncate the file and rewrite. @@ -327,9 +325,9 @@ Task TF2::load_task (const std::string& line) { Task::status status = task.getStatus (); // Completed / deleted tasks in pending.data get an ID if GC is off. - if (! context.run_gc || + if (! Context::getContext ().run_gc || (status != Task::completed && status != Task::deleted)) - task.id = context.tdb2.next_id (); + task.id = Context::getContext ().tdb2.next_id (); } // Maintain mapping for ease of link/dependency resolution. @@ -355,7 +353,7 @@ void TF2::load_gc (Task& task) if (status == "pending" || status == "recurring") { - context.tdb2.pending._tasks.push_back (task); + Context::getContext ().tdb2.pending._tasks.push_back (task); } else if (status == "waiting") { @@ -366,17 +364,17 @@ void TF2::load_gc (Task& task) task.remove ("wait"); // Unwaiting pending tasks is the only case not caught by the size() // checks in TDB2::gc(), so we need to signal it here. - context.tdb2.pending._dirty = true; + Context::getContext ().tdb2.pending._dirty = true; - if (context.verbose ("unwait")) - context.footnote (format ("Un-waiting task '{1}'", task.get ("description"))); + if (Context::getContext ().verbose ("unwait")) + Context::getContext ().footnote (format ("Un-waiting task '{1}'", task.get ("description"))); } - context.tdb2.pending._tasks.push_back (task); + Context::getContext ().tdb2.pending._tasks.push_back (task); } else { - context.tdb2.completed._tasks.push_back (task); + Context::getContext ().tdb2.completed._tasks.push_back (task); } } @@ -411,7 +409,7 @@ void TF2::load_tasks (bool from_gc /* = false */) else _tasks.push_back (task); - if (context.cli2.getCommand () == "import") // For faster lookup only + if (Context::getContext ().cli2.getCommand () == "import") // For faster lookup only _tasks_map.insert (std::pair (task.get("uuid"), task)); } @@ -427,7 +425,7 @@ void TF2::load_tasks (bool from_gc /* = false */) throw e + format (" in {1} at line {2}", _file._data, line_number); } - context.time_load_us += timer.total_us (); + Context::getContext ().time_load_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -435,7 +433,7 @@ void TF2::load_lines () { if (_file.open ()) { - if (context.config.getBoolean ("locking")) + if (Context::getContext ().config.getBoolean ("locking")) _file.lock (); _file.read (_lines); @@ -645,7 +643,7 @@ void TDB2::add (Task& task, bool add_to_backlog /* = true */) // Only locally-added tasks trigger hooks. This means that tasks introduced // via 'sync' do not trigger hooks. if (add_to_backlog) - context.hooks.onAdd (task); + Context::getContext ().hooks.onAdd (task); update (task, add_to_backlog, true); } @@ -662,7 +660,7 @@ void TDB2::modify (Task& task, bool add_to_backlog /* = true */) { Task original; get (uuid, original); - context.hooks.onModify (original, task); + Context::getContext ().hooks.onModify (original, task); } update (task, add_to_backlog); @@ -764,7 +762,7 @@ void TDB2::commit () signal (SIGUSR1, SIG_DFL); signal (SIGUSR2, SIG_DFL); - context.time_commit_us += timer.total_us (); + Context::getContext ().time_commit_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -803,7 +801,7 @@ void TDB2::revert () // Display diff and confirm. show_diff (current, prior, when); - if (! context.config.getBoolean ("confirmation") || + if (! Context::getContext ().config.getBoolean ("confirmation") || confirm ("The undo command is not reversible. Are you sure you want to revert to the previous state?")) { // There are six kinds of change possible. Determine which one, and act @@ -914,7 +912,7 @@ void TDB2::revert_pending ( { if (task->find (uuid_att) != std::string::npos) { - context.debug ("TDB::revert - task found in pending.data"); + Context::getContext ().debug ("TDB::revert - task found in pending.data"); // Either revert if there was a prior state, or remove the task. if (prior != "") @@ -947,7 +945,7 @@ void TDB2::revert_completed ( { if (task->find (uuid_att) != std::string::npos) { - context.debug ("TDB::revert_completed - task found in completed.data"); + Context::getContext ().debug ("TDB::revert_completed - task found in completed.data"); // Either revert if there was a prior state, or remove the task. if (prior != "") @@ -960,12 +958,12 @@ void TDB2::revert_completed ( c.erase (task); p.push_back (prior); std::cout << STRING_TDB2_REVERTED << '\n'; - context.debug ("TDB::revert_completed - task belongs in pending.data"); + Context::getContext ().debug ("TDB::revert_completed - task belongs in pending.data"); } else { std::cout << STRING_TDB2_REVERTED << '\n'; - context.debug ("TDB::revert_completed - task belongs in completed.data"); + Context::getContext ().debug ("TDB::revert_completed - task belongs in completed.data"); } } else @@ -973,7 +971,7 @@ void TDB2::revert_completed ( c.erase (task); std::cout << STRING_TDB2_REVERTED << '\n'; - context.debug ("TDB::revert_completed - task removed"); + Context::getContext ().debug ("TDB::revert_completed - task removed"); } std::cout << "Undo complete.\n"; @@ -996,7 +994,7 @@ void TDB2::revert_backlog ( { if (task->find (uuid_att) != std::string::npos) { - context.debug ("TDB::revert_backlog - task found in backlog.data"); + Context::getContext ().debug ("TDB::revert_backlog - task found in backlog.data"); found = true; // If this is a new task (no prior), then just remove it from the backlog. @@ -1031,10 +1029,10 @@ void TDB2::show_diff ( Datetime lastChange (strtol (when.c_str (), NULL, 10)); // Set the colors. - Color color_red (context.color () ? context.config.get ("color.undo.before") : ""); - Color color_green (context.color () ? context.config.get ("color.undo.after") : ""); + Color color_red (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.before") : ""); + Color color_green (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.after") : ""); - if (context.config.get ("undo.style") == "side") + if (Context::getContext ().config.get ("undo.style") == "side") { std::cout << '\n' << format ("The last modification was made {1}", lastChange.toString ()) @@ -1043,7 +1041,7 @@ void TDB2::show_diff ( // Attributes are all there is, so figure the different attribute names // between before and after. Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.intraPadding (2); view.add (""); view.add ("Prior Values"); @@ -1128,7 +1126,7 @@ void TDB2::show_diff ( // - name: // + name: new // att added // - else if (context.config.get ("undo.style") == "diff") + else if (Context::getContext ().config.get ("undo.style") == "diff") { // Create reference tasks. Task before; @@ -1139,7 +1137,7 @@ void TDB2::show_diff ( // Generate table header. Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.intraPadding (2); view.add (""); view.add (""); @@ -1151,13 +1149,13 @@ void TDB2::show_diff ( row = view.addRow (); view.set (row, 0, "+++ current state ", color_green); view.set (row, 1, format ("Change made {1}", - lastChange.toString (context.config.get ("dateformat"))), + lastChange.toString (Context::getContext ().config.get ("dateformat"))), color_green); view.addRow (); // Add rows to table showing diffs. - std::vector all = context.getColumns (); + std::vector all = Context::getContext ().getColumns (); // Now factor in the annotation attributes. for (auto& it : before.data) @@ -1252,7 +1250,7 @@ void TDB2::gc () Timer timer; // Allowed as an override, but not recommended. - if (context.config.getBoolean ("gc")) + if (Context::getContext ().config.getBoolean ("gc")) { // Load pending, check whether completed changes size auto size_before = completed._tasks.size (); @@ -1286,7 +1284,7 @@ void TDB2::gc () completed.dependency_scan (); } - context.time_gc_us += timer.total_us (); + Context::getContext ().time_gc_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -1463,13 +1461,13 @@ void TDB2::clear () //////////////////////////////////////////////////////////////////////////////// void TDB2::dump () { - if (context.config.getBoolean ("debug")) + if (Context::getContext ().config.getBoolean ("debug")) { - context.debug (pending.dump ()); - context.debug (completed.dump ()); - context.debug (undo.dump ()); - context.debug (backlog.dump ()); - context.debug (" "); + Context::getContext ().debug (pending.dump ()); + Context::getContext ().debug (completed.dump ()); + Context::getContext ().debug (undo.dump ()); + Context::getContext ().debug (backlog.dump ()); + Context::getContext ().debug (" "); } } diff --git a/src/Task.cpp b/src/Task.cpp index ba55eb6c4..bf520e85e 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -60,7 +60,6 @@ #define APPROACHING_INFINITY 1000 // Close enough. This isn't rocket surgery. -extern Context context; extern Task& contextTask; static const float epsilon = 0.000001; @@ -336,7 +335,7 @@ Task::dateState Task::getDateState (const std::string& name) const return dateLaterToday; } - int imminentperiod = context.config.getInteger ("due"); + int imminentperiod = Context::getContext ().config.getInteger ("due"); if (imminentperiod == 0) return dateAfterToday; @@ -519,7 +518,7 @@ bool Task::is_dueyear () const //////////////////////////////////////////////////////////////////////////////// bool Task::is_udaPresent () const { - for (auto& col : context.columns) + for (auto& col : Context::getContext ().columns) if (col.second->is_uda () && has (col.first)) return true; @@ -532,7 +531,7 @@ bool Task::is_orphanPresent () const { for (auto& att : data) if (att.first.compare (0, 11, "annotation_", 11) != 0) - if (context.columns.find (att.first) == context.columns.end ()) + if (Context::getContext ().columns.find (att.first) == Context::getContext ().columns.end ()) return true; return false; @@ -783,7 +782,7 @@ void Task::parseJSON (const json::object* root_obj) << "' with value '" << i.second << "' --> preserved\n"; - context.debug (message.str ()); + Context::getContext ().debug (message.str ()); #endif auto text = i.second->dump (); Lexer::dequote (text); @@ -818,7 +817,7 @@ void Task::parseLegacy (const std::string& line) message << "Invalid fileformat at line '" << line << '\''; - context.debug (message.str ()); + Context::getContext ().debug (message.str ()); #endif throw std::string ("Unrecognized Taskwarrior file format or blank line in data."); break; @@ -962,7 +961,7 @@ std::string Task::composeJSON (bool decorate /*= false*/) const // and Taskserver 1.2.0 is released, the default for // 'json.depends.array' can revert to 'on'. - && context.config.getBoolean ("json.depends.array") + && Context::getContext ().config.getBoolean ("json.depends.array") #endif ) { @@ -1124,14 +1123,14 @@ void Task::setAnnotations (const std::map & annotation void Task::addDependency (int depid) { // Check that id is resolvable. - std::string uuid = context.tdb2.pending.uuid (depid); + std::string uuid = Context::getContext ().tdb2.pending.uuid (depid); if (uuid == "") throw format ("Could not create a dependency on task {1} - not found.", depid); std::string depends = get ("depends"); if (depends.find (uuid) != std::string::npos) { - context.footnote (format ("Task {1} already depends on task {2}.", id, depid)); + Context::getContext ().footnote (format ("Task {1} already depends on task {2}.", id, depid)); return; } @@ -1155,7 +1154,7 @@ void Task::addDependency (const std::string& uuid) else { #ifdef PRODUCT_TASKWARRIOR - context.footnote (format ("Task {1} already depends on task {2}.", get ("uuid"), uuid)); + Context::getContext ().footnote (format ("Task {1} already depends on task {2}.", get ("uuid"), uuid)); #endif return; } @@ -1193,7 +1192,7 @@ void Task::removeDependency (const std::string& uuid) void Task::removeDependency (int id) { std::string depends = get ("depends"); - std::string uuid = context.tdb2.pending.uuid (id); + std::string uuid = Context::getContext ().tdb2.pending.uuid (id); if (uuid != "" && depends.find (uuid) != std::string::npos) removeDependency (uuid); else @@ -1205,7 +1204,7 @@ std::vector Task::getDependencyIDs () const { std::vector all; for (auto& dep : split (get ("depends"), ',')) - all.push_back (context.tdb2.pending.id (dep)); + all.push_back (Context::getContext ().tdb2.pending.id (dep)); return all; } @@ -1223,7 +1222,7 @@ std::vector Task::getDependencyTasks () const for (auto& dep : split (get ("depends"), ',')) { Task task; - context.tdb2.get (dep, task); + Context::getContext ().tdb2.get (dep, task); all.push_back (task); } @@ -1288,7 +1287,7 @@ bool Task::hasTag (const std::string& tag) const #ifdef PRODUCT_TASKWARRIOR if (tag == "UDA") return is_udaPresent (); if (tag == "ORPHAN") return is_orphanPresent (); - if (tag == "LATEST") return id == context.tdb2.latest_id (); + if (tag == "LATEST") return id == Context::getContext ().tdb2.latest_id (); #endif if (tag == "PROJECT") return has ("project"); if (tag == "PRIORITY") return has ("priority"); @@ -1357,7 +1356,7 @@ std::vector Task::getUDAOrphanUUIDs () const std::vector orphans; for (auto& it : data) if (it.first.compare (0, 11, "annotation_", 11) != 0) - if (context.columns.find (it.first) == context.columns.end ()) + if (Context::getContext ().columns.find (it.first) == Context::getContext ().columns.end ()) orphans.push_back (it.first); return orphans; @@ -1574,7 +1573,7 @@ void Task::validate (bool applyDefault /* = true */) if (Task::defaultProject != "" && ! has ("project")) { - if (context.columns["project"]->validate (Task::defaultProject)) + if (Context::getContext ().columns["project"]->validate (Task::defaultProject)) set ("project", Task::defaultProject); } @@ -1582,7 +1581,7 @@ void Task::validate (bool applyDefault /* = true */) if (Task::defaultDue != "" && ! has ("due")) { - if (context.columns["due"]->validate (Task::defaultDue)) + if (Context::getContext ().columns["due"]->validate (Task::defaultDue)) { Duration dur (Task::defaultDue); if (dur.toTime_t () != 0) @@ -1596,7 +1595,7 @@ void Task::validate (bool applyDefault /* = true */) if (Task::defaultScheduled != "" && ! has ("scheduled")) { - if (context.columns["scheduled"]->validate (Task::defaultScheduled)) + if (Context::getContext ().columns["scheduled"]->validate (Task::defaultScheduled)) { Duration dur (Task::defaultScheduled); if (dur.toTime_t () != 0) @@ -1610,7 +1609,7 @@ void Task::validate (bool applyDefault /* = true */) // override with uda.(uda).default, if not specified. // Gather a list of all UDAs with a .default value std::vector udas; - for (auto& var : context.config) + for (auto& var : Context::getContext ().config) { if (! var.first.compare (0, 4, "uda.", 4) && var.first.find (".default") != std::string::npos) @@ -1627,7 +1626,7 @@ void Task::validate (bool applyDefault /* = true */) // of course only if we don't have one on the command line already for (auto& uda : udas) { - std::string defVal= context.config.get ("uda." + uda + ".default"); + std::string defVal= Context::getContext ().config.get ("uda." + uda + ".default"); // If the default is empty, or we already have a value, skip it if (defVal != "" && get (uda) == "") @@ -1687,7 +1686,7 @@ void Task::validate_before (const std::string& left, const std::string& right) // if date is zero, then it is being removed (e.g. "due: wait:1day") if (date_left > date_right && date_right.toEpoch () != 0) - context.footnote (format ("Warning: You have specified that the '{1}' date is after the '{2}' date.", left, right)); + Context::getContext ().footnote (format ("Warning: You have specified that the '{1}' date is after the '{2}' date.", left, right)); } #endif } @@ -1886,7 +1885,7 @@ float Task::urgency_c () const } } - if (is_blocking && context.config.getBoolean ("urgency.inherit")) + if (is_blocking && Context::getContext ().config.getBoolean ("urgency.inherit")) { float prev = value; value = std::max (value, urgency_inherit ()); @@ -2069,7 +2068,7 @@ void Task::modify (modType type, bool text_required /* = false */) std::string text = ""; bool mods = false; - for (auto& a : context.cli2._args) + for (auto& a : Context::getContext ().cli2._args) { if (a.hasTag ("MODIFICATION")) { @@ -2086,22 +2085,22 @@ void Task::modify (modType type, bool text_required /* = false */) // ::composeF4 will skip if the value is blank, but the presence of // the attribute will prevent ::validate from applying defaults. if ((has (name) && get (name) != "") || - (name == "due" && context.config.has ("default.due")) || - (name == "scheduled" && context.config.has ("default.scheduled")) || - (name == "project" && context.config.has ("default.project"))) + (name == "due" && Context::getContext ().config.has ("default.due")) || + (name == "scheduled" && Context::getContext ().config.has ("default.scheduled")) || + (name == "project" && Context::getContext ().config.has ("default.project"))) { mods = true; set (name, ""); } - context.debug (label + name + " <-- ''"); + Context::getContext ().debug (label + name + " <-- ''"); } else { Lexer::dequote (value); // Get the column info. Some columns are not modifiable. - Column* column = context.columns[name]; + Column* column = Context::getContext ().columns[name]; if (! column || ! column->modifiable ()) throw format ("The '{1}' attribute does not allow a value of '{2}'.", name, value); @@ -2127,7 +2126,7 @@ void Task::modify (modType type, bool text_required /* = false */) // Perform description/annotation substitution. else if (a._lextype == Lexer::Type::substitution) { - context.debug (label + "substitute " + a.attribute ("raw")); + Context::getContext ().debug (label + "substitute " + a.attribute ("raw")); substitute (a.attribute ("from"), a.attribute ("to"), a.attribute ("flags")); @@ -2144,13 +2143,13 @@ void Task::modify (modType type, bool text_required /* = false */) if (a.attribute ("sign") == "+") { - context.debug (label + "tags <-- add '" + tag + '\''); + Context::getContext ().debug (label + "tags <-- add '" + tag + '\''); addTag (tag); feedback_special_tags (*this, tag); } else { - context.debug (label + "tags <-- remove '" + tag + '\''); + Context::getContext ().debug (label + "tags <-- remove '" + tag + '\''); removeTag (tag); } @@ -2176,22 +2175,22 @@ void Task::modify (modType type, bool text_required /* = false */) switch (type) { case modReplace: - context.debug (label + "description <-- '" + text + '\''); + Context::getContext ().debug (label + "description <-- '" + text + '\''); set ("description", text); break; case modPrepend: - context.debug (label + "description <-- '" + text + "' + description"); + Context::getContext ().debug (label + "description <-- '" + text + "' + description"); set ("description", text + ' ' + get ("description")); break; case modAppend: - context.debug (label + "description <-- description + '" + text + '\''); + Context::getContext ().debug (label + "description <-- description + '" + text + '\''); set ("description", get ("description") + ' ' + text); break; case modAnnotate: - context.debug (label + "new annotation <-- '" + text + '\''); + Context::getContext ().debug (label + "new annotation <-- '" + text + '\''); addAnnotation (text); break; } @@ -2205,7 +2204,7 @@ void Task::modify (modType type, bool text_required /* = false */) getStatus () == originalStatus) { auto uuid = get ("uuid").substr (0, 8); - context.footnote (format ("Note: Modified task {1} is {2}. You may wish to make this task pending with: task {3} modify status:pending", uuid, get ("status"), uuid)); + Context::getContext ().footnote (format ("Note: Modified task {1} is {2}. You may wish to make this task pending with: task {3} modify status:pending", uuid, get ("status"), uuid)); } } #endif diff --git a/src/ViewTask.cpp b/src/ViewTask.cpp index 9ef8ba3fa..1ae01d711 100644 --- a/src/ViewTask.cpp +++ b/src/ViewTask.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// ViewTask::ViewTask () : _width (0) @@ -112,8 +110,8 @@ std::string ViewTask::render (std::vector & data, std::vector & seque { Timer timer; - bool const obfuscate = context.config.getBoolean ("obfuscate"); - bool const print_empty_columns = context.config.getBoolean ("print.empty.columns"); + bool const obfuscate = Context::getContext ().config.getBoolean ("obfuscate"); + bool const print_empty_columns = Context::getContext ().config.getBoolean ("print.empty.columns"); std::vector nonempty_columns; std::vector nonempty_sort; @@ -190,11 +188,11 @@ std::string ViewTask::render (std::vector & data, std::vector & seque // Calculate final column widths. int overage = _width - sum_minimal - all_extra; - context.debug (format ("ViewTask::render min={1} ideal={2} overage={3} width={4}", - sum_minimal + all_extra, - sum_ideal + all_extra, - overage, - _width)); + Context::getContext ().debug (format ("ViewTask::render min={1} ideal={2} overage={3} width={4}", + sum_minimal + all_extra, + sum_ideal + all_extra, + overage, + _width)); std::vector widths; @@ -207,7 +205,7 @@ std::string ViewTask::render (std::vector & data, std::vector & seque // Not enough for minimum. else if (overage < 0) { - context.error (format ("The report has a minimum width of {1} and does not fit in the available width of {2}.", sum_minimal + all_extra, _width)); + Context::getContext ().error (format ("The report has a minimum width of {1} and does not fit in the available width of {2}.", sum_minimal + all_extra, _width)); widths = minimal; } @@ -256,10 +254,10 @@ std::string ViewTask::render (std::vector & data, std::vector & seque std::string extra = std::string (_extra_padding, ' '); std::string intra = std::string (_intra_padding, ' '); - std::string extra_odd = context.color () ? _extra_odd.colorize (extra) : extra; - std::string extra_even = context.color () ? _extra_even.colorize (extra) : extra; - std::string intra_odd = context.color () ? _intra_odd.colorize (intra) : intra; - std::string intra_even = context.color () ? _intra_even.colorize (intra) : intra; + std::string extra_odd = Context::getContext ().color () ? _extra_odd.colorize (extra) : extra; + std::string extra_even = Context::getContext ().color () ? _extra_even.colorize (extra) : extra; + std::string intra_odd = Context::getContext ().color () ? _intra_odd.colorize (intra) : intra; + std::string intra_even = Context::getContext ().color () ? _intra_even.colorize (intra) : intra; std::string out; _lines = 0; @@ -287,7 +285,7 @@ std::string ViewTask::render (std::vector & data, std::vector & seque // Stop if the line limit is exceeded. if (++_lines >= _truncate_lines && _truncate_lines != 0) { - context.time_render_us += timer.total_us (); + Context::getContext ().time_render_us += timer.total_us (); return out; } } @@ -306,7 +304,7 @@ std::string ViewTask::render (std::vector & data, std::vector & seque // Alternate rows based on |s % 2| bool odd = (s % 2) ? true : false; Color row_color; - if (context.color ()) + if (Context::getContext ().color ()) { row_color = odd ? _odd : _even; row_color.blend (rule_color); @@ -373,7 +371,7 @@ std::string ViewTask::render (std::vector & data, std::vector & seque // Stop if the line limit is exceeded. if (++_lines >= _truncate_lines && _truncate_lines != 0) { - context.time_render_us += timer.total_us (); + Context::getContext ().time_render_us += timer.total_us (); return out; } } @@ -383,12 +381,12 @@ std::string ViewTask::render (std::vector & data, std::vector & seque // Stop if the row limit is exceeded. if (++_rows >= _truncate_rows && _truncate_rows != 0) { - context.time_render_us += timer.total_us (); + Context::getContext ().time_render_us += timer.total_us (); return out; } } - context.time_render_us += timer.total_us (); + Context::getContext ().time_render_us += timer.total_us (); return out; } diff --git a/src/calc.cpp b/src/calc.cpp index 837cced10..919764e55 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -37,8 +37,6 @@ #include #include -Context context; - //////////////////////////////////////////////////////////////////////////////// // Constants. bool get (const std::string&, Variant&) @@ -58,6 +56,9 @@ int main (int argc, char** argv) try { + Context globalContext; + Context::setContext (&globalContext); + // Same operating parameters as Context::staticInitialization. Datetime::standaloneDateEnabled = false; Datetime::standaloneTimeEnabled = false; @@ -118,7 +119,7 @@ int main (int argc, char** argv) e.evaluatePostfixExpression (expression, result); // Show any debug output. - for (const auto& i : context.debugMessages) + for (const auto& i : Context::getContext ().debugMessages) std::cout << i << '\n'; // Show the result in string form. diff --git a/src/columns/ColDepends.cpp b/src/columns/ColDepends.cpp index c74fdb2b9..91d243910 100644 --- a/src/columns/ColDepends.cpp +++ b/src/columns/ColDepends.cpp @@ -36,8 +36,6 @@ #define STRING_COLUMN_LABEL_DEP "Depends" -extern Context context; - //////////////////////////////////////////////////////////////////////////////// ColumnDepends::ColumnDepends () { @@ -49,7 +47,7 @@ ColumnDepends::ColumnDepends () "indicator"}; _examples = {"1 2 10", "[3]", - context.config.get ("dependency.indicator")}; + Context::getContext ().config.get ("dependency.indicator")}; _hyphenate = false; } @@ -61,7 +59,7 @@ void ColumnDepends::setStyle (const std::string& value) { Column::setStyle (value); - if (_style == "indicator" && _label == STRING_COLUMN_LABEL_DEP) _label = _label.substr (0, context.config.get ("dependency.indicator").length ()); + if (_style == "indicator" && _label == STRING_COLUMN_LABEL_DEP) _label = _label.substr (0, Context::getContext ().config.get ("dependency.indicator").length ()); else if (_style == "count" && _label == STRING_COLUMN_LABEL_DEP) _label = "Dep"; } @@ -74,7 +72,7 @@ void ColumnDepends::measure (Task& task, unsigned int& minimum, unsigned int& ma { if (_style == "indicator") { - minimum = maximum = utf8_width (context.config.get ("dependency.indicator")); + minimum = maximum = utf8_width (Context::getContext ().config.get ("dependency.indicator")); } else if (_style == "count") @@ -117,7 +115,7 @@ void ColumnDepends::render ( { if (_style == "indicator") { - renderStringRight (lines, width, color, context.config.get ("dependency.indicator")); + renderStringRight (lines, width, color, Context::getContext ().config.get ("dependency.indicator")); } else if (_style == "count") diff --git a/src/columns/ColDescription.cpp b/src/columns/ColDescription.cpp index 98187b798..c26a97308 100644 --- a/src/columns/ColDescription.cpp +++ b/src/columns/ColDescription.cpp @@ -34,8 +34,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// ColumnDescription::ColumnDescription () { @@ -51,9 +49,9 @@ ColumnDescription::ColumnDescription () "count", "truncated_count"}; - _dateformat = context.config.get ("dateformat.annotation"); + _dateformat = Context::getContext ().config.get ("dateformat.annotation"); if (_dateformat == "") - _dateformat = context.config.get ("dateformat"); + _dateformat = Context::getContext ().config.get ("dateformat"); std::string t = Datetime ().toString (_dateformat); std::string d = "Move your clothes down on to the lower peg"; @@ -75,9 +73,9 @@ ColumnDescription::ColumnDescription () d + " [4]", d.substr (0, 20) + "... [4]"}; - _hyphenate = context.config.getBoolean ("hyphenate"); + _hyphenate = Context::getContext ().config.getBoolean ("hyphenate"); - _indent = context.config.getInteger ("indent.annotation"); + _indent = Context::getContext ().config.getInteger ("indent.annotation"); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColProject.cpp b/src/columns/ColProject.cpp index b29d9309c..af011ea42 100644 --- a/src/columns/ColProject.cpp +++ b/src/columns/ColProject.cpp @@ -36,7 +36,6 @@ #include #include -extern Context context; extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// @@ -49,7 +48,7 @@ ColumnProject::ColumnProject () _examples = {"home.garden", "home", " home.garden"}; - _hyphenate = context.config.getBoolean ("hyphenate"); + _hyphenate = Context::getContext ().config.getBoolean ("hyphenate"); } //////////////////////////////////////////////////////////////////////////////// @@ -127,7 +126,7 @@ void ColumnProject::modify (Task& task, const std::string& value) Variant v; e.evaluateInfixExpression (value, v); task.set (_name, (std::string) v); - context.debug (label + _name + " <-- '" + (std::string) v + "' <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + (std::string) v + "' <-- '" + value + '\''); } catch (const std::string& e) { @@ -136,7 +135,7 @@ void ColumnProject::modify (Task& task, const std::string& value) if (e == "The value is not an expression.") { task.set (_name, value); - context.debug (label + _name + " <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + value + '\''); } else throw; @@ -145,7 +144,7 @@ void ColumnProject::modify (Task& task, const std::string& value) else { task.set (_name, value); - context.debug (label + _name + " <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + value + '\''); } } diff --git a/src/columns/ColRType.cpp b/src/columns/ColRType.cpp index d64267712..917d931a7 100644 --- a/src/columns/ColRType.cpp +++ b/src/columns/ColRType.cpp @@ -31,8 +31,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// ColumnRType::ColumnRType () { @@ -52,7 +50,7 @@ void ColumnRType::setStyle (const std::string& value) Column::setStyle (value); if (_style == "indicator" && _label == "Recurrence type") - _label = _label.substr (0, context.config.get ("rtype.indicator").length ()); + _label = _label.substr (0, Context::getContext ().config.get ("rtype.indicator").length ()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColRecur.cpp b/src/columns/ColRecur.cpp index 28ac58e79..a70a9cb5d 100644 --- a/src/columns/ColRecur.cpp +++ b/src/columns/ColRecur.cpp @@ -36,7 +36,6 @@ #include #include -extern Context context; extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// @@ -47,7 +46,7 @@ ColumnRecur::ColumnRecur () _label = "Recur"; _modifiable = true; _styles = {"duration", "indicator"}; - _examples = {"weekly", context.config.get ("recurrence.indicator")}; + _examples = {"weekly", Context::getContext ().config.get ("recurrence.indicator")}; } //////////////////////////////////////////////////////////////////////////////// @@ -58,7 +57,7 @@ void ColumnRecur::setStyle (const std::string& value) Column::setStyle (value); if (_style == "indicator" && _label == "Recur") - _label = _label.substr (0, context.config.get ("recurrence.indicator").length ()); + _label = _label.substr (0, Context::getContext ().config.get ("recurrence.indicator").length ()); } //////////////////////////////////////////////////////////////////////////////// @@ -75,7 +74,7 @@ void ColumnRecur::measure (Task& task, unsigned int& minimum, unsigned int& maxi } else if (_style == "indicator") { - minimum = maximum = utf8_width (context.config.get ("recurrence.indicator")); + minimum = maximum = utf8_width (Context::getContext ().config.get ("recurrence.indicator")); } } } @@ -94,7 +93,7 @@ void ColumnRecur::render ( renderStringRight (lines, width, color, Duration (task.get (_name)).formatISO ()); else if (_style == "indicator") - renderStringRight (lines, width, color, context.config.get ("recurrence.indicator")); + renderStringRight (lines, width, color, Context::getContext ().config.get ("recurrence.indicator")); } } @@ -122,7 +121,7 @@ void ColumnRecur::modify (Task& task, const std::string& value) { // Store the raw value, for 'recur'. std::string label = " MODIFICATION "; - context.debug (label + _name + " <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + value + '\''); task.set (_name, value); } else diff --git a/src/columns/ColStart.cpp b/src/columns/ColStart.cpp index 056873790..833b59448 100644 --- a/src/columns/ColStart.cpp +++ b/src/columns/ColStart.cpp @@ -29,8 +29,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// ColumnStart::ColumnStart () { @@ -38,7 +36,7 @@ ColumnStart::ColumnStart () _label = "Started"; _styles.push_back ("active"); - _examples.push_back (context.config.get ("active.indicator")); + _examples.push_back (Context::getContext ().config.get ("active.indicator")); } //////////////////////////////////////////////////////////////////////////////// @@ -60,7 +58,7 @@ void ColumnStart::measure (Task& task, unsigned int& minimum, unsigned int& maxi if (task.has (_name)) { if (_style == "active") - minimum = maximum = utf8_width (context.config.get ("active.indicator")); + minimum = maximum = utf8_width (Context::getContext ().config.get ("active.indicator")); else ColumnTypeDate::measure (task, minimum, maximum); @@ -80,7 +78,7 @@ void ColumnStart::render ( if (_style == "active") { if (! task.has ("end")) - renderStringRight (lines, width, color, context.config.get ("active.indicator")); + renderStringRight (lines, width, color, Context::getContext ().config.get ("active.indicator")); } else ColumnTypeDate::render (lines, task, width, color); diff --git a/src/columns/ColTags.cpp b/src/columns/ColTags.cpp index d4a654517..185c83316 100644 --- a/src/columns/ColTags.cpp +++ b/src/columns/ColTags.cpp @@ -36,7 +36,6 @@ #include #include -extern Context context; extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// @@ -47,7 +46,7 @@ ColumnTags::ColumnTags () _label = "Tags"; _styles = {"list", "indicator", "count"}; _examples = {"home @chore next", - context.config.get ("tag.indicator"), + Context::getContext ().config.get ("tag.indicator"), "[2]"}; _hyphenate = false; } @@ -61,7 +60,7 @@ void ColumnTags::setStyle (const std::string& value) if (_style == "indicator" && _label == "Tags") - _label = _label.substr (0, context.config.get ("tag.indicator").length ()); + _label = _label.substr (0, Context::getContext ().config.get ("tag.indicator").length ()); else if (_style == "count" && _label == "Tags") @@ -77,7 +76,7 @@ void ColumnTags::measure (Task& task, unsigned int& minimum, unsigned int& maxim { if (_style == "indicator") { - minimum = maximum = utf8_width (context.config.get ("tag.indicator")); + minimum = maximum = utf8_width (Context::getContext ().config.get ("tag.indicator")); } else if (_style == "count") { @@ -139,7 +138,7 @@ void ColumnTags::render ( } else if (_style == "indicator") { - renderStringRight (lines, width, color, context.config.get ("tag.indicator")); + renderStringRight (lines, width, color, Context::getContext ().config.get ("tag.indicator")); } else if (_style == "count") { @@ -173,12 +172,12 @@ void ColumnTags::modify (Task& task, const std::string& value) Variant v; e.evaluateInfixExpression (value, v); task.addTag ((std::string) v); - context.debug (label + "tags <-- '" + (std::string) v + "' <-- '" + tag + '\''); + Context::getContext ().debug (label + "tags <-- '" + (std::string) v + "' <-- '" + tag + '\''); } else { task.addTag (tag); - context.debug (label + "tags <-- '" + tag + '\''); + Context::getContext ().debug (label + "tags <-- '" + tag + '\''); } feedback_special_tags (task, tag); diff --git a/src/columns/ColTypeDate.cpp b/src/columns/ColTypeDate.cpp index 2502784a7..4aeaa0db1 100644 --- a/src/columns/ColTypeDate.cpp +++ b/src/columns/ColTypeDate.cpp @@ -34,7 +34,6 @@ #include #include -extern Context context; extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// @@ -55,7 +54,7 @@ ColumnTypeDate::ColumnTypeDate () Datetime now; now -= 125; // So that "age" is non-zero. - _examples = {now.toString (context.config.get ("dateformat")), + _examples = {now.toString (Context::getContext ().config.get ("dateformat")), format (now.toJulian (), 13, 12), now.toEpochString (), now.toISO (), @@ -81,11 +80,11 @@ void ColumnTypeDate::measure (Task& task, unsigned int& minimum, unsigned int& m // rc.report..dateformat // rc.dateformat.report // rc.dateformat. - std::string format = context.config.get ("report." + _report + ".dateformat"); + std::string format = Context::getContext ().config.get ("report." + _report + ".dateformat"); if (format == "") - format = context.config.get ("dateformat.report"); + format = Context::getContext ().config.get ("dateformat.report"); if (format == "") - format = context.config.get ("dateformat"); + format = Context::getContext ().config.get ("dateformat"); minimum = maximum = Datetime::length (format); } @@ -149,12 +148,12 @@ void ColumnTypeDate::render ( // rc.report..dateformat // rc.dateformat.report // rc.dateformat - std::string format = context.config.get ("report." + _report + ".dateformat"); + std::string format = Context::getContext ().config.get ("report." + _report + ".dateformat"); if (format == "") { - format = context.config.get ("dateformat.report"); + format = Context::getContext ().config.get ("dateformat.report"); if (format == "") - format = context.config.get ("dateformat"); + format = Context::getContext ().config.get ("dateformat"); } renderStringLeft (lines, width, color, date.toString (format)); @@ -227,7 +226,7 @@ void ColumnTypeDate::modify (Task& task, const std::string& value) std::string label = " MODIFICATION "; if (evaluatedValue.type () == Variant::type_duration) { - context.debug (label + _name + " <-- '" + format ("{1}", format (evaluatedValue.get_duration ())) + "' <-- '" + (std::string) evaluatedValue + "' <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + format ("{1}", format (evaluatedValue.get_duration ())) + "' <-- '" + (std::string) evaluatedValue + "' <-- '" + value + '\''); Datetime date_now; Variant now (date_now.toEpoch (), Variant::type_date); evaluatedValue += now; @@ -235,7 +234,7 @@ void ColumnTypeDate::modify (Task& task, const std::string& value) else { evaluatedValue.cast (Variant::type_date); - context.debug (label + _name + " <-- '" + format ("{1}", evaluatedValue.get_date ()) + "' <-- '" + (std::string) evaluatedValue + "' <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + format ("{1}", evaluatedValue.get_date ()) + "' <-- '" + (std::string) evaluatedValue + "' <-- '" + value + '\''); } // If a date doesn't parse (2/29/2014) then it evaluates to zero. diff --git a/src/columns/ColTypeDuration.cpp b/src/columns/ColTypeDuration.cpp index a869dcfc5..bfd2d2051 100644 --- a/src/columns/ColTypeDuration.cpp +++ b/src/columns/ColTypeDuration.cpp @@ -32,7 +32,6 @@ #include #include -extern Context context; extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// @@ -71,7 +70,7 @@ void ColumnTypeDuration::modify (Task& task, const std::string& value) if (evaluatedValue.type () == Variant::type_duration) { // Store the raw value, for 'recur'. - context.debug (label + _name + " <-- " + (std::string) evaluatedValue + " <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- " + (std::string) evaluatedValue + " <-- '" + value + '\''); task.set (_name, evaluatedValue); } else diff --git a/src/columns/ColTypeNumeric.cpp b/src/columns/ColTypeNumeric.cpp index 5d72a269f..033381ca5 100644 --- a/src/columns/ColTypeNumeric.cpp +++ b/src/columns/ColTypeNumeric.cpp @@ -32,7 +32,6 @@ #include #include -extern Context context; extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// @@ -66,7 +65,7 @@ void ColumnTypeNumeric::modify (Task& task, const std::string& value) } std::string label = " MODIFICATION "; - context.debug (label + _name + " <-- '" + evaluatedValue.get_string () + "' <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + evaluatedValue.get_string () + "' <-- '" + value + '\''); // If the result is not readily convertible to a numeric value, then this is // an error. diff --git a/src/columns/ColTypeString.cpp b/src/columns/ColTypeString.cpp index 0b1a79771..f6d5e8933 100644 --- a/src/columns/ColTypeString.cpp +++ b/src/columns/ColTypeString.cpp @@ -34,7 +34,6 @@ #define STRING_INVALID_MOD "The '{1}' attribute does not allow a value of '{2}'." -extern Context context; extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// @@ -71,7 +70,7 @@ void ColumnTypeString::modify (Task& task, const std::string& value) if (validate (strValue)) { task.set (_name, strValue); - context.debug (label + _name + " <-- '" + strValue + "' <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + strValue + "' <-- '" + value + '\''); } else throw format (STRING_INVALID_MOD, _name, value); @@ -81,7 +80,7 @@ void ColumnTypeString::modify (Task& task, const std::string& value) if (validate (value)) { task.set (_name, value); - context.debug (label + _name + " <-- '" + value + '\''); + Context::getContext ().debug (label + _name + " <-- '" + value + '\''); } else throw format (STRING_INVALID_MOD, _name, value); diff --git a/src/columns/ColUDA.cpp b/src/columns/ColUDA.cpp index 463b3ef9d..7a36812e7 100644 --- a/src/columns/ColUDA.cpp +++ b/src/columns/ColUDA.cpp @@ -34,8 +34,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// ColumnUDAString::ColumnUDAString () { @@ -84,7 +82,7 @@ void ColumnUDAString::measure (Task& task, unsigned int& minimum, unsigned int& } else if (_style == "indicator") { - auto indicator = context.config.get ("uda." + _name + ".indicator"); + auto indicator = Context::getContext ().config.get ("uda." + _name + ".indicator"); if (indicator == "") indicator = "U"; @@ -113,7 +111,7 @@ void ColumnUDAString::render ( } else if (_style == "indicator") { - auto indicator = context.config.get ("uda." + _name + ".indicator"); + auto indicator = Context::getContext ().config.get ("uda." + _name + ".indicator"); if (indicator == "") indicator = "U"; @@ -165,7 +163,7 @@ void ColumnUDANumeric::measure (Task& task, unsigned int& minimum, unsigned int& } else if (_style == "indicator") { - auto indicator = context.config.get ("uda." + _name + ".indicator"); + auto indicator = Context::getContext ().config.get ("uda." + _name + ".indicator"); if (indicator == "") indicator = "U"; @@ -190,7 +188,7 @@ void ColumnUDANumeric::render ( } else if (_style == "indicator") { - auto indicator = context.config.get ("uda." + _name + ".indicator"); + auto indicator = Context::getContext ().config.get ("uda." + _name + ".indicator"); if (indicator == "") indicator = "U"; @@ -244,18 +242,18 @@ void ColumnUDADate::measure (Task& task, unsigned int& minimum, unsigned int& ma // rc.dateformat.report // rc.dateformat Datetime date ((time_t) strtol (value.c_str (), NULL, 10)); - auto format = context.config.get ("report." + _report + ".dateformat"); + auto format = Context::getContext ().config.get ("report." + _report + ".dateformat"); if (format == "") - format = context.config.get ("dateformat.report"); + format = Context::getContext ().config.get ("dateformat.report"); if (format == "") - format = context.config.get ("dateformat"); + format = Context::getContext ().config.get ("dateformat"); minimum = maximum = Datetime::length (format); } } else if (_style == "indicator") { - auto indicator = context.config.get ("uda." + _name + ".indicator"); + auto indicator = Context::getContext ().config.get ("uda." + _name + ".indicator"); if (indicator == "") indicator = "U"; @@ -281,19 +279,19 @@ void ColumnUDADate::render ( // rc.report..dateformat // rc.dateformat.report // rc.dateformat. - auto format = context.config.get ("report." + _report + ".dateformat"); + auto format = Context::getContext ().config.get ("report." + _report + ".dateformat"); if (format == "") { - format = context.config.get ("dateformat.report"); + format = Context::getContext ().config.get ("dateformat.report"); if (format == "") - format = context.config.get ("dateformat"); + format = Context::getContext ().config.get ("dateformat"); } renderStringLeft (lines, width, color, Datetime ((time_t) strtol (value.c_str (), NULL, 10)).toString (format)); } else if (_style == "indicator") { - auto indicator = context.config.get ("uda." + _name + ".indicator"); + auto indicator = Context::getContext ().config.get ("uda." + _name + ".indicator"); if (indicator == "") indicator = "U"; @@ -347,7 +345,7 @@ void ColumnUDADuration::measure (Task& task, unsigned int& minimum, unsigned int { if (task.has (_name)) { - auto indicator = context.config.get ("uda." + _name + ".indicator"); + auto indicator = Context::getContext ().config.get ("uda." + _name + ".indicator"); if (indicator == "") indicator = "U"; @@ -375,7 +373,7 @@ void ColumnUDADuration::render ( } else if (_style == "indicator") { - auto indicator = context.config.get ("uda." + _name + ".indicator"); + auto indicator = Context::getContext ().config.get ("uda." + _name + ".indicator"); if (indicator == "") indicator = "U"; diff --git a/src/columns/Column.cpp b/src/columns/Column.cpp index 9ade676e7..2a2fd5285 100644 --- a/src/columns/Column.cpp +++ b/src/columns/Column.cpp @@ -56,8 +56,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// // Supports the complete column definition: // @@ -106,7 +104,7 @@ Column* Column::factory (const std::string& name, const std::string& report) else if (column_name == "wait") c = new ColumnWait (); // UDA. - else if (context.config.has ("uda." + column_name + ".type")) + else if (Context::getContext ().config.has ("uda." + column_name + ".type")) c = Column::uda (column_name); else @@ -156,7 +154,7 @@ void Column::uda (std::map & all) // For each UDA, instantiate and initialize ColumnUDA. std::set udas; - for (const auto& i : context.config) + for (const auto& i : Context::getContext ().config) { if (i.first.substr (0, 4) == "uda.") { @@ -181,9 +179,9 @@ void Column::uda (std::map & all) //////////////////////////////////////////////////////////////////////////////// Column* Column::uda (const std::string& name) { - auto type = context.config.get ("uda." + name + ".type"); - auto label = context.config.get ("uda." + name + ".label"); - auto values = context.config.get ("uda." + name + ".values"); + auto type = Context::getContext ().config.get ("uda." + name + ".type"); + auto label = Context::getContext ().config.get ("uda." + name + ".label"); + auto values = Context::getContext ().config.get ("uda." + name + ".values"); if (type == "string") { @@ -251,7 +249,7 @@ void Column::renderHeader ( int width, Color& color) { - if (context.verbose ("label") && + if (Context::getContext ().verbose ("label") && _label != "") { // Create a basic label. @@ -263,8 +261,8 @@ void Column::renderHeader ( Color c = color; // Now underline the header, or add a dashed line. - if (context.color () && - context.config.getBoolean ("fontunderline")) + if (Context::getContext ().color () && + Context::getContext ().config.getBoolean ("fontunderline")) { c.blend (Color (Color::nocolor, Color::nocolor, true, false, false)); lines.push_back (c.colorize (leftJustify (header, width))); diff --git a/src/commands/CmdAdd.cpp b/src/commands/CmdAdd.cpp index 394f0cfbb..9f3335a0f 100644 --- a/src/commands/CmdAdd.cpp +++ b/src/commands/CmdAdd.cpp @@ -30,8 +30,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdAdd::CmdAdd () { @@ -54,7 +52,7 @@ int CmdAdd::execute (std::string& output) // Apply the command line modifications to the new task. Task task; task.modify (Task::modReplace, true); - context.tdb2.add (task); + Context::getContext ().tdb2.add (task); // Do not display ID 0, users cannot query by that auto status = task.getStatus (); @@ -64,25 +62,25 @@ int CmdAdd::execute (std::string& output) // it's enduring and never changes, and it's unlikely the caller // asked for this if they just wanted a human-friendly number. - if (context.verbose ("new-uuid") && + if (Context::getContext ().verbose ("new-uuid") && status != Task::recurring) output += format ("Created task {1}.\n", task.get ("uuid")); - else if (context.verbose ("new-uuid") && + else if (Context::getContext ().verbose ("new-uuid") && status == Task::recurring) output += format ("Created task {1} (recurrence template).\n", task.get ("uuid")); - else if (context.verbose ("new-id") && + else if (Context::getContext ().verbose ("new-id") && (status == Task::pending || status == Task::waiting)) output += format ("Created task {1}.\n", task.id); - else if (context.verbose ("new-id") && + else if (Context::getContext ().verbose ("new-id") && status == Task::recurring) output += format ("Created task {1} (recurrence template).\n", task.id); - if (context.verbose ("project")) - context.footnote (onProjectChange (task)); + if (Context::getContext ().verbose ("project")) + Context::getContext ().footnote (onProjectChange (task)); return 0; } diff --git a/src/commands/CmdAliases.cpp b/src/commands/CmdAliases.cpp index 32985fa06..b6004e3df 100644 --- a/src/commands/CmdAliases.cpp +++ b/src/commands/CmdAliases.cpp @@ -29,8 +29,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdCompletionAliases::CmdCompletionAliases () { @@ -50,7 +48,7 @@ CmdCompletionAliases::CmdCompletionAliases () //////////////////////////////////////////////////////////////////////////////// int CmdCompletionAliases::execute (std::string& output) { - for (const auto& alias : context.config) + for (const auto& alias : Context::getContext ().config) if (alias.first.substr (0, 6) == "alias.") output += alias.first.substr (6) + '\n'; diff --git a/src/commands/CmdAnnotate.cpp b/src/commands/CmdAnnotate.cpp index 40b5ba1a0..0c27f02bb 100644 --- a/src/commands/CmdAnnotate.cpp +++ b/src/commands/CmdAnnotate.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdAnnotate::CmdAnnotate () { @@ -63,7 +61,7 @@ int CmdAnnotate::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -85,33 +83,33 @@ int CmdAnnotate::execute (std::string&) if (permission (taskDifferences (before, task) + question, filtered.size ())) { - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); ++count; feedback_affected ("Annotating task {1} '{2}'.", task); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task, false); // Annotate siblings. if (task.has ("parent")) { - if ((context.config.get ("recurrence.confirmation") == "prompt" + if ((Context::getContext ().config.get ("recurrence.confirmation") == "prompt" && confirm ("This is a recurring task. Do you want to annotate all pending recurrences of this same task?")) || - context.config.getBoolean ("recurrence.confirmation")) + Context::getContext ().config.getBoolean ("recurrence.confirmation")) { - auto siblings = context.tdb2.siblings (task); + auto siblings = Context::getContext ().tdb2.siblings (task); for (auto& sibling : siblings) { sibling.modify (Task::modAnnotate, true); - context.tdb2.modify (sibling); + Context::getContext ().tdb2.modify (sibling); ++count; feedback_affected ("Annotating recurring task {1} '{2}'.", sibling); } // Annotate the parent Task parent; - context.tdb2.get (task.get ("parent"), parent); + Context::getContext ().tdb2.get (task.get ("parent"), parent); parent.modify (Task::modAnnotate, true); - context.tdb2.modify (parent); + Context::getContext ().tdb2.modify (parent); } } } @@ -127,7 +125,7 @@ int CmdAnnotate::execute (std::string&) // Now list the project changes. for (const auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Annotated {1} task." : "Annotated {1} tasks.", count); return rc; diff --git a/src/commands/CmdAppend.cpp b/src/commands/CmdAppend.cpp index 1579114fb..93f7369c5 100644 --- a/src/commands/CmdAppend.cpp +++ b/src/commands/CmdAppend.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdAppend::CmdAppend () { @@ -63,7 +61,7 @@ int CmdAppend::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -85,33 +83,33 @@ int CmdAppend::execute (std::string&) if (permission (taskDifferences (before, task) + question, filtered.size ())) { - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); ++count; feedback_affected ("Appending to task {1} '{2}'.", task); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task, false); // Append to siblings. if (task.has ("parent")) { - if ((context.config.get ("recurrence.confirmation") == "prompt" + if ((Context::getContext ().config.get ("recurrence.confirmation") == "prompt" && confirm ("This is a recurring task. Do you want to append to all pending recurrences of this same task?")) || - context.config.getBoolean ("recurrence.confirmation")) + Context::getContext ().config.getBoolean ("recurrence.confirmation")) { - std::vector siblings = context.tdb2.siblings (task); + std::vector siblings = Context::getContext ().tdb2.siblings (task); for (auto& sibling : siblings) { sibling.modify (Task::modAppend, true); - context.tdb2.modify (sibling); + Context::getContext ().tdb2.modify (sibling); ++count; feedback_affected ("Appending to recurring task {1} '{2}'.", sibling); } // Append to the parent Task parent; - context.tdb2.get (task.get ("parent"), parent); + Context::getContext ().tdb2.get (task.get ("parent"), parent); parent.modify (Task::modAppend, true); - context.tdb2.modify (parent); + Context::getContext ().tdb2.modify (parent); } } } @@ -127,7 +125,7 @@ int CmdAppend::execute (std::string&) // Now list the project changes. for (const auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Appended {1} task." : "Appended {1} tasks.", count); return rc; diff --git a/src/commands/CmdAttributes.cpp b/src/commands/CmdAttributes.cpp index 4abc53a9d..b50bd221f 100644 --- a/src/commands/CmdAttributes.cpp +++ b/src/commands/CmdAttributes.cpp @@ -31,8 +31,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdZshAttributes::CmdZshAttributes () { @@ -53,7 +51,7 @@ CmdZshAttributes::CmdZshAttributes () int CmdZshAttributes::execute (std::string& output) { // Get a list of all columns, sort them. - auto columns = context.getColumns (); + auto columns = Context::getContext ().getColumns (); std::sort (columns.begin (), columns.end ()); std::stringstream out; diff --git a/src/commands/CmdBurndown.cpp b/src/commands/CmdBurndown.cpp index 01b8a1d4b..a40cadb00 100644 --- a/src/commands/CmdBurndown.cpp +++ b/src/commands/CmdBurndown.cpp @@ -40,8 +40,6 @@ #include #include -extern Context context; - // Helper macro. #define LOC(y,x) (((y) * (_width + 1)) + (x)) @@ -174,8 +172,8 @@ Chart::Chart (char type) { // How much space is there to render in? This chart will occupy the // maximum space, and the width drives various other parameters. - _width = context.getWidth (); - _height = context.getHeight () - 1; // Allow for new line with prompt. + _width = Context::getContext ().getWidth (); + _height = Context::getContext ().getHeight () - 1; // Allow for new line with prompt. _max_value = 0; _max_label = 1; _graph_height = _height - 7; @@ -193,7 +191,7 @@ Chart::Chart (char type) _net_fix_rate = 0.0; // Set the title. - std::vector words = context.cli2.getWords (); + std::vector words = Context::getContext ().cli2.getWords (); auto filter = join (" ", words); _title = '(' + filter + ')'; } @@ -396,7 +394,7 @@ std::string Chart::render () } if (_max_value == 0) - context.footnote ("No matches."); + Context::getContext ().footnote ("No matches."); // Create a grid, folded into a string. _grid = ""; @@ -520,12 +518,12 @@ std::string Chart::render () optimizeGrid (); - if (context.color ()) + if (Context::getContext ().color ()) { // Colorize the grid. - Color color_pending (context.config.get ("color.burndown.pending")); - Color color_done (context.config.get ("color.burndown.done")); - Color color_started (context.config.get ("color.burndown.started")); + Color color_pending (Context::getContext ().config.get ("color.burndown.pending")); + Color color_done (Context::getContext ().config.get ("color.burndown.done")); + Color color_started (Context::getContext ().config.get ("color.burndown.started")); // Replace DD, SS, PP with colored strings. std::string::size_type i; @@ -799,7 +797,7 @@ void Chart::calculateRates () << ", with currently " << _current_count << " pending tasks"; - context.debug (peak_message.str ()); + Context::getContext ().debug (peak_message.str ()); // If there are no current pending tasks, then it is meaningless to find // rates or estimated completion date. @@ -824,16 +822,16 @@ void Chart::calculateRates () << " = " << _net_fix_rate << " tasks/d"; - context.debug (rate_message.str ()); + Context::getContext ().debug (rate_message.str ()); Duration delta (static_cast (_current_count / fix_rate)); Datetime end = now + delta.toTime_t (); // Prefer dateformat.report over dateformat. - std::string format = context.config.get ("dateformat.report"); + std::string format = Context::getContext ().config.get ("dateformat.report"); if (format == "") { - format = context.config.get ("dateformat"); + format = Context::getContext ().config.get ("dateformat"); if (format == "") format = "Y-M-D"; } @@ -852,7 +850,7 @@ void Chart::calculateRates () << delta.format () << " --> " << end.toISO (); - context.debug (completion_message.str ()); + Context::getContext ().debug (completion_message.str ()); } else { diff --git a/src/commands/CmdCalc.cpp b/src/commands/CmdCalc.cpp index 59d8b7288..52f7b5b4c 100644 --- a/src/commands/CmdCalc.cpp +++ b/src/commands/CmdCalc.cpp @@ -29,8 +29,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdCalc::CmdCalc () { @@ -52,17 +50,17 @@ int CmdCalc::execute (std::string& output) { // Configurable infix/postfix bool infix {true}; - if (context.config.get ("expressions") == "postfix") + if (Context::getContext ().config.get ("expressions") == "postfix") infix = false; // Create an evaluator with DOM access. Eval e; e.addSource (domSource); - e.debug (context.config.getBoolean ("debug")); + e.debug (Context::getContext ().config.getBoolean ("debug")); // Compile all the args into one expression. std::string expression; - for (const auto& word : context.cli2.getWords ()) + for (const auto& word : Context::getContext ().cli2.getWords ()) expression += word + ' '; // Evaluate according to preference. diff --git a/src/commands/CmdCalendar.cpp b/src/commands/CmdCalendar.cpp index a8b0d0c7c..c6363de81 100644 --- a/src/commands/CmdCalendar.cpp +++ b/src/commands/CmdCalendar.cpp @@ -38,8 +38,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdCalendar::CmdCalendar () { @@ -63,8 +61,8 @@ int CmdCalendar::execute (std::string& output) // Each month requires 28 text columns width. See how many will actually // fit. But if a preference is specified, and it fits, use it. - auto width = context.getWidth (); - auto preferredMonthsPerLine = context.config.getInteger ("monthsperline"); + auto width = Context::getContext ().getWidth (); + auto preferredMonthsPerLine = Context::getContext ().config.getInteger ("monthsperline"); auto monthsThatFit = width / 26; auto monthsPerLine = monthsThatFit; @@ -74,7 +72,7 @@ int CmdCalendar::execute (std::string& output) // Load the pending tasks. handleUntil (); handleRecurrence (); - auto tasks = context.tdb2.pending.get_tasks (); + auto tasks = Context::getContext ().tdb2.pending.get_tasks (); Datetime today; auto getPendingDate = false; @@ -108,14 +106,14 @@ int CmdCalendar::execute (std::string& output) auto argYear = 0; auto argWholeYear = false; - for (auto& arg : context.cli2.getWords ()) + for (auto& arg : Context::getContext ().cli2.getWords ()) { // Some version of "calendar". - if (autoComplete (Lexer::lowerCase (arg), commandNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) + if (autoComplete (Lexer::lowerCase (arg), commandNames, matches, Context::getContext ().config.getInteger ("abbreviation.minimum")) == 1) continue; // "due". - else if (autoComplete (Lexer::lowerCase (arg), keywordNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) + else if (autoComplete (Lexer::lowerCase (arg), keywordNames, matches, Context::getContext ().config.getInteger ("abbreviation.minimum")) == 1) getPendingDate = true; // "y". @@ -135,7 +133,7 @@ int CmdCalendar::execute (std::string& output) } // "January" etc. - else if (autoComplete (Lexer::lowerCase (arg), monthNames, matches, context.config.getInteger ("abbreviation.minimum")) == 1) + else if (autoComplete (Lexer::lowerCase (arg), monthNames, matches, Context::getContext ().config.getInteger ("abbreviation.minimum")) == 1) { argMonth = Datetime::monthOfYear (matches[0]); if (argMonth == -1) @@ -192,10 +190,10 @@ int CmdCalendar::execute (std::string& output) yFrom = oldest.year(); } - if (context.config.getBoolean ("calendar.offset")) + if (Context::getContext ().config.getBoolean ("calendar.offset")) { - auto moffset = context.config.getInteger ("calendar.offset.value") % 12; - auto yoffset = context.config.getInteger ("calendar.offset.value") / 12; + auto moffset = Context::getContext ().config.getInteger ("calendar.offset.value") % 12; + auto yoffset = Context::getContext ().config.getInteger ("calendar.offset.value") / 12; mFrom += moffset; yFrom += yoffset; if (mFrom < 1) @@ -279,15 +277,15 @@ int CmdCalendar::execute (std::string& output) } } - Color color_today (context.config.get ("color.calendar.today")); - Color color_due (context.config.get ("color.calendar.due")); - Color color_duetoday (context.config.get ("color.calendar.due.today")); - Color color_overdue (context.config.get ("color.calendar.overdue")); - Color color_weekend (context.config.get ("color.calendar.weekend")); - Color color_holiday (context.config.get ("color.calendar.holiday")); - Color color_weeknumber (context.config.get ("color.calendar.weeknumber")); + Color color_today (Context::getContext ().config.get ("color.calendar.today")); + Color color_due (Context::getContext ().config.get ("color.calendar.due")); + Color color_duetoday (Context::getContext ().config.get ("color.calendar.due.today")); + Color color_overdue (Context::getContext ().config.get ("color.calendar.overdue")); + Color color_weekend (Context::getContext ().config.get ("color.calendar.weekend")); + Color color_holiday (Context::getContext ().config.get ("color.calendar.holiday")); + Color color_weeknumber (Context::getContext ().config.get ("color.calendar.weeknumber")); - if (context.color () && context.config.getBoolean ("calendar.legend")) + if (Context::getContext ().color () && Context::getContext ().config.getBoolean ("calendar.legend")) out << "Legend: " << color_today.colorize ("today") << ", " @@ -306,7 +304,7 @@ int CmdCalendar::execute (std::string& output) << optionalBlankLine () << '\n'; - if (context.config.get ("calendar.details") == "full" || context.config.get ("calendar.holidays") == "full") + if (Context::getContext ().config.get ("calendar.details") == "full" || Context::getContext ().config.get ("calendar.holidays") == "full") { --details_mFrom; if (details_mFrom == 0) @@ -324,30 +322,30 @@ int CmdCalendar::execute (std::string& output) } Datetime date_after (details_yFrom, details_mFrom, details_dFrom); - auto after = date_after.toString (context.config.get ("dateformat")); + auto after = date_after.toString (Context::getContext ().config.get ("dateformat")); Datetime date_before (yTo, mTo, 1); - auto before = date_before.toString (context.config.get ("dateformat")); + auto before = date_before.toString (Context::getContext ().config.get ("dateformat")); // Table with due date information - if (context.config.get ("calendar.details") == "full") + if (Context::getContext ().config.get ("calendar.details") == "full") { // Assert that 'report' is a valid report. - auto report = context.config.get ("calendar.details.report"); - if (context.commands.find (report) == context.commands.end ()) + auto report = Context::getContext ().config.get ("calendar.details.report"); + if (Context::getContext ().commands.find (report) == Context::getContext ().commands.end ()) throw std::string ("The setting 'calendar.details.report' must contain a single report name."); // TODO Fix this: cal --> task // calendar --> taskendar // If the executable was "cal" or equivalent, replace it with "task". - auto executable = context.cli2._original_args[0].attribute ("raw"); + auto executable = Context::getContext ().cli2._original_args[0].attribute ("raw"); auto cal = executable.find ("cal"); if (cal != std::string::npos) executable = executable.substr (0, cal) + PACKAGE; std::vector args; - args.push_back ("rc:" + context.rc_file._data); + args.push_back ("rc:" + Context::getContext ().rc_file._data); args.push_back ("rc.due:0"); args.push_back ("rc.verbose:label,affected,blank"); args.push_back ("due.after:" + after); @@ -361,34 +359,34 @@ int CmdCalendar::execute (std::string& output) } // Table with holiday information - if (context.config.get ("calendar.holidays") == "full") + if (Context::getContext ().config.get ("calendar.holidays") == "full") { Table holTable; - holTable.width (context.getWidth ()); + holTable.width (Context::getContext ().getWidth ()); holTable.add ("Date"); holTable.add ("Holiday"); setHeaderUnderline (holTable); std::map > hm; // we need to store multiple holidays per day - for (auto& it : context.config) + for (auto& it : Context::getContext ().config) if (it.first.substr (0, 8) == "holiday.") if (it.first.substr (it.first.size () - 4) == "name") { - auto holName = context.config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".name"); - auto holDate = context.config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".date"); - Datetime hDate (holDate.c_str (), context.config.get ("dateformat.holiday")); + auto holName = Context::getContext ().config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".name"); + auto holDate = Context::getContext ().config.get ("holiday." + it.first.substr (8, it.first.size () - 13) + ".date"); + Datetime hDate (holDate.c_str (), Context::getContext ().config.get ("dateformat.holiday")); if (date_after < hDate && hDate < date_before) hm[hDate.toEpoch()].push_back (holName); } - auto format = context.config.get ("report." + - context.config.get ("calendar.details.report") + + auto format = Context::getContext ().config.get ("report." + + Context::getContext ().config.get ("calendar.details.report") + ".dateformat"); if (format == "") - format = context.config.get ("dateformat.report"); + format = Context::getContext ().config.get ("dateformat.report"); if (format == "") - format = context.config.get ("dateformat"); + format = Context::getContext ().config.get ("dateformat"); for (auto& hm_it : hm) { @@ -422,14 +420,14 @@ std::string CmdCalendar::renderMonths ( int monthsPerLine) { // What day of the week does the user consider the first? - auto weekStart = Datetime::dayOfWeek (context.config.get ("weekstart")); + auto weekStart = Datetime::dayOfWeek (Context::getContext ().config.get ("weekstart")); if (weekStart != 0 && weekStart != 1) throw std::string ("The 'weekstart' configuration variable may only contain 'Sunday' or 'Monday'."); // Build table for the number of months to be displayed. Table view; setHeaderUnderline (view); - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); for (int i = 0 ; i < (monthsPerLine * 8); i += 8) { if (weekStart == 1) @@ -487,13 +485,13 @@ std::string CmdCalendar::renderMonths ( auto row = 0; - Color color_today (context.config.get ("color.calendar.today")); - Color color_due (context.config.get ("color.calendar.due")); - Color color_duetoday (context.config.get ("color.calendar.due.today")); - Color color_overdue (context.config.get ("color.calendar.overdue")); - Color color_weekend (context.config.get ("color.calendar.weekend")); - Color color_holiday (context.config.get ("color.calendar.holiday")); - Color color_weeknumber (context.config.get ("color.calendar.weeknumber")); + Color color_today (Context::getContext ().config.get ("color.calendar.today")); + Color color_due (Context::getContext ().config.get ("color.calendar.due")); + Color color_duetoday (Context::getContext ().config.get ("color.calendar.due.today")); + Color color_overdue (Context::getContext ().config.get ("color.calendar.overdue")); + Color color_weekend (Context::getContext ().config.get ("color.calendar.weekend")); + Color color_holiday (Context::getContext ().config.get ("color.calendar.holiday")); + Color color_weeknumber (Context::getContext ().config.get ("color.calendar.weeknumber")); // Loop through months to be added on this line. for (int mpl = 0; mpl < monthsPerLine ; mpl++) @@ -509,7 +507,7 @@ std::string CmdCalendar::renderMonths ( auto dow = temp.dayOfWeek (); auto woy = temp.week (); - if (context.config.getBoolean ("displayweeknumber")) + if (Context::getContext ().config.getBoolean ("displayweeknumber")) view.set (row, (8 * mpl), // Make sure the week number is always 4 columns, space-padded. @@ -526,7 +524,7 @@ std::string CmdCalendar::renderMonths ( view.set (row, thisCol, d); - if (context.color ()) + if (Context::getContext ().color ()) { Color cellColor; @@ -535,14 +533,14 @@ std::string CmdCalendar::renderMonths ( cellColor.blend (color_weekend); // colorize holidays - if (context.config.get ("calendar.holidays") != "none") + if (Context::getContext ().config.get ("calendar.holidays") != "none") { - for (auto& hol : context.config) + for (auto& hol : Context::getContext ().config) if (hol.first.substr (0, 8) == "holiday.") if (hol.first.substr (hol.first.size () - 4) == "date") { std::string value = hol.second; - Datetime holDate (value.c_str (), context.config.get ("dateformat.holiday")); + Datetime holDate (value.c_str (), Context::getContext ().config.get ("dateformat.holiday")); if (holDate.day () == d && holDate.month () == months[mpl] && holDate.year () == years[mpl]) @@ -557,9 +555,9 @@ std::string CmdCalendar::renderMonths ( cellColor.blend (color_today); // colorize due tasks - if (context.config.get ("calendar.details") != "none") + if (Context::getContext ().config.get ("calendar.details") != "none") { - context.config.set ("due", 0); + Context::getContext ().config.set ("due", 0); for (auto& task : all) { if (task.getStatus () == Task::pending && diff --git a/src/commands/CmdColor.cpp b/src/commands/CmdColor.cpp index 23c9cd4e8..2bc4ea388 100644 --- a/src/commands/CmdColor.cpp +++ b/src/commands/CmdColor.cpp @@ -34,8 +34,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdColor::CmdColor () { @@ -59,13 +57,13 @@ int CmdColor::execute (std::string& output) // Get the non-attribute, non-fancy command line arguments. auto legend = false; - auto words = context.cli2.getWords (); + auto words = Context::getContext ().cli2.getWords (); for (auto& word : words) if (closeEnough ("legend", word)) legend = true; std::stringstream out; - if (context.color ()) + if (Context::getContext ().color ()) { // If the description contains 'legend', show all the colors currently in // use. @@ -74,13 +72,13 @@ int CmdColor::execute (std::string& output) out << "\nHere are the colors currently in use:\n"; Table view; - view.width (context.getWidth ()); - if (context.config.getBoolean ("color")) + view.width (Context::getContext ().getWidth ()); + if (Context::getContext ().config.getBoolean ("color")) view.forceColor (); view.add ("Color"); view.add ("Definition"); - for (auto& item : context.config) + for (auto& item : Context::getContext ().config) { // Skip items with 'color' in their name, that are not referring to // actual colors. @@ -88,7 +86,7 @@ int CmdColor::execute (std::string& output) item.first != "color" && item.first.find ("color") == 0) { - Color color (context.config.get (item.first)); + Color color (Context::getContext ().config.get (item.first)); int row = view.addRow (); view.set (row, 0, item.first, color); view.set (row, 1, item.second, color); diff --git a/src/commands/CmdColumns.cpp b/src/commands/CmdColumns.cpp index 1d7b0c076..941096505 100644 --- a/src/commands/CmdColumns.cpp +++ b/src/commands/CmdColumns.cpp @@ -34,8 +34,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdColumns::CmdColumns () { @@ -57,20 +55,20 @@ int CmdColumns::execute (std::string& output) { // Obtain the arguments from the description. That way, things like '--' // have already been handled. - auto words = context.cli2.getWords (); + auto words = Context::getContext ().cli2.getWords (); if (words.size () > 1) throw std::string ("You can only specify one search string."); // Include all columns in the table. std::vector names; - for (const auto& col : context.columns) + for (const auto& col : Context::getContext ().columns) names.push_back (col.first); std::sort (names.begin (), names.end ()); // Render a list of column names, formats and examples. Table formats; - formats.width (context.getWidth ()); + formats.width (Context::getContext ().getWidth ()); formats.add ("Columns"); formats.add ("Type"); formats.add ("Modifiable"); @@ -83,15 +81,15 @@ int CmdColumns::execute (std::string& output) if (words.size () == 0 || find (name, words[0], false) != std::string::npos) { - auto styles = context.columns[name]->styles (); - auto examples = context.columns[name]->examples (); + auto styles = Context::getContext ().columns[name]->styles (); + auto examples = Context::getContext ().columns[name]->examples (); for (unsigned int i = 0; i < styles.size (); ++i) { auto row = formats.addRow (); formats.set (row, 0, i == 0 ? name : ""); - formats.set (row, 1, i == 0 ? context.columns[name]->type () : ""); - formats.set (row, 2, i == 0 ? (context.columns[name]->modifiable () ? "Modifiable" : "Read Only") : ""); + formats.set (row, 1, i == 0 ? Context::getContext ().columns[name]->type () : ""); + formats.set (row, 2, i == 0 ? (Context::getContext ().columns[name]->modifiable () ? "Modifiable" : "Read Only") : ""); formats.set (row, 3, styles[i] + (i == 0 ? "*" : "")); formats.set (row, 4, i < examples.size () ? examples[i] : ""); } @@ -137,7 +135,7 @@ int CmdCompletionColumns::execute (std::string& output) { // Include all columns. std::vector names; - for (const auto& col : context.columns) + for (const auto& col : Context::getContext ().columns) names.push_back (col.first); std::sort (names.begin (), names.end ()); diff --git a/src/commands/CmdCommands.cpp b/src/commands/CmdCommands.cpp index 87b0de63b..fa623cb11 100644 --- a/src/commands/CmdCommands.cpp +++ b/src/commands/CmdCommands.cpp @@ -34,8 +34,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdCommands::CmdCommands () { @@ -56,7 +54,7 @@ CmdCommands::CmdCommands () int CmdCommands::execute (std::string& output) { Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.add ("Command"); view.add ("Category"); view.add ("R/W", false); @@ -67,12 +65,12 @@ int CmdCommands::execute (std::string& output) view.add ("Mods", false); view.add ("Misc", false); view.add ("Description"); - view.leftMargin (context.config.getInteger ("indent.report")); - view.extraPadding (context.config.getInteger ("row.padding")); - view.intraPadding (context.config.getInteger ("column.padding")); + view.leftMargin (Context::getContext ().config.getInteger ("indent.report")); + view.extraPadding (Context::getContext ().config.getInteger ("row.padding")); + view.intraPadding (Context::getContext ().config.getInteger ("column.padding")); setHeaderUnderline (view); - for (auto& command : context.commands) + for (auto& command : Context::getContext ().commands) { auto row = view.addRow (); view.set (row, 0, command.first); @@ -133,7 +131,7 @@ int CmdCompletionCommands::execute (std::string& output) { // Get a list of all commands. std::vector commands; - for (const auto& command : context.commands) + for (const auto& command : Context::getContext ().commands) commands.push_back (command.first); // Sort alphabetically. @@ -199,7 +197,7 @@ int CmdZshCommands::execute (std::string& output) // denominator alternative: a custom struct type. std::vector commands; - for (auto& command : context.commands) + for (auto& command : Context::getContext ().commands) { ZshCommand zshCommand {command.second->category (), command.first, diff --git a/src/commands/CmdConfig.cpp b/src/commands/CmdConfig.cpp index 2e6dd61d3..bb6edf444 100644 --- a/src/commands/CmdConfig.cpp +++ b/src/commands/CmdConfig.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdConfig::CmdConfig () { @@ -59,7 +57,7 @@ bool CmdConfig::setConfigVariable ( { // Read .taskrc (or equivalent) std::vector contents; - File::read (context.config.file (), contents); + File::read (Context::getContext ().config.file (), contents); auto found = false; auto change = false; @@ -76,7 +74,7 @@ bool CmdConfig::setConfigVariable ( { found = true; if (!confirmation || - confirm (format ("Are you sure you want to change the value of '{1}' from '{2}' to '{3}'?", name, context.config.get (name), value))) + confirm (format ("Are you sure you want to change the value of '{1}' from '{2}' to '{3}'?", name, Context::getContext ().config.get (name), value))) { line = name + '=' + json::encode (value); @@ -98,7 +96,7 @@ bool CmdConfig::setConfigVariable ( } if (change) - File::write (context.config.file (), contents); + File::write (Context::getContext ().config.file (), contents); return change; } @@ -108,7 +106,7 @@ int CmdConfig::unsetConfigVariable (const std::string& name, bool confirmation / { // Read .taskrc (or equivalent) std::vector contents; - File::read (context.config.file (), contents); + File::read (Context::getContext ().config.file (), contents); auto found = false; auto change = false; @@ -143,7 +141,7 @@ int CmdConfig::unsetConfigVariable (const std::string& name, bool confirmation / } if (change) - File::write (context.config.file (), contents); + File::write (Context::getContext ().config.file (), contents); if (change && found) return 0; @@ -160,7 +158,7 @@ int CmdConfig::execute (std::string& output) std::stringstream out; // Get the non-attribute, non-fancy command line arguments. - std::vector words = context.cli2.getWords (); + std::vector words = Context::getContext ().cli2.getWords (); // Support: // task config name value # set name to value @@ -168,7 +166,7 @@ int CmdConfig::execute (std::string& output) // task config name # remove name if (words.size ()) { - auto confirmation = context.config.getBoolean ("confirmation"); + auto confirmation = Context::getContext ().config.getBoolean ("confirmation"); auto found = false; auto name = words[0]; @@ -214,7 +212,7 @@ int CmdConfig::execute (std::string& output) // Show feedback depending on whether .taskrc has been rewritten if (change) { - out << format ("Config file {1} modified.", context.config.file ()) + out << format ("Config file {1} modified.", Context::getContext ().config.file ()) << '\n'; } else @@ -250,7 +248,7 @@ CmdCompletionConfig::CmdCompletionConfig () //////////////////////////////////////////////////////////////////////////////// int CmdCompletionConfig::execute (std::string& output) { - auto configs = context.config.all (); + auto configs = Context::getContext ().config.all (); std::sort (configs.begin (), configs.end ()); for (const auto& config : configs) diff --git a/src/commands/CmdContext.cpp b/src/commands/CmdContext.cpp index 644e3bb2e..d1657327b 100644 --- a/src/commands/CmdContext.cpp +++ b/src/commands/CmdContext.cpp @@ -36,8 +36,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdContext::CmdContext () { @@ -60,7 +58,7 @@ int CmdContext::execute (std::string& output) std::stringstream out; // Get the non-attribute, non-fancy command line arguments. - auto words = context.cli2.getWords (); + auto words = Context::getContext ().cli2.getWords (); if (words.size () > 0) { auto subcommand = words[0]; @@ -110,7 +108,7 @@ std::vector CmdContext::getContexts () { std::vector contexts; - for (auto& name : context.config) + for (auto& name : Context::getContext ().config) if (name.first.substr (0, 8) == "context.") contexts.push_back (name.first.substr (8)); @@ -129,7 +127,7 @@ std::vector CmdContext::getContexts () // void CmdContext::defineContext (const std::vector & words, std::stringstream& out) { - auto confirmation = context.config.getBoolean ("confirmation"); + auto confirmation = Context::getContext ().config.getBoolean ("confirmation"); if (words.size () > 2) { @@ -145,12 +143,12 @@ void CmdContext::defineContext (const std::vector & words, std::str // Check if the value is a proper filter by filtering current pending.data Filter filter; std::vector filtered; - auto pending = context.tdb2.pending.get_tasks (); + auto pending = Context::getContext ().tdb2.pending.get_tasks (); try { // This result is not used, and is just to check validity. - context.cli2.addFilter (value); + Context::getContext ().cli2.addFilter (value); filter.subset (pending, filtered); } catch (std::string exception) @@ -193,11 +191,11 @@ void CmdContext::deleteContext (const std::vector & words, std::str // Delete the specified context auto name = "context." + words[1]; - auto confirmation = context.config.getBoolean ("confirmation"); + auto confirmation = Context::getContext ().config.getBoolean ("confirmation"); auto rc = CmdConfig::unsetConfigVariable(name, confirmation); // If the currently set context was deleted, unset it - if (context.config.get ("context") == words[1]) + if (Context::getContext ().config.get ("context") == words[1]) CmdConfig::unsetConfigVariable("context", false); // Output feedback @@ -226,13 +224,13 @@ void CmdContext::listContexts (std::stringstream& out) std::sort (contexts.begin (), contexts.end ()); Table table; - table.width (context.getWidth ()); + table.width (Context::getContext ().getWidth ()); table.add ("Name"); table.add ("Definition"); table.add ("Active"); setHeaderUnderline (table); - std::string activeContext = context.config.get ("context"); + std::string activeContext = Context::getContext ().config.get ("context"); for (auto& userContext : contexts) { @@ -242,7 +240,7 @@ void CmdContext::listContexts (std::stringstream& out) int row = table.addRow (); table.set (row, 0, userContext); - table.set (row, 1, context.config.get ("context." + userContext)); + table.set (row, 1, Context::getContext ().config.get ("context." + userContext)); table.set (row, 2, active); } @@ -294,13 +292,13 @@ void CmdContext::setContext (const std::vector & words, std::string // void CmdContext::showContext (std::stringstream& out) { - auto currentContext = context.config.get ("context"); + auto currentContext = Context::getContext ().config.get ("context"); if (currentContext == "") out << "No context is currently applied.\n"; else { - std::string currentFilter = context.config.get ("context." + currentContext); + std::string currentFilter = Context::getContext ().config.get ("context." + currentContext); out << format ("Context '{1}' with filter '{2}' is currently applied.\n", currentContext, currentFilter); } } diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index 1e5c551c0..abdc3351d 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -40,8 +40,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdCustom::CmdCustom ( const std::string& keyword, @@ -67,10 +65,10 @@ int CmdCustom::execute (std::string& output) auto rc = 0; // Load report configuration. - auto reportColumns = context.config.get ("report." + _keyword + ".columns"); - auto reportLabels = context.config.get ("report." + _keyword + ".labels"); - auto reportSort = context.config.get ("report." + _keyword + ".sort"); - auto reportFilter = context.config.get ("report." + _keyword + ".filter"); + auto reportColumns = Context::getContext ().config.get ("report." + _keyword + ".columns"); + auto reportLabels = Context::getContext ().config.get ("report." + _keyword + ".labels"); + auto reportSort = Context::getContext ().config.get ("report." + _keyword + ".sort"); + auto reportFilter = Context::getContext ().config.get ("report." + _keyword + ".filter"); auto columns = split (reportColumns, ','); validateReportColumns (columns); @@ -87,7 +85,7 @@ int CmdCustom::execute (std::string& output) // Add the report filter to any existing filter. if (reportFilter != "") - context.cli2.addFilter (reportFilter); + Context::getContext ().cli2.addFilter (reportFilter); // Apply filter. handleUntil (); @@ -101,10 +99,10 @@ int CmdCustom::execute (std::string& output) sortOrder[0] == "none") { // Assemble a sequence vector that represents the tasks listed in - // context.cli2._uuid_ranges, in the order in which they appear. This + // Context::getContext ().cli2._uuid_ranges, in the order in which they appear. This // equates to no sorting, just a specified order. sortOrder.clear (); - for (auto& i : context.cli2._uuid_list) + for (auto& i : Context::getContext ().cli2._uuid_list) for (unsigned int t = 0; t < filtered.size (); ++t) if (filtered[t].get ("uuid") == i) sequence.push_back (t); @@ -123,21 +121,21 @@ int CmdCustom::execute (std::string& output) // Configure the view. ViewTask view; - view.width (context.getWidth ()); - view.leftMargin (context.config.getInteger ("indent.report")); - view.extraPadding (context.config.getInteger ("row.padding")); - view.intraPadding (context.config.getInteger ("column.padding")); + view.width (Context::getContext ().getWidth ()); + view.leftMargin (Context::getContext ().config.getInteger ("indent.report")); + view.extraPadding (Context::getContext ().config.getInteger ("row.padding")); + view.intraPadding (Context::getContext ().config.getInteger ("column.padding")); - if (context.color ()) + if (Context::getContext ().color ()) { - Color label (context.config.get ("color.label")); + Color label (Context::getContext ().config.get ("color.label")); view.colorHeader (label); - Color label_sort (context.config.get ("color.label.sort")); + Color label_sort (Context::getContext ().config.get ("color.label.sort")); view.colorSortHeader (label_sort); // If an alternating row color is specified, notify the table. - Color alternate (context.config.get ("color.alternate")); + Color alternate (Context::getContext ().config.get ("color.alternate")); if (alternate.nontrivial ()) { view.colorOdd (alternate); @@ -154,7 +152,7 @@ int CmdCustom::execute (std::string& output) std::string name; bool ascending; bool breakIndicator; - context.decomposeSortField (so, name, ascending, breakIndicator); + Context::getContext ().decomposeSortField (so, name, ascending, breakIndicator); if (breakIndicator) view.addBreak (name); @@ -178,9 +176,9 @@ int CmdCustom::execute (std::string& output) // How many lines taken up by table header? int table_header = 0; - if (context.verbose ("label")) + if (Context::getContext ().verbose ("label")) { - if (context.color () && context.config.getBoolean ("fontunderline")) + if (Context::getContext ().color () && Context::getContext ().config.getBoolean ("fontunderline")) table_header = 1; // Underlining doesn't use extra line. else table_header = 2; // Dashes use an extra line. @@ -189,15 +187,15 @@ int CmdCustom::execute (std::string& output) // Report output can be limited by rows or lines. auto maxrows = 0; auto maxlines = 0; - context.getLimits (maxrows, maxlines); + Context::getContext ().getLimits (maxrows, maxlines); // Adjust for fluff in the output. if (maxlines) maxlines -= table_header - + (context.verbose ("blank") ? 1 : 0) - + (context.verbose ("footnote") ? context.footnotes.size () : 0) - + (context.verbose ("affected") ? 1 : 0) - + context.config.getInteger ("reserved.lines"); // For prompt, etc. + + (Context::getContext ().verbose ("blank") ? 1 : 0) + + (Context::getContext ().verbose ("footnote") ? Context::getContext ().footnotes.size () : 0) + + (Context::getContext ().verbose ("affected") ? 1 : 0) + + Context::getContext ().config.getInteger ("reserved.lines"); // For prompt, etc. // Render. std::stringstream out; @@ -211,7 +209,7 @@ int CmdCustom::execute (std::string& output) << optionalBlankLine (); // Print the number of rendered tasks - if (context.verbose ("affected")) + if (Context::getContext ().verbose ("affected")) { out << (filtered.size () == 1 ? "1 task" @@ -229,7 +227,7 @@ int CmdCustom::execute (std::string& output) } else { - context.footnote ("No matches."); + Context::getContext ().footnote ("No matches."); rc = 1; } diff --git a/src/commands/CmdDelete.cpp b/src/commands/CmdDelete.cpp index 06a547c06..abb58a703 100644 --- a/src/commands/CmdDelete.cpp +++ b/src/commands/CmdDelete.cpp @@ -36,8 +36,6 @@ #define STRING_CMD_DELETE_TASK_R "Deleting recurring task {1} '{2}'." #define STRING_CMD_DELETE_CONFIRM_R "This is a recurring task. Do you want to delete all pending recurrences of this same task?" -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdDelete::CmdDelete () { @@ -67,7 +65,7 @@ int CmdDelete::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -95,21 +93,21 @@ int CmdDelete::execute (std::string&) { updateRecurrenceMask (task); ++count; - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); feedback_affected ("Deleting task {1} '{2}'.", task); feedback_unblocked (task); dependencyChainOnComplete (task); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task); // Delete siblings. if (task.has ("parent")) { - if ((context.config.get ("recurrence.confirmation") == "prompt" + if ((Context::getContext ().config.get ("recurrence.confirmation") == "prompt" && confirm (STRING_CMD_DELETE_CONFIRM_R)) || - context.config.getBoolean ("recurrence.confirmation")) + Context::getContext ().config.getBoolean ("recurrence.confirmation")) { - std::vector siblings = context.tdb2.siblings (task); + std::vector siblings = Context::getContext ().tdb2.siblings (task); for (auto& sibling : siblings) { sibling.modify (Task::modAnnotate); @@ -118,7 +116,7 @@ int CmdDelete::execute (std::string&) sibling.setAsNow ("end"); updateRecurrenceMask (sibling); - context.tdb2.modify (sibling); + Context::getContext ().tdb2.modify (sibling); feedback_affected (STRING_CMD_DELETE_TASK_R, sibling); feedback_unblocked (sibling); ++count; @@ -126,21 +124,21 @@ int CmdDelete::execute (std::string&) // Delete the parent Task parent; - context.tdb2.get (task.get ("parent"), parent); + Context::getContext ().tdb2.get (task.get ("parent"), parent); parent.setStatus (Task::deleted); if (! parent.has ("end")) parent.setAsNow ("end"); - context.tdb2.modify (parent); + Context::getContext ().tdb2.modify (parent); } } // Task potentially has child tasks - optionally delete them. else { - std::vector children = context.tdb2.children (task); + std::vector children = Context::getContext ().tdb2.children (task); if (children.size () && - (context.config.getBoolean ("recurrence.confirmation") || + (Context::getContext ().config.getBoolean ("recurrence.confirmation") || confirm (STRING_CMD_DELETE_CONFIRM_R))) { for (auto& child : children) @@ -151,7 +149,7 @@ int CmdDelete::execute (std::string&) child.setAsNow ("end"); updateRecurrenceMask (child); - context.tdb2.modify (child); + Context::getContext ().tdb2.modify (child); feedback_affected (STRING_CMD_DELETE_TASK_R, child); feedback_unblocked (child); ++count; @@ -180,7 +178,7 @@ int CmdDelete::execute (std::string&) // Now list the project changes. for (const auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Deleted {1} task." : "Deleted {1} tasks.", count); diff --git a/src/commands/CmdDenotate.cpp b/src/commands/CmdDenotate.cpp index f2a0c3dca..5b5941a14 100644 --- a/src/commands/CmdDenotate.cpp +++ b/src/commands/CmdDenotate.cpp @@ -38,8 +38,6 @@ #define STRING_CMD_DENO_1 "Denotated {1} task." #define STRING_CMD_DENO_N "Denotated {1} tasks." -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdDenotate::CmdDenotate () { @@ -61,7 +59,7 @@ int CmdDenotate::execute (std::string&) { auto rc = 0; auto count = 0; - auto sensitive = context.config.getBoolean ("search.case.sensitive"); + auto sensitive = Context::getContext ().config.getBoolean ("search.case.sensitive"); // Apply filter. Filter filter; @@ -69,13 +67,13 @@ int CmdDenotate::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } // Extract all the ORIGINAL MODIFICATION args as simple text patterns. std::string pattern = ""; - for (auto& a : context.cli2._args) + for (auto& a : Context::getContext ().cli2._args) { if (a.hasTag ("MISCELLANEOUS")) { @@ -136,9 +134,9 @@ int CmdDenotate::execute (std::string&) if (permission (taskDifferences (before, task) + question, filtered.size ())) { ++count; - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); feedback_affected (format ("Found annotation '{1}' and deleted it.", anno)); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task, false); } else @@ -159,7 +157,7 @@ int CmdDenotate::execute (std::string&) // Now list the project changes. for (const auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? STRING_CMD_DENO_1 : STRING_CMD_DENO_N, count); return rc; diff --git a/src/commands/CmdDiagnostics.cpp b/src/commands/CmdDiagnostics.cpp index 1e9ff63bc..303c129d2 100644 --- a/src/commands/CmdDiagnostics.cpp +++ b/src/commands/CmdDiagnostics.cpp @@ -43,8 +43,6 @@ #include #endif -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdDiagnostics::CmdDiagnostics () { @@ -69,7 +67,7 @@ CmdDiagnostics::CmdDiagnostics () int CmdDiagnostics::execute (std::string& output) { Color bold; - if (context.color ()) + if (Context::getContext ().color ()) bold = Color ("bold"); std::stringstream out; @@ -160,7 +158,7 @@ int CmdDiagnostics::execute (std::string& output) << "\n\n"; // Config: .taskrc found, readable, writable - File rcFile (context.config.file ()); + File rcFile (Context::getContext ().config.file ()); out << bold.colorize ("Configuration") << '\n' << " File: " << rcFile._data << ' ' @@ -174,7 +172,7 @@ int CmdDiagnostics::execute (std::string& output) << '\n'; // Config: data.location found, readable, writable - File location (context.config.get ("data.location")); + File location (Context::getContext ().config.get ("data.location")); out << " Data: " << location._data << ' ' << (location.exists () ? "(found)" @@ -198,31 +196,31 @@ int CmdDiagnostics::execute (std::string& output) << '\n'; out << " Locking: " - << (context.config.getBoolean ("locking") + << (Context::getContext ().config.getBoolean ("locking") ? "Enabled" : "Disabled") << '\n'; out << " GC: " - << (context.config.getBoolean ("gc") + << (Context::getContext ().config.getBoolean ("gc") ? "Enabled" : "Disabled") << '\n'; // Determine rc.editor/$EDITOR/$VISUAL. char* peditor; - if (context.config.get ("editor") != "") - out << " rc.editor: " << context.config.get ("editor") << '\n'; + if (Context::getContext ().config.get ("editor") != "") + out << " rc.editor: " << Context::getContext ().config.get ("editor") << '\n'; else if ((peditor = getenv ("VISUAL")) != NULL) out << " $VISUAL: " << peditor << '\n'; else if ((peditor = getenv ("EDITOR")) != NULL) out << " $EDITOR: " << peditor << '\n'; out << " Server: " - << context.config.get ("taskd.server") + << Context::getContext ().config.get ("taskd.server") << '\n'; - auto ca_pem = context.config.get ("taskd.ca"); + auto ca_pem = Context::getContext ().config.get ("taskd.ca"); out << " CA: "; if (ca_pem != "") { @@ -238,7 +236,7 @@ int CmdDiagnostics::execute (std::string& output) else out << "-\n"; - auto cert_pem = context.config.get ("taskd.certificate"); + auto cert_pem = Context::getContext ().config.get ("taskd.certificate"); out << "Certificate: "; if (cert_pem != "") { @@ -254,7 +252,7 @@ int CmdDiagnostics::execute (std::string& output) else out << "-\n"; - auto key_pem = context.config.get ("taskd.key"); + auto key_pem = Context::getContext ().config.get ("taskd.key"); out << " Key: "; if (key_pem != "") { @@ -270,7 +268,7 @@ int CmdDiagnostics::execute (std::string& output) else out << "-\n"; - auto trust_value = context.config.get ("taskd.trust"); + auto trust_value = Context::getContext ().config.get ("taskd.trust"); if (trust_value == "strict" || trust_value == "ignore hostname" || trust_value == "allow all") @@ -279,11 +277,11 @@ int CmdDiagnostics::execute (std::string& output) out << " Trust: Bad value - see 'man taskrc'\n"; out << " Ciphers: " - << context.config.get ("taskd.ciphers") + << Context::getContext ().config.get ("taskd.ciphers") << '\n'; // Get credentials, but mask out the key. - auto credentials = context.config.get ("taskd.credentials"); + auto credentials = Context::getContext ().config.get ("taskd.credentials"); auto last_slash = credentials.rfind ('/'); if (last_slash != std::string::npos) credentials = credentials.substr (0, last_slash) @@ -296,26 +294,26 @@ int CmdDiagnostics::execute (std::string& output) // Display hook status. Path hookLocation; - if (context.config.has ("hooks.location")) + if (Context::getContext ().config.has ("hooks.location")) { - hookLocation = Path (context.config.get ("hooks.location")); + hookLocation = Path (Context::getContext ().config.get ("hooks.location")); } else { - hookLocation = Path (context.config.get ("data.location")); + hookLocation = Path (Context::getContext ().config.get ("data.location")); hookLocation += "hooks"; } out << bold.colorize ("Hooks") << '\n' << " System: " - << (context.config.getBoolean ("hooks") ? "Enabled" : "Disabled") + << (Context::getContext ().config.getBoolean ("hooks") ? "Enabled" : "Disabled") << '\n' << " Location: " << static_cast (hookLocation) << '\n'; - auto hooks = context.hooks.list (); + auto hooks = Context::getContext ().hooks.list (); if (hooks.size ()) { unsigned int longest = 0; @@ -397,13 +395,13 @@ int CmdDiagnostics::execute (std::string& output) // Report terminal dimensions. out << " Terminal: " - << context.getWidth () + << Context::getContext ().getWidth () << 'x' - << context.getHeight () + << Context::getContext ().getHeight () << '\n'; // Scan tasks for duplicate UUIDs. - auto all = context.tdb2.all_tasks (); + auto all = Context::getContext ().tdb2.all_tasks (); std::map seen; std::vector dups; std::string uuid; @@ -442,7 +440,7 @@ int CmdDiagnostics::execute (std::string& output) // Check dependencies for (auto& uuid : task.getDependencyUUIDs ()) { - if (! context.tdb2.has (uuid)) + if (! Context::getContext ().tdb2.has (uuid)) { out << " " << format ("Task {1} depends on nonexistent task: {2}", task.get ("uuid"), uuid) @@ -454,7 +452,7 @@ int CmdDiagnostics::execute (std::string& output) // Check recurrence parent auto parentUUID = task.get ("parent"); - if (parentUUID != "" && ! context.tdb2.has (parentUUID)) + if (parentUUID != "" && ! Context::getContext ().tdb2.has (parentUUID)) { out << " " << format ("Task {1} has nonexistent recurrence template {2}", task.get ("uuid"), parentUUID) diff --git a/src/commands/CmdDone.cpp b/src/commands/CmdDone.cpp index d336fd89e..0c7a898a3 100644 --- a/src/commands/CmdDone.cpp +++ b/src/commands/CmdDone.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdDone::CmdDone () { @@ -63,7 +61,7 @@ int CmdDone::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -92,21 +90,21 @@ int CmdDone::execute (std::string&) if (task.has ("start")) { task.remove ("start"); - if (context.config.getBoolean ("journal.time")) - task.addAnnotation (context.config.get ("journal.time.stop.annotation")); + if (Context::getContext ().config.getBoolean ("journal.time")) + task.addAnnotation (Context::getContext ().config.get ("journal.time.stop.annotation")); } if (permission (taskDifferences (before, task) + question, filtered.size ())) { updateRecurrenceMask (task); - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); ++count; feedback_affected ("Completed task {1} '{2}'.", task); feedback_unblocked (task); if (!nagged) nagged = nag (task); dependencyChainOnComplete (task); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task); } else @@ -130,7 +128,7 @@ int CmdDone::execute (std::string&) // Now list the project changes. for (const auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Completed {1} task." : "Completed {1} tasks.", count); return rc; diff --git a/src/commands/CmdDuplicate.cpp b/src/commands/CmdDuplicate.cpp index 80ab5db47..a13bd38ed 100644 --- a/src/commands/CmdDuplicate.cpp +++ b/src/commands/CmdDuplicate.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdDuplicate::CmdDuplicate () { @@ -63,7 +61,7 @@ int CmdDuplicate::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -109,21 +107,21 @@ int CmdDuplicate::execute (std::string&) task.get ("description")), filtered.size ())) { - context.tdb2.add (dup); + Context::getContext ().tdb2.add (dup); ++count; feedback_affected ("Duplicated task {1} '{2}'.", task); auto status = dup.getStatus (); - if (context.verbose ("new-id") && + if (Context::getContext ().verbose ("new-id") && (status == Task::pending || status == Task::waiting)) std::cout << format ("Created task {1}.\n", dup.id); - else if (context.verbose ("new-uuid") && + else if (Context::getContext ().verbose ("new-uuid") && status != Task::recurring) std::cout << format ("Created task {1}.\n", dup.get ("uuid")); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task); } else @@ -138,7 +136,7 @@ int CmdDuplicate::execute (std::string&) // Now list the project changes. for (const auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Duplicated {1} task." : "Duplicated {1} tasks.", count); diff --git a/src/commands/CmdEdit.cpp b/src/commands/CmdEdit.cpp index ce37353c8..c399fa308 100644 --- a/src/commands/CmdEdit.cpp +++ b/src/commands/CmdEdit.cpp @@ -51,8 +51,6 @@ #define STRING_EDIT_UNTIL_MOD "Until date modified." #define STRING_EDIT_WAIT_MOD "Wait date modified." -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdEdit::CmdEdit () { @@ -84,7 +82,7 @@ int CmdEdit::execute (std::string&) if (! filtered.size ()) { - context.footnote ("No matches."); + Context::getContext ().footnote ("No matches."); return 1; } @@ -95,7 +93,7 @@ int CmdEdit::execute (std::string&) if (result == CmdEdit::editResult::error) break; else if (result == CmdEdit::editResult::changes) - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); } return 0; @@ -201,7 +199,7 @@ std::string CmdEdit::formatDuration ( std::string CmdEdit::formatTask (Task task, const std::string& dateformat) { std::stringstream before; - auto verbose = context.verbose ("edit"); + auto verbose = Context::getContext ().verbose ("edit"); if (verbose) before << "# The 'task edit' command allows you to modify all aspects of a task\n" @@ -269,7 +267,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) allDeps << ","; Task t; - context.tdb2.get (dependencies[i], t); + Context::getContext ().tdb2.get (dependencies[i], t); if (t.getStatus () == Task::pending || t.getStatus () == Task::waiting) allDeps << t.id; @@ -284,8 +282,8 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) // UDAs std::vector udas; - for (auto& col : context.columns) - if (context.config.get ("uda." + col.first + ".type") != "") + for (auto& col : Context::getContext ().columns) + if (Context::getContext ().config.get ("uda." + col.first + ".type") != "") udas.push_back (col.first); if (udas.size ()) @@ -299,7 +297,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) if (pad > 0) padding = std::string (pad, ' '); - std::string type = context.config.get ("uda." + uda + ".type"); + std::string type = Context::getContext ().config.get ("uda." + uda + ".type"); if (type == "string" || type == "numeric") before << " UDA " << uda << ": " << padding << task.get (uda) << '\n'; else if (type == "date") @@ -339,12 +337,12 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != "") { - context.footnote ("Project modified."); + Context::getContext ().footnote ("Project modified."); task.set ("project", value); } else { - context.footnote ("Project deleted."); + Context::getContext ().footnote ("Project deleted."); task.remove ("project"); } } @@ -360,7 +358,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != "") { - context.footnote ("Description modified."); + Context::getContext ().footnote ("Description modified."); task.set ("description", value); } else @@ -373,7 +371,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != formatDate (task, "entry", dateformat)) { - context.footnote ("Creation date modified."); + Context::getContext ().footnote ("Creation date modified."); task.set ("entry", Datetime (value, dateformat).toEpochString ()); } } @@ -388,13 +386,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != formatDate (task, "start", dateformat)) { - context.footnote (STRING_EDIT_START_MOD); + Context::getContext ().footnote (STRING_EDIT_START_MOD); task.set ("start", Datetime (value, dateformat).toEpochString ()); } } else { - context.footnote (STRING_EDIT_START_MOD); + Context::getContext ().footnote (STRING_EDIT_START_MOD); task.set ("start", Datetime (value, dateformat).toEpochString ()); } } @@ -402,7 +400,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (task.get ("start") != "") { - context.footnote ("Start date removed."); + Context::getContext ().footnote ("Start date removed."); task.remove ("start"); } } @@ -415,7 +413,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != formatDate (task, "end", dateformat)) { - context.footnote ("End date modified."); + Context::getContext ().footnote ("End date modified."); task.set ("end", Datetime (value, dateformat).toEpochString ()); } } @@ -426,7 +424,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (task.get ("end") != "") { - context.footnote ("End date removed."); + Context::getContext ().footnote ("End date removed."); task.setStatus (Task::pending); task.remove ("end"); } @@ -440,13 +438,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != formatDate (task, "scheduled", dateformat)) { - context.footnote (STRING_EDIT_SCHED_MOD); + Context::getContext ().footnote (STRING_EDIT_SCHED_MOD); task.set ("scheduled", Datetime (value, dateformat).toEpochString ()); } } else { - context.footnote (STRING_EDIT_SCHED_MOD); + Context::getContext ().footnote (STRING_EDIT_SCHED_MOD); task.set ("scheduled", Datetime (value, dateformat).toEpochString ()); } } @@ -454,7 +452,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (task.get ("scheduled") != "") { - context.footnote ("Scheduled date removed."); + Context::getContext ().footnote ("Scheduled date removed."); task.remove ("scheduled"); } } @@ -467,13 +465,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != formatDate (task, "due", dateformat)) { - context.footnote (STRING_EDIT_DUE_MOD); + Context::getContext ().footnote (STRING_EDIT_DUE_MOD); task.set ("due", Datetime (value, dateformat).toEpochString ()); } } else { - context.footnote (STRING_EDIT_DUE_MOD); + Context::getContext ().footnote (STRING_EDIT_DUE_MOD); task.set ("due", Datetime (value, dateformat).toEpochString ()); } } @@ -484,11 +482,11 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string if (task.getStatus () == Task::recurring || task.get ("parent") != "") { - context.footnote ("Cannot remove a due date from a recurring task."); + Context::getContext ().footnote ("Cannot remove a due date from a recurring task."); } else { - context.footnote ("Due date removed."); + Context::getContext ().footnote ("Due date removed."); task.remove ("due"); } } @@ -502,13 +500,13 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != formatDate (task, "until", dateformat)) { - context.footnote (STRING_EDIT_UNTIL_MOD); + Context::getContext ().footnote (STRING_EDIT_UNTIL_MOD); task.set ("until", Datetime (value, dateformat).toEpochString ()); } } else { - context.footnote (STRING_EDIT_UNTIL_MOD); + Context::getContext ().footnote (STRING_EDIT_UNTIL_MOD); task.set ("until", Datetime (value, dateformat).toEpochString ()); } } @@ -516,7 +514,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (task.get ("until") != "") { - context.footnote ("Until date removed."); + Context::getContext ().footnote ("Until date removed."); task.remove ("until"); } } @@ -531,7 +529,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string std::string::size_type idx = 0; if (p.parse (value, idx)) { - context.footnote ("Recurrence modified."); + Context::getContext ().footnote ("Recurrence modified."); if (task.get ("due") != "") { task.set ("recur", value); @@ -545,7 +543,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string } else { - context.footnote ("Recurrence removed."); + Context::getContext ().footnote ("Recurrence removed."); task.setStatus (Task::pending); task.remove ("recur"); task.remove ("until"); @@ -562,14 +560,14 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != formatDate (task, "wait", dateformat)) { - context.footnote (STRING_EDIT_WAIT_MOD); + Context::getContext ().footnote (STRING_EDIT_WAIT_MOD); task.set ("wait", Datetime (value, dateformat).toEpochString ()); task.setStatus (Task::waiting); } } else { - context.footnote (STRING_EDIT_WAIT_MOD); + Context::getContext ().footnote (STRING_EDIT_WAIT_MOD); task.set ("wait", Datetime (value, dateformat).toEpochString ()); task.setStatus (Task::waiting); } @@ -578,7 +576,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (task.get ("wait") != "") { - context.footnote ("Wait date removed."); + Context::getContext ().footnote ("Wait date removed."); task.remove ("wait"); task.setStatus (Task::pending); } @@ -590,12 +588,12 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != "") { - context.footnote ("Parent UUID modified."); + Context::getContext ().footnote ("Parent UUID modified."); task.set ("parent", value); } else { - context.footnote ("Parent UUID removed."); + Context::getContext ().footnote ("Parent UUID removed."); task.remove ("parent"); } } @@ -659,9 +657,9 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string } // UDAs - for (auto& col : context.columns) + for (auto& col : Context::getContext ().columns) { - auto type = context.config.get ("uda." + col.first + ".type"); + auto type = Context::getContext ().config.get ("uda." + col.first + ".type"); if (type != "") { auto value = findValue (after, "\n UDA " + col.first + ":"); @@ -672,7 +670,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string { if (value != "") { - context.footnote (format ("UDA {1} modified.", col.first)); + Context::getContext ().footnote (format ("UDA {1} modified.", col.first)); if (type == "string") { @@ -699,7 +697,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string } else { - context.footnote (format ("UDA {1} deleted.", col.first)); + Context::getContext ().footnote (format ("UDA {1} deleted.", col.first)); task.remove (col.first); } } @@ -727,7 +725,7 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string CmdEdit::editResult CmdEdit::editFile (Task& task) { // Check for file permissions. - Directory location (context.config.get ("data.location")); + Directory location (Context::getContext ().config.get ("data.location")); if (! location.writable ()) throw std::string ("Your data.location directory is not writable."); @@ -738,9 +736,9 @@ CmdEdit::editResult CmdEdit::editFile (Task& task) // Determine the output date format, which uses a hierarchy of definitions. // rc.dateformat.edit // rc.dateformat - auto dateformat = context.config.get ("dateformat.edit"); + auto dateformat = Context::getContext ().config.get ("dateformat.edit"); if (dateformat == "") - dateformat = context.config.get ("dateformat"); + dateformat = Context::getContext ().config.get ("dateformat"); // Change directory for the editor auto current_dir = Directory::cwd (); @@ -758,7 +756,7 @@ CmdEdit::editResult CmdEdit::editFile (Task& task) File::write (file.str (), before); // Determine correct editor: .taskrc:editor > $VISUAL > $EDITOR > vi - auto editor = context.config.get ("editor"); + auto editor = Context::getContext ().config.get ("editor"); char* peditor = getenv ("VISUAL"); if (editor == "" && peditor) editor = std::string (peditor); peditor = getenv ("EDITOR"); diff --git a/src/commands/CmdExec.cpp b/src/commands/CmdExec.cpp index 4435d2297..117ed7443 100644 --- a/src/commands/CmdExec.cpp +++ b/src/commands/CmdExec.cpp @@ -30,8 +30,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdExec::CmdExec () { @@ -51,7 +49,7 @@ CmdExec::CmdExec () //////////////////////////////////////////////////////////////////////////////// int CmdExec::execute (std::string&) { - return system (join (" ", context.cli2.getWords ()).c_str ()); + return system (join (" ", Context::getContext ().cli2.getWords ()).c_str ()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdExport.cpp b/src/commands/CmdExport.cpp index b0d9b74c6..4afcd4abd 100644 --- a/src/commands/CmdExport.cpp +++ b/src/commands/CmdExport.cpp @@ -30,8 +30,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdExport::CmdExport () { @@ -68,11 +66,11 @@ int CmdExport::execute (std::string& output) // Obey 'limit:N'. int rows = 0; int lines = 0; - context.getLimits (rows, lines); + Context::getContext ().getLimits (rows, lines); int limit = (rows > lines ? rows : lines); // Is output contained within a JSON array? - bool json_array = context.config.getBoolean ("json.array"); + bool json_array = Context::getContext ().config.getBoolean ("json.array"); // Compose output. if (json_array) @@ -101,7 +99,7 @@ int CmdExport::execute (std::string& output) if (json_array) output += "]\n"; - context.time_render_us += timer.total_us (); + Context::getContext ().time_render_us += timer.total_us (); return rc; } diff --git a/src/commands/CmdGet.cpp b/src/commands/CmdGet.cpp index d29093e47..6be5500f5 100644 --- a/src/commands/CmdGet.cpp +++ b/src/commands/CmdGet.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdGet::CmdGet () { @@ -60,7 +58,7 @@ CmdGet::CmdGet () int CmdGet::execute (std::string& output) { std::vector results; - for (auto& arg : context.cli2._args) + for (auto& arg : Context::getContext ().cli2._args) { switch (arg._lextype) { diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index d80ae8b99..7f0e97658 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdHelp::CmdHelp () { @@ -54,7 +52,7 @@ CmdHelp::CmdHelp () //////////////////////////////////////////////////////////////////////////////// int CmdHelp::execute (std::string& output) { - auto words = context.cli2.getWords (); + auto words = Context::getContext ().cli2.getWords (); if (words.size () == 1 && closeEnough ("usage", words[0])) output = '\n' + composeUsage () @@ -183,7 +181,7 @@ int CmdHelp::execute (std::string& output) std::string CmdHelp::composeUsage () const { Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.add (""); view.add (""); view.add (""); @@ -196,7 +194,7 @@ std::string CmdHelp::composeUsage () const // Obsolete method of getting a list of all commands. std::vector all; - for (auto& cmd : context.commands) + for (auto& cmd : Context::getContext ().commands) all.push_back (cmd.first); // Sort alphabetically by usage. @@ -208,8 +206,8 @@ std::string CmdHelp::composeUsage () const if (name[0] != '_') { row = view.addRow (); - view.set (row, 1, context.commands[name]->usage ()); - view.set (row, 2, context.commands[name]->description ()); + view.set (row, 1, Context::getContext ().commands[name]->usage ()); + view.set (row, 2, Context::getContext ().commands[name]->description ()); } } @@ -219,8 +217,8 @@ std::string CmdHelp::composeUsage () const if (name[0] == '_') { row = view.addRow (); - view.set (row, 1, context.commands[name]->usage ()); - view.set (row, 2, context.commands[name]->description ()); + view.set (row, 1, Context::getContext ().commands[name]->usage ()); + view.set (row, 2, Context::getContext ().commands[name]->description ()); } } @@ -228,7 +226,7 @@ std::string CmdHelp::composeUsage () const row = view.addRow (); view.set (row, 1, " "); - for (auto& alias : context.config) + for (auto& alias : Context::getContext ().config) { if (alias.first.substr (0, 6) == "alias.") { diff --git a/src/commands/CmdHistory.cpp b/src/commands/CmdHistory.cpp index c6604200b..3aa294d43 100644 --- a/src/commands/CmdHistory.cpp +++ b/src/commands/CmdHistory.cpp @@ -42,8 +42,6 @@ #define STRING_CMD_HISTORY_COMP "Completed" #define STRING_CMD_HISTORY_DEL "Deleted" -extern Context context; - //////////////////////////////////////////////////////////////////////////////// template CmdHistoryBase::CmdHistoryBase () @@ -66,21 +64,21 @@ CmdHistoryBase::CmdHistoryBase () template void CmdHistoryBase::outputGraphical (std::string& output) { - auto widthOfBar = context.getWidth () - HistoryStrategy::labelWidth; + auto widthOfBar = Context::getContext ().getWidth () - HistoryStrategy::labelWidth; // Now build the view. Table view; setHeaderUnderline (view); - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); HistoryStrategy::setupTableDates (view); view.add ("Number Added/Completed/Deleted", true, false); // Fixed. - Color color_add (context.config.get ("color.history.add")); - Color color_done (context.config.get ("color.history.done")); - Color color_delete (context.config.get ("color.history.delete")); - Color label (context.config.get ("color.label")); + Color color_add (Context::getContext ().config.get ("color.history.add")); + Color color_done (Context::getContext ().config.get ("color.history.done")); + Color color_delete (Context::getContext ().config.get ("color.history.delete")); + Color label (Context::getContext ().config.get ("color.label")); // Determine the longest line, and the longest "added" line. auto maxAddedLine = 0; @@ -121,7 +119,7 @@ void CmdHistoryBase::outputGraphical (std::string& output) unsigned int deletedBar = (widthOfBar * deletedGroup[i.first]) / maxLine; std::string bar; - if (context.color ()) + if (Context::getContext ().color ()) { std::string aBar; if (addedGroup[i.first]) @@ -173,7 +171,7 @@ void CmdHistoryBase::outputGraphical (std::string& output) << view.render () << '\n'; - if (context.color ()) + if (Context::getContext ().color ()) out << format ("Legend: {1}, {2}, {3}", color_add.colorize (STRING_CMD_HISTORY_ADDED), color_done.colorize (STRING_CMD_HISTORY_COMP), @@ -185,7 +183,7 @@ void CmdHistoryBase::outputGraphical (std::string& output) } else { - context.footnote ("No tasks."); + Context::getContext ().footnote ("No tasks."); rc = 1; } @@ -198,7 +196,7 @@ void CmdHistoryBase::outputTabular (std::string& output) { Table view; setHeaderUnderline (view); - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); HistoryStrategy::setupTableDates (view); @@ -245,7 +243,7 @@ void CmdHistoryBase::outputTabular (std::string& output) } Color net_color; - if (context.color () && net) + if (Context::getContext ().color () && net) net_color = net > 0 ? Color (Color::red) : Color (Color::green); @@ -260,7 +258,7 @@ void CmdHistoryBase::outputTabular (std::string& output) row = view.addRow (); Color row_color; - if (context.color ()) + if (Context::getContext ().color ()) row_color = Color (Color::nocolor, Color::nocolor, false, true, false); view.set (row, HistoryStrategy::dateFieldCount - 1, "Average", row_color); @@ -277,7 +275,7 @@ void CmdHistoryBase::outputTabular (std::string& output) << '\n'; else { - context.footnote ("No tasks."); + Context::getContext ().footnote ("No tasks."); rc = 1; } diff --git a/src/commands/CmdIDs.cpp b/src/commands/CmdIDs.cpp index 2c3a884d5..cf2200f2e 100644 --- a/src/commands/CmdIDs.cpp +++ b/src/commands/CmdIDs.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - std::string zshColonReplacement = ","; //////////////////////////////////////////////////////////////////////////////// @@ -72,7 +70,7 @@ int CmdIDs::execute (std::string& output) std::sort (ids.begin (), ids.end ()); output = compressIds (ids) + '\n'; - context.headers.clear (); + Context::getContext ().headers.clear (); return 0; } @@ -166,7 +164,7 @@ int CmdCompletionIds::execute (std::string& output) std::sort (ids.begin (), ids.end ()); output = join ("\n", ids) + '\n'; - context.headers.clear (); + Context::getContext ().headers.clear (); return 0; } @@ -207,7 +205,7 @@ int CmdZshCompletionIds::execute (std::string& output) output = out.str (); - context.headers.clear (); + Context::getContext ().headers.clear (); return 0; } @@ -244,7 +242,7 @@ int CmdUUIDs::execute (std::string& output) std::sort (uuids.begin (), uuids.end ()); output = join (" ", uuids) + '\n'; - context.headers.clear (); + Context::getContext ().headers.clear (); return 0; } @@ -281,7 +279,7 @@ int CmdCompletionUuids::execute (std::string& output) std::sort (uuids.begin (), uuids.end ()); output = join ("\n", uuids) + '\n'; - context.headers.clear (); + Context::getContext ().headers.clear (); return 0; } @@ -320,7 +318,7 @@ int CmdZshCompletionUuids::execute (std::string& output) output = out.str (); - context.headers.clear (); + Context::getContext ().headers.clear (); return 0; } diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index 7ca2f2a82..15e78eecd 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdImport::CmdImport () { @@ -58,7 +56,7 @@ int CmdImport::execute (std::string&) auto count = 0; // Get filenames from command line arguments. - auto words = context.cli2.getWords (); + auto words = Context::getContext ().cli2.getWords (); if (! words.size () || (words.size () == 1 && words[0] == "-")) { @@ -91,7 +89,7 @@ int CmdImport::execute (std::string&) } } - context.footnote (format ("Imported {1} tasks.", count)); + Context::getContext ().footnote (format ("Imported {1} tasks.", count)); return rc; } @@ -177,7 +175,7 @@ void CmdImport::importSingleTask (json::object* obj) // Check whether the imported task is new or a modified existing task. Task before; - if (context.tdb2.get (task.get ("uuid"), before)) + if (Context::getContext ().tdb2.get (task.get ("uuid"), before)) { // We need to neglect updates from attributes with dynamic defaults // unless they have been explicitly specified on import. @@ -214,7 +212,7 @@ void CmdImport::importSingleTask (json::object* obj) } else { - context.tdb2.add (task); + Context::getContext ().tdb2.add (task); std::cout << " add "; } diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index c36bd62bd..2323c002c 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -38,8 +38,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdInfo::CmdInfo () { @@ -74,23 +72,23 @@ int CmdInfo::execute (std::string& output) if (! filtered.size ()) { - context.footnote ("No matches."); + Context::getContext ().footnote ("No matches."); rc = 1; } // Get the undo data. std::vector undo; - if (context.config.getBoolean ("journal.info")) - undo = context.tdb2.undo.get_lines (); + if (Context::getContext ().config.getBoolean ("journal.info")) + undo = Context::getContext ().tdb2.undo.get_lines (); // Determine the output date format, which uses a hierarchy of definitions. // rc.dateformat.info // rc.dateformat - auto dateformat = context.config.get ("dateformat.info"); + auto dateformat = Context::getContext ().config.get ("dateformat.info"); if (dateformat == "") - dateformat = context.config.get ("dateformat"); + dateformat = Context::getContext ().config.get ("dateformat"); - auto dateformatanno = context.config.get ("dateformat.annotation"); + auto dateformatanno = Context::getContext ().config.get ("dateformat.annotation"); if (dateformatanno == "") dateformatanno = dateformat; @@ -99,10 +97,10 @@ int CmdInfo::execute (std::string& output) for (auto& task : filtered) { Table view; - view.width (context.getWidth ()); - if (context.config.getBoolean ("obfuscate")) + view.width (Context::getContext ().getWidth ()); + if (Context::getContext ().config.getBoolean ("obfuscate")) view.obfuscate (); - if (context.color ()) + if (Context::getContext ().color ()) view.forceColor (); view.add ("Name"); view.add ("Value"); @@ -121,7 +119,7 @@ int CmdInfo::execute (std::string& output) Color c; autoColorize (task, c); auto description = task.get ("description"); - auto indent = context.config.getInteger ("indent.annotation"); + auto indent = Context::getContext ().config.getInteger ("indent.annotation"); for (auto& anno : task.getAnnotations ()) description += '\n' @@ -381,9 +379,9 @@ int CmdInfo::execute (std::string& output) std::string type; for (auto& att: all) { - if (context.columns.find (att) != context.columns.end ()) + if (Context::getContext ().columns.find (att) != Context::getContext ().columns.end ()) { - Column* col = context.columns[att]; + Column* col = Context::getContext ().columns[att]; if (col->is_uda ()) { auto value = task.get (att); @@ -415,7 +413,7 @@ int CmdInfo::execute (std::string& output) for (auto& att : all) { if (att.substr (0, 11) != "annotation_" && - context.columns.find (att) == context.columns.end ()) + Context::getContext ().columns.find (att) == Context::getContext ().columns.end ()) { row = view.addRow (); view.set (row, 0, '[' + att); @@ -428,19 +426,19 @@ int CmdInfo::execute (std::string& output) if (task.urgency () != 0.0) { setHeaderUnderline (urgencyDetails); - if (context.color ()) + if (Context::getContext ().color ()) { - Color alternate (context.config.get ("color.alternate")); + Color alternate (Context::getContext ().config.get ("color.alternate")); urgencyDetails.colorOdd (alternate); urgencyDetails.intraColorOdd (alternate); } - if (context.config.getBoolean ("obfuscate")) + if (Context::getContext ().config.getBoolean ("obfuscate")) urgencyDetails.obfuscate (); - if (context.config.getBoolean ("color")) + if (Context::getContext ().config.getBoolean ("color")) view.forceColor (); - urgencyDetails.width (context.getWidth ()); + urgencyDetails.width (Context::getContext ().getWidth ()); urgencyDetails.add (""); // Attribute urgencyDetails.add (""); // Value urgencyDetails.add (""); // * @@ -529,16 +527,16 @@ int CmdInfo::execute (std::string& output) Table journal; setHeaderUnderline (journal); - if (context.config.getBoolean ("obfuscate")) + if (Context::getContext ().config.getBoolean ("obfuscate")) journal.obfuscate (); - if (context.config.getBoolean ("color")) + if (Context::getContext ().config.getBoolean ("color")) journal.forceColor (); - journal.width (context.getWidth ()); + journal.width (Context::getContext ().getWidth ()); journal.add ("Date"); journal.add ("Modification"); - if (context.config.getBoolean ("journal.info") && + if (Context::getContext ().config.getBoolean ("journal.info") && undo.size () > 3) { // Scan the undo data for entries matching this task, without making diff --git a/src/commands/CmdLog.cpp b/src/commands/CmdLog.cpp index eee0cd042..922c697d6 100644 --- a/src/commands/CmdLog.cpp +++ b/src/commands/CmdLog.cpp @@ -30,8 +30,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdLog::CmdLog () { @@ -64,12 +62,12 @@ int CmdLog::execute (std::string& output) if (task.has ("wait")) throw std::string ("You cannot log waiting tasks."); - context.tdb2.add (task); + Context::getContext ().tdb2.add (task); - if (context.verbose ("project")) - context.footnote (onProjectChange (task)); + if (Context::getContext ().verbose ("project")) + Context::getContext ().footnote (onProjectChange (task)); - if (context.verbose ("new-uuid")) + if (Context::getContext ().verbose ("new-uuid")) output = format ("Logged task {1}.\n", task.get ("uuid")); return 0; diff --git a/src/commands/CmdLogo.cpp b/src/commands/CmdLogo.cpp index f9e9c77c6..a6f1b1273 100644 --- a/src/commands/CmdLogo.cpp +++ b/src/commands/CmdLogo.cpp @@ -29,8 +29,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdLogo::CmdLogo () { @@ -83,10 +81,10 @@ int CmdLogo::execute (std::string& output) "" }; - if (! context.color ()) + if (! Context::getContext ().color ()) throw std::string ("The logo command requires that color support is enabled."); - std::string indent (context.config.getInteger ("indent.report"), ' '); + std::string indent (Context::getContext ().config.getInteger ("indent.report"), ' '); output += optionalBlankLine (); for (int line = 0; data[line][0]; ++line) diff --git a/src/commands/CmdModify.cpp b/src/commands/CmdModify.cpp index 520d9f788..3745d04a0 100644 --- a/src/commands/CmdModify.cpp +++ b/src/commands/CmdModify.cpp @@ -36,8 +36,6 @@ #define STRING_CMD_MODIFY_TASK_R "Modifying recurring task {1} '{2}'." #define STRING_CMD_MODIFY_RECUR "This is a recurring task. Do you want to modify all pending recurrences of this same task?" -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdModify::CmdModify () { @@ -65,7 +63,7 @@ int CmdModify::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -104,7 +102,7 @@ int CmdModify::execute (std::string&) // Now list the project changes. for (const auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Modified {1} task." : "Modified {1} tasks.", count); return rc; @@ -143,8 +141,8 @@ int CmdModify::modifyAndUpdate ( updateRecurrenceMask (after); feedback_affected ("Modifying task {1} '{2}'.", after); feedback_unblocked (after); - context.tdb2.modify (after); - if (context.verbose ("project") && projectChanges) + Context::getContext ().tdb2.modify (after); + if (Context::getContext ().verbose ("project") && projectChanges) (*projectChanges)[after.get ("project")] = onProjectChange (before, after); // Task has siblings - modify them. @@ -165,11 +163,11 @@ int CmdModify::modifyRecurrenceSiblings ( { auto count = 0; - if ((context.config.get ("recurrence.confirmation") == "prompt" + if ((Context::getContext ().config.get ("recurrence.confirmation") == "prompt" && confirm (STRING_CMD_MODIFY_RECUR)) || - context.config.getBoolean ("recurrence.confirmation")) + Context::getContext ().config.getBoolean ("recurrence.confirmation")) { - std::vector siblings = context.tdb2.siblings (task); + std::vector siblings = Context::getContext ().tdb2.siblings (task); for (auto& sibling : siblings) { Task alternate (sibling); @@ -178,16 +176,16 @@ int CmdModify::modifyRecurrenceSiblings ( ++count; feedback_affected (STRING_CMD_MODIFY_TASK_R, sibling); feedback_unblocked (sibling); - context.tdb2.modify (sibling); - if (context.verbose ("project") && projectChanges) + Context::getContext ().tdb2.modify (sibling); + if (Context::getContext ().verbose ("project") && projectChanges) (*projectChanges)[sibling.get ("project")] = onProjectChange (alternate, sibling); } // Modify the parent Task parent; - context.tdb2.get (task.get ("parent"), parent); + Context::getContext ().tdb2.get (task.get ("parent"), parent); parent.modify (Task::modReplace); - context.tdb2.modify (parent); + Context::getContext ().tdb2.modify (parent); } return count; @@ -200,9 +198,9 @@ int CmdModify::modifyRecurrenceParent ( { auto count = 0; - auto children = context.tdb2.children (task); + auto children = Context::getContext ().tdb2.children (task); if (children.size () && - (! context.config.getBoolean ("recurrence.confirmation") || + (! Context::getContext ().config.getBoolean ("recurrence.confirmation") || confirm (STRING_CMD_MODIFY_RECUR))) { for (auto& child : children) @@ -210,8 +208,8 @@ int CmdModify::modifyRecurrenceParent ( Task alternate (child); child.modify (Task::modReplace); updateRecurrenceMask (child); - context.tdb2.modify (child); - if (context.verbose ("project") && projectChanges) + Context::getContext ().tdb2.modify (child); + if (Context::getContext ().verbose ("project") && projectChanges) (*projectChanges)[child.get ("project")] = onProjectChange (alternate, child); ++count; feedback_affected (STRING_CMD_MODIFY_TASK_R, child); diff --git a/src/commands/CmdPrepend.cpp b/src/commands/CmdPrepend.cpp index ec83e65b4..cfd1376f7 100644 --- a/src/commands/CmdPrepend.cpp +++ b/src/commands/CmdPrepend.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdPrepend::CmdPrepend () { @@ -63,7 +61,7 @@ int CmdPrepend::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -85,33 +83,33 @@ int CmdPrepend::execute (std::string&) if (permission (taskDifferences (before, task) + question, filtered.size ())) { - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); ++count; feedback_affected ("Prepending to task {1} '{2}'.", task); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task, false); // Prepend to siblings. if (task.has ("parent")) { - if ((context.config.get ("recurrence.confirmation") == "prompt" + if ((Context::getContext ().config.get ("recurrence.confirmation") == "prompt" && confirm ("This is a recurring task. Do you want to prepend to all pending recurrences of this same task?")) || - context.config.getBoolean ("recurrence.confirmation")) + Context::getContext ().config.getBoolean ("recurrence.confirmation")) { - std::vector siblings = context.tdb2.siblings (task); + std::vector siblings = Context::getContext ().tdb2.siblings (task); for (auto& sibling : siblings) { sibling.modify (Task::modPrepend, true); - context.tdb2.modify (sibling); + Context::getContext ().tdb2.modify (sibling); ++count; feedback_affected ("Prepending to recurring task {1} '{2}'.", sibling); } // Prepend to the parent Task parent; - context.tdb2.get (task.get ("parent"), parent); + Context::getContext ().tdb2.get (task.get ("parent"), parent); parent.modify (Task::modPrepend, true); - context.tdb2.modify (parent); + Context::getContext ().tdb2.modify (parent); } } } @@ -127,7 +125,7 @@ int CmdPrepend::execute (std::string&) // Now list the project changes. for (auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Prepended {1} task." : "Prepended {1} tasks.", count); return rc; diff --git a/src/commands/CmdProjects.cpp b/src/commands/CmdProjects.cpp index 4c752989f..e9efe07ba 100644 --- a/src/commands/CmdProjects.cpp +++ b/src/commands/CmdProjects.cpp @@ -35,8 +35,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdProjects::CmdProjects () { @@ -61,10 +59,10 @@ int CmdProjects::execute (std::string& output) // Get all the tasks. handleUntil (); handleRecurrence (); - auto tasks = context.tdb2.pending.get_tasks (); + auto tasks = Context::getContext ().tdb2.pending.get_tasks (); - if (context.config.getBoolean ("list.all.projects")) - for (auto& task : context.tdb2.completed.get_tasks ()) + if (Context::getContext ().config.getBoolean ("list.all.projects")) + for (auto& task : Context::getContext ().tdb2.completed.get_tasks ()) tasks.push_back (task); // Apply the filter. @@ -106,7 +104,7 @@ int CmdProjects::execute (std::string& output) { // Render a list of project names from the map. Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.add ("Project"); view.add ("Tasks", false); setHeaderUnderline (view); @@ -180,10 +178,10 @@ int CmdCompletionProjects::execute (std::string& output) // Get all the tasks. handleUntil (); handleRecurrence (); - auto tasks = context.tdb2.pending.get_tasks (); + auto tasks = Context::getContext ().tdb2.pending.get_tasks (); - if (context.config.getBoolean ("list.all.projects")) - for (auto& task : context.tdb2.completed.get_tasks ()) + if (Context::getContext ().config.getBoolean ("list.all.projects")) + for (auto& task : Context::getContext ().tdb2.completed.get_tasks ()) tasks.push_back (task); // Apply the filter. diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index 055833bd1..ffb7ada19 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -32,8 +32,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdPurge::CmdPurge () { @@ -57,7 +55,7 @@ CmdPurge::CmdPurge () // - child tasks void CmdPurge::purgeTask (Task& task, int& count) { - context.tdb2.purge (task); + Context::getContext ().tdb2.purge (task); handleDeps (task); handleChildren (task, count); count++; @@ -70,14 +68,14 @@ void CmdPurge::handleDeps (Task& task) { std::string uuid = task.get ("uuid"); - for (auto& blockedConst: context.tdb2.all_tasks ()) + for (auto& blockedConst: Context::getContext ().tdb2.all_tasks ()) { Task& blocked = const_cast(blockedConst); if (blocked.has ("depends") && blocked.get ("depends").find (uuid) != std::string::npos) { blocked.removeDependency (uuid); - context.tdb2.modify (blocked); + Context::getContext ().tdb2.modify (blocked); } } } @@ -95,7 +93,7 @@ void CmdPurge::handleChildren (Task& task, int& count) std::vector children; // Find all child tasks - for (auto& childConst: context.tdb2.all_tasks ()) + for (auto& childConst: Context::getContext ().tdb2.all_tasks ()) { Task& child = const_cast (childConst); @@ -120,8 +118,8 @@ void CmdPurge::handleChildren (Task& task, int& count) task.get ("description"), children.size ()); - if (context.config.getBoolean ("recurrence.confirmation") || - (context.config.get ("recurrence.confirmation") == "prompt" + if (Context::getContext ().config.getBoolean ("recurrence.confirmation") || + (Context::getContext ().config.get ("recurrence.confirmation") == "prompt" && confirm (question))) { for (auto& child: children) @@ -145,7 +143,7 @@ int CmdPurge::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } diff --git a/src/commands/CmdReports.cpp b/src/commands/CmdReports.cpp index 3ac2be602..de7716ade 100644 --- a/src/commands/CmdReports.cpp +++ b/src/commands/CmdReports.cpp @@ -32,8 +32,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdReports::CmdReports () { @@ -56,7 +54,7 @@ int CmdReports::execute (std::string& output) std::vector reports; // Add custom reports. - for (auto& i : context.config) + for (auto& i : Context::getContext ().config) { if (i.first.substr (0, 7) == "report.") { @@ -85,7 +83,7 @@ int CmdReports::execute (std::string& output) // Compose the output. std::stringstream out; Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.add ("Report"); view.add ("Description"); setHeaderUnderline (view); @@ -94,7 +92,7 @@ int CmdReports::execute (std::string& output) { int row = view.addRow (); view.set (row, 0, report); - view.set (row, 1, context.commands[report]->description ()); + view.set (row, 1, Context::getContext ().commands[report]->description ()); } out << optionalBlankLine () diff --git a/src/commands/CmdShow.cpp b/src/commands/CmdShow.cpp index 5f414d5b2..ec6863b61 100644 --- a/src/commands/CmdShow.cpp +++ b/src/commands/CmdShow.cpp @@ -39,7 +39,6 @@ #define STRING_CMD_SHOW_DIFFER_COLOR "These are highlighted in {1} above." #define STRING_CMD_SHOW_CONFIG_ERROR "Configuration error: {1} contains an unrecognized value '{2}'." -extern Context context; extern std::string configurationDefaults; //////////////////////////////////////////////////////////////////////////////// @@ -66,11 +65,11 @@ int CmdShow::execute (std::string& output) // Obtain the arguments from the description. That way, things like '--' // have already been handled. - std::vector words = context.cli2.getWords (); + std::vector words = Context::getContext ().cli2.getWords (); if (words.size () > 1) throw std::string ("You can only specify 'all' or a search string."); - int width = context.getWidth (); + int width = Context::getContext ().getWidth (); // Complain about configuration variables that are not recognized. // These are the regular configuration variables. @@ -224,7 +223,7 @@ int CmdShow::execute (std::string& output) recognized += "_forcecolor "; std::vector unrecognized; - for (auto& i : context.config) + for (auto& i : Context::getContext ().config) { // Disallow partial matches by tacking a leading and trailing space on each // variable name. @@ -259,7 +258,7 @@ int CmdShow::execute (std::string& output) Configuration default_config; default_config.parse (configurationDefaults); - for (auto& i : context.config) + for (auto& i : Context::getContext ().config) if (i.second != default_config.get (i.first)) default_values.push_back (i.first); @@ -272,10 +271,10 @@ int CmdShow::execute (std::string& output) Color error; Color warning; - if (context.color ()) + if (Context::getContext ().color ()) { - error = Color (context.config.get ("color.error")); - warning = Color (context.config.get ("color.warning")); + error = Color (Context::getContext ().config.get ("color.error")); + warning = Color (Context::getContext ().config.get ("color.warning")); } bool issue_error = false; @@ -291,7 +290,7 @@ int CmdShow::execute (std::string& output) section = ""; std::string::size_type loc; - for (auto& i : context.config) + for (auto& i : Context::getContext ().config) { loc = i.first.find (section, 0); if (loc != std::string::npos) @@ -333,7 +332,7 @@ int CmdShow::execute (std::string& output) { out << "Some of your .taskrc variables differ from the default values.\n"; - if (context.color () && warning.nontrivial ()) + if (Context::getContext ().color () && warning.nontrivial ()) out << " " << format (STRING_CMD_SHOW_DIFFER_COLOR, warning.colorize ("color")) << "\n\n"; @@ -347,7 +346,7 @@ int CmdShow::execute (std::string& output) for (auto& i : unrecognized) out << " " << i << '\n'; - if (context.color () && error.nontrivial ()) + if (Context::getContext ().color () && error.nontrivial ()) out << '\n' << format (STRING_CMD_SHOW_DIFFER_COLOR, error.colorize ("color")); out << "\n\n"; @@ -360,7 +359,7 @@ int CmdShow::execute (std::string& output) // TODO Check for referenced but missing string files. // Check for bad values in rc.calendar.details. - std::string calendardetails = context.config.get ("calendar.details"); + std::string calendardetails = Context::getContext ().config.get ("calendar.details"); if (calendardetails != "full" && calendardetails != "sparse" && calendardetails != "none") @@ -368,7 +367,7 @@ int CmdShow::execute (std::string& output) << '\n'; // Check for bad values in rc.calendar.holidays. - std::string calendarholidays = context.config.get ("calendar.holidays"); + std::string calendarholidays = Context::getContext ().config.get ("calendar.holidays"); if (calendarholidays != "full" && calendarholidays != "sparse" && calendarholidays != "none") @@ -378,14 +377,14 @@ int CmdShow::execute (std::string& output) // Verify installation. This is mentioned in the documentation as the way // to ensure everything is properly installed. - if (context.config.size () == 0) + if (Context::getContext ().config.size () == 0) { out << "Configuration error: .taskrc contains no entries.\n"; rc = 1; } else { - Directory location (context.config.get ("data.location")); + Directory location (Context::getContext ().config.get ("data.location")); if (location._data == "") out << "Configuration error: data.location not specified in .taskrc file.\n"; @@ -413,13 +412,13 @@ CmdShowRaw::CmdShowRaw () int CmdShowRaw::execute (std::string& output) { // Get all the settings and sort alphabetically by name. - auto all = context.config.all (); + auto all = Context::getContext ().config.all (); std::sort (all.begin (), all.end ()); // Display them all. std::stringstream out; for (auto& i : all) - out << i << '=' << context.config.get (i) << '\n'; + out << i << '=' << Context::getContext ().config.get (i) << '\n'; output = out.str (); return 0; diff --git a/src/commands/CmdStart.cpp b/src/commands/CmdStart.cpp index 964bdd35c..0c67d5ab4 100644 --- a/src/commands/CmdStart.cpp +++ b/src/commands/CmdStart.cpp @@ -33,8 +33,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdStart::CmdStart () { @@ -63,7 +61,7 @@ int CmdStart::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -91,19 +89,19 @@ int CmdStart::execute (std::string&) task.setStatus (Task::pending); } - if (context.config.getBoolean ("journal.time")) - task.addAnnotation (context.config.get ("journal.time.start.annotation")); + if (Context::getContext ().config.getBoolean ("journal.time")) + task.addAnnotation (Context::getContext ().config.get ("journal.time.start.annotation")); if (permission (taskDifferences (before, task) + question, filtered.size ())) { updateRecurrenceMask (task); - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); ++count; feedback_affected ("Starting task {1} '{2}'.", task); if (!nagged) nagged = nag (task); dependencyChainOnStart (task); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task, false); } else @@ -127,7 +125,7 @@ int CmdStart::execute (std::string&) // Now list the project changes. for (auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Started {1} task." : "Started {1} tasks.", count); return rc; diff --git a/src/commands/CmdStats.cpp b/src/commands/CmdStats.cpp index 7b993d762..87ecf07e5 100644 --- a/src/commands/CmdStats.cpp +++ b/src/commands/CmdStats.cpp @@ -38,8 +38,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdStats::CmdStats () { @@ -62,23 +60,23 @@ int CmdStats::execute (std::string& output) int rc = 0; std::stringstream out; - std::string dateformat = context.config.get ("dateformat"); + std::string dateformat = Context::getContext ().config.get ("dateformat"); // Go get the file sizes. - size_t dataSize = context.tdb2.pending._file.size () - + context.tdb2.completed._file.size () - + context.tdb2.undo._file.size () - + context.tdb2.backlog._file.size (); + size_t dataSize = Context::getContext ().tdb2.pending._file.size () + + Context::getContext ().tdb2.completed._file.size () + + Context::getContext ().tdb2.undo._file.size () + + Context::getContext ().tdb2.backlog._file.size (); // Count the undo transactions. - std::vector undoTxns = context.tdb2.undo.get_lines (); + std::vector undoTxns = Context::getContext ().tdb2.undo.get_lines (); int undoCount = 0; for (auto& tx : undoTxns) if (tx == "---") ++undoCount; // Count the backlog transactions. - std::vector backlogTxns = context.tdb2.backlog.get_lines (); + std::vector backlogTxns = Context::getContext ().tdb2.backlog.get_lines (); int backlogCount = 0; for (auto& tx : backlogTxns) if (tx[0] == '{') @@ -86,7 +84,7 @@ int CmdStats::execute (std::string& output) // Get all the tasks. Filter filter; - std::vector all = context.tdb2.all_tasks (); + std::vector all = Context::getContext ().tdb2.all_tasks (); std::vector filtered; filter.subset (all, filtered); @@ -155,7 +153,7 @@ int CmdStats::execute (std::string& output) // Create a table for output. Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.intraPadding (2); view.add ("Category"); view.add ("Data"); @@ -280,9 +278,9 @@ int CmdStats::execute (std::string& output) } // If an alternating row color is specified, notify the table. - if (context.color ()) + if (Context::getContext ().color ()) { - Color alternate (context.config.get ("color.alternate")); + Color alternate (Context::getContext ().config.get ("color.alternate")); if (alternate.nontrivial ()) { view.colorOdd (alternate); diff --git a/src/commands/CmdStop.cpp b/src/commands/CmdStop.cpp index d48af2930..7ff5beeba 100644 --- a/src/commands/CmdStop.cpp +++ b/src/commands/CmdStop.cpp @@ -32,8 +32,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdStop::CmdStop () { @@ -62,7 +60,7 @@ int CmdStop::execute (std::string&) filter.subset (filtered); if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } @@ -83,17 +81,17 @@ int CmdStop::execute (std::string&) task.modify (Task::modAnnotate); task.remove ("start"); - if (context.config.getBoolean ("journal.time")) - task.addAnnotation (context.config.get ("journal.time.stop.annotation")); + if (Context::getContext ().config.getBoolean ("journal.time")) + task.addAnnotation (Context::getContext ().config.get ("journal.time.stop.annotation")); if (permission (taskDifferences (before, task) + question, filtered.size ())) { updateRecurrenceMask (task); - context.tdb2.modify (task); + Context::getContext ().tdb2.modify (task); ++count; feedback_affected ("Stopping task {1} '{2}'.", task); dependencyChainOnStart (task); - if (context.verbose ("project")) + if (Context::getContext ().verbose ("project")) projectChanges[task.get ("project")] = onProjectChange (task, false); } else @@ -117,7 +115,7 @@ int CmdStop::execute (std::string&) // Now list the project changes. for (auto& change : projectChanges) if (change.first != "") - context.footnote (change.second); + Context::getContext ().footnote (change.second); feedback_affected (count == 1 ? "Stopped {1} task." : "Stopped {1} tasks.", count); return rc; diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index ef1e732d9..d4e8719ad 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -37,8 +37,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdSummary::CmdSummary () { @@ -62,7 +60,7 @@ CmdSummary::CmdSummary () int CmdSummary::execute (std::string& output) { int rc = 0; - bool showAllProjects = context.config.getBoolean ("summary.all.projects"); + bool showAllProjects = Context::getContext ().config.getBoolean ("summary.all.projects"); // Apply filter. handleUntil (); @@ -132,7 +130,7 @@ int CmdSummary::execute (std::string& output) // Create a table for output. Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.add ("Project"); view.add ("Remaining", false); view.add ("Avg age", false); @@ -142,10 +140,10 @@ int CmdSummary::execute (std::string& output) Color bar_color; Color bg_color; - if (context.color ()) + if (Context::getContext ().color ()) { - bar_color = Color (context.config.get ("color.summary.bar")); - bg_color = Color (context.config.get ("color.summary.background")); + bar_color = Color (Context::getContext ().config.get ("color.summary.bar")); + bg_color = Color (Context::getContext ().config.get ("color.summary.background")); } int barWidth = 30; @@ -183,7 +181,7 @@ int CmdSummary::execute (std::string& output) std::string bar; std::string subbar; - if (context.color ()) + if (Context::getContext ().color ()) { bar += bar_color.colorize (std::string ( completedBar, ' ')); bar += bg_color.colorize (std::string (barWidth - completedBar, ' ')); diff --git a/src/commands/CmdSync.cpp b/src/commands/CmdSync.cpp index 19a8ad6f2..126980e4a 100644 --- a/src/commands/CmdSync.cpp +++ b/src/commands/CmdSync.cpp @@ -36,8 +36,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdSync::CmdSync () { @@ -67,12 +65,12 @@ int CmdSync::execute (std::string& output) // Loog for the 'init' keyword to indicate one-time pending.data upload. bool first_time_init = false; - std::vector words = context.cli2.getWords (); + std::vector words = Context::getContext ().cli2.getWords (); for (auto& word : words) { if (closeEnough ("initialize", word, 4)) { - if (!context.config.getBoolean ("confirmation") || + if (!Context::getContext ().config.getBoolean ("confirmation") || confirm ("Please confirm that you wish to upload all your tasks to the Taskserver")) first_time_init = true; else @@ -81,13 +79,13 @@ int CmdSync::execute (std::string& output) } // If no server is set up, quit. - std::string connection = context.config.get ("taskd.server"); + std::string connection = Context::getContext ().config.get ("taskd.server"); if (connection == "" || connection.rfind (':') == std::string::npos) throw std::string ("Taskserver is not configured."); // Obtain credentials. - std::string credentials_string = context.config.get ("taskd.credentials"); + std::string credentials_string = Context::getContext ().config.get ("taskd.credentials"); if (credentials_string == "") throw std::string ("Taskserver credentials malformed."); @@ -96,7 +94,7 @@ int CmdSync::execute (std::string& output) throw std::string ("Taskserver credentials malformed."); // This was a Boolean value in 2.3.0, and is a tri-state since 2.4.0. - std::string trust_value = context.config.get ("taskd.trust"); + std::string trust_value = Context::getContext ().config.get ("taskd.trust"); if (trust_value != "strict" && trust_value != "ignore hostname" && trust_value != "allow all") @@ -109,18 +107,18 @@ int CmdSync::execute (std::string& output) trust = TLSClient::ignore_hostname; // CA must exist, if provided. - File ca (context.config.get ("taskd.ca")); + File ca (Context::getContext ().config.get ("taskd.ca")); if (ca._data != "" && ! ca.exists ()) throw std::string ("CA certificate not found."); if (trust == TLSClient::allow_all && ca._data != "") throw std::string ("You should either provide a CA certificate or override verification, but not both."); - File certificate (context.config.get ("taskd.certificate")); + File certificate (Context::getContext ().config.get ("taskd.certificate")); if (! certificate.exists ()) throw std::string ("Taskserver certificate missing."); - File key (context.config.get ("taskd.key")); + File key (Context::getContext ().config.get ("taskd.key")); if (! key.exists ()) throw std::string ("Taskserver key missing."); @@ -132,9 +130,9 @@ int CmdSync::execute (std::string& output) { // Delete backlog.data. Because if we're uploading everything, the list of // deltas is meaningless. - context.tdb2.backlog._file.truncate (); + Context::getContext ().tdb2.backlog._file.truncate (); - auto all_tasks = context.tdb2.all_tasks (); + auto all_tasks = Context::getContext ().tdb2.all_tasks (); for (auto& i : all_tasks) { payload += i.composeJSON () + '\n'; @@ -143,7 +141,7 @@ int CmdSync::execute (std::string& output) } else { - std::vector lines = context.tdb2.backlog.get_lines (); + std::vector lines = Context::getContext ().tdb2.backlog.get_lines (); for (auto& i : lines) { if (i[0] == '{') @@ -169,7 +167,7 @@ int CmdSync::execute (std::string& output) request.setPayload (payload); - if (context.verbose ("sync")) + if (Context::getContext ().verbose ("sync")) out << format ("Syncing with {1}", connection) << '\n'; @@ -189,10 +187,10 @@ int CmdSync::execute (std::string& output) { Color colorAdded; Color colorChanged; - if (context.color ()) + if (Context::getContext ().color ()) { - colorAdded = Color (context.config.get ("color.sync.added")); - colorChanged = Color (context.config.get ("color.sync.changed")); + colorAdded = Color (Context::getContext ().config.get ("color.sync.added")); + colorChanged = Color (Context::getContext ().config.get ("color.sync.changed")); } int download_count = 0; @@ -203,7 +201,7 @@ int CmdSync::execute (std::string& output) // the payload, so if there are two or more lines, then we have merging // to perform, otherwise it's just a backlog.data update. if (lines.size () > 1) - context.tdb2.all_tasks (); + Context::getContext ().tdb2.all_tasks (); std::string sync_key = ""; for (auto& line : lines) @@ -217,33 +215,33 @@ int CmdSync::execute (std::string& output) // Is it a new task from the server, or an update to an existing one? Task dummy; - if (context.tdb2.get (uuid, dummy)) + if (Context::getContext ().tdb2.get (uuid, dummy)) { - if (context.verbose ("sync")) + if (Context::getContext ().verbose ("sync")) out << " " << colorChanged.colorize ( format ("modify {1} '{2}'", uuid, from_server.get ("description"))) << '\n'; - context.tdb2.modify (from_server, false); + Context::getContext ().tdb2.modify (from_server, false); } else { - if (context.verbose ("sync")) + if (Context::getContext ().verbose ("sync")) out << " " << colorAdded.colorize ( format (" add {1} '{2}'", uuid, from_server.get ("description"))) << '\n'; - context.tdb2.add (from_server, false); + Context::getContext ().tdb2.add (from_server, false); } } else if (line != "") { sync_key = line; - context.debug ("Sync key " + sync_key); + Context::getContext ().debug ("Sync key " + sync_key); } // Otherwise line is blank, so ignore it. @@ -254,46 +252,46 @@ int CmdSync::execute (std::string& output) if (sync_key != "") { // Truncate backlog.data, save new sync_key. - context.tdb2.backlog._file.truncate (); - context.tdb2.backlog.clear_tasks (); - context.tdb2.backlog.clear_lines (); - context.tdb2.backlog.add_line (sync_key + '\n'); + Context::getContext ().tdb2.backlog._file.truncate (); + Context::getContext ().tdb2.backlog.clear_tasks (); + Context::getContext ().tdb2.backlog.clear_lines (); + Context::getContext ().tdb2.backlog.add_line (sync_key + '\n'); // Present a clear status message. if (upload_count == 0 && download_count == 0) // Note: should not happen - expect code 201 instead. - context.footnote ("Sync successful."); + Context::getContext ().footnote ("Sync successful."); else if (upload_count == 0 && download_count > 0) - context.footnote (format ("Sync successful. {1} changes downloaded.", download_count)); + Context::getContext ().footnote (format ("Sync successful. {1} changes downloaded.", download_count)); else if (upload_count > 0 && download_count == 0) - context.footnote (format ("Sync successful. {1} changes uploaded.", upload_count)); + Context::getContext ().footnote (format ("Sync successful. {1} changes uploaded.", upload_count)); else if (upload_count > 0 && download_count > 0) - context.footnote (format ("Sync successful. {1} changes uploaded, {2} changes downloaded.", upload_count, download_count)); + Context::getContext ().footnote (format ("Sync successful. {1} changes uploaded, {2} changes downloaded.", upload_count, download_count)); } status = 0; } else if (code == "201") { - context.footnote ("Sync successful. No changes."); + Context::getContext ().footnote ("Sync successful. No changes."); status = 0; } else if (code == "301") { std::string new_server = response.get ("info"); - context.config.set ("taskd.server", new_server); - context.error ("The server account has been relocated. Please update your configuration using:"); - context.error (" " + format ("task config taskd.server {1}", new_server)); + Context::getContext ().config.set ("taskd.server", new_server); + Context::getContext ().error ("The server account has been relocated. Please update your configuration using:"); + Context::getContext ().error (" " + format ("task config taskd.server {1}", new_server)); status = 2; } else if (code == "430") { - context.error ("Sync failed. Either your credentials are incorrect, or your account doesn't exist on the Taskserver."); + Context::getContext ().error ("Sync failed. Either your credentials are incorrect, or your account doesn't exist on the Taskserver."); status = 2; } else { - context.error (format ("Sync failed. The Taskserver returned error: {1} {2}", + Context::getContext ().error (format ("Sync failed. The Taskserver returned error: {1} {2}", code, response.get ("status"))); status = 2; @@ -303,10 +301,10 @@ int CmdSync::execute (std::string& output) std::string to_be_displayed = response.get ("messages"); if (to_be_displayed != "") { - if (context.verbose ("footnote")) - context.footnote (to_be_displayed); + if (Context::getContext ().verbose ("footnote")) + Context::getContext ().footnote (to_be_displayed); else - context.debug (to_be_displayed); + Context::getContext ().debug (to_be_displayed); } } @@ -319,11 +317,11 @@ int CmdSync::execute (std::string& output) // - No signal/cable else { - context.error ("Sync failed. Could not connect to the Taskserver."); + Context::getContext ().error ("Sync failed. Could not connect to the Taskserver."); status = 1; } - if (context.verbose ("sync")) + if (Context::getContext ().verbose ("sync")) out << '\n'; output = out.str (); @@ -365,10 +363,10 @@ bool CmdSync::send ( try { TLSClient client; - client.debug (context.config.getInteger ("debug.tls")); + client.debug (Context::getContext ().config.getInteger ("debug.tls")); client.trust (trust); - client.ciphers (context.config.get ("taskd.ciphers")); + client.ciphers (Context::getContext ().config.get ("taskd.ciphers")); client.init (ca, certificate, key); client.connect (server, port); client.send (request.serialize () + '\n'); @@ -383,7 +381,7 @@ bool CmdSync::send ( catch (std::string& error) { - context.error (error); + Context::getContext ().error (error); } // Indicate message failed. diff --git a/src/commands/CmdTags.cpp b/src/commands/CmdTags.cpp index b289dfd19..a9d25f865 100644 --- a/src/commands/CmdTags.cpp +++ b/src/commands/CmdTags.cpp @@ -35,8 +35,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdTags::CmdTags () { @@ -60,10 +58,10 @@ int CmdTags::execute (std::string& output) std::stringstream out; // Get all the tasks. - auto tasks = context.tdb2.pending.get_tasks (); + auto tasks = Context::getContext ().tdb2.pending.get_tasks (); - if (context.config.getBoolean ("list.all.tags")) - for (auto& task : context.tdb2.completed.get_tasks ()) + if (Context::getContext ().config.getBoolean ("list.all.tags")) + for (auto& task : Context::getContext ().tdb2.completed.get_tasks ()) tasks.push_back (task); int quantity = tasks.size (); @@ -89,20 +87,20 @@ int CmdTags::execute (std::string& output) { // Render a list of tags names from the map. Table view; - view.width (context.getWidth ()); + view.width (Context::getContext ().getWidth ()); view.add ("Tag"); view.add ("Count", false); setHeaderUnderline (view); Color bold; - if (context.color ()) + if (Context::getContext ().color ()) bold = Color ("bold"); bool special = false; for (auto& i : unique) { // Highlight the special tags. - special = (context.color () && + special = (Context::getContext ().color () && (i.first == "nocolor" || i.first == "nonag" || i.first == "nocal" || @@ -118,20 +116,20 @@ int CmdTags::execute (std::string& output) << optionalBlankLine (); if (unique.size () == 1) - context.footnote ("1 tag"); + Context::getContext ().footnote ("1 tag"); else - context.footnote (format ("{1} tags", unique.size ())); + Context::getContext ().footnote (format ("{1} tags", unique.size ())); if (quantity == 1) - context.footnote ("(1 task)"); + Context::getContext ().footnote ("(1 task)"); else - context.footnote (format ("({1} tasks)", quantity)); + Context::getContext ().footnote (format ("({1} tasks)", quantity)); out << '\n'; } else { - context.footnote ("No tags."); + Context::getContext ().footnote ("No tags."); rc = 1; } @@ -159,10 +157,10 @@ CmdCompletionTags::CmdCompletionTags () int CmdCompletionTags::execute (std::string& output) { // Get all the tasks. - auto tasks = context.tdb2.pending.get_tasks (); + auto tasks = Context::getContext ().tdb2.pending.get_tasks (); - if (context.config.getBoolean ("complete.all.tags")) - for (auto& task : context.tdb2.completed.get_tasks ()) + if (Context::getContext ().config.getBoolean ("complete.all.tags")) + for (auto& task : Context::getContext ().tdb2.completed.get_tasks ()) tasks.push_back (task); // Apply filter. diff --git a/src/commands/CmdTimesheet.cpp b/src/commands/CmdTimesheet.cpp index e083290de..c9df6bb5a 100644 --- a/src/commands/CmdTimesheet.cpp +++ b/src/commands/CmdTimesheet.cpp @@ -37,8 +37,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdTimesheet::CmdTimesheet () { @@ -62,7 +60,7 @@ int CmdTimesheet::execute (std::string& output) // Detect a filter. bool hasFilter {false}; - for (auto& a : context.cli2._args) + for (auto& a : Context::getContext ().cli2._args) { if (a.hasTag ("FILTER")) { @@ -73,10 +71,10 @@ int CmdTimesheet::execute (std::string& output) if (! hasFilter) { - auto defaultFilter = context.config.get ("report.timesheet.filter"); + auto defaultFilter = Context::getContext ().config.get ("report.timesheet.filter"); if (defaultFilter == "") defaultFilter = "(+PENDING and start.after:now-4wks) or (+COMPLETED and end.after:now-4wks)"; - context.cli2.addFilter (defaultFilter); + Context::getContext ().cli2.addFilter (defaultFilter); } // Apply filter to get a set of tasks. @@ -115,8 +113,8 @@ int CmdTimesheet::execute (std::string& output) // Render the completed table. Table table; - table.width (context.getWidth ()); - if (context.config.getBoolean ("obfuscate")) + table.width (Context::getContext ().getWidth ()); + if (Context::getContext ().config.getBoolean ("obfuscate")) table.obfuscate (); table.add ("Wk"); table.add ("Date"); @@ -127,7 +125,7 @@ int CmdTimesheet::execute (std::string& output) table.add ("Task"); setHeaderUnderline (table); - auto dateformat = context.config.get ("dateformat"); + auto dateformat = Context::getContext ().config.get ("dateformat"); int previous_week = -1; std::string previous_date = ""; @@ -189,7 +187,7 @@ int CmdTimesheet::execute (std::string& output) << table.render () << '\n'; - if (context.verbose ("affected")) + if (Context::getContext ().verbose ("affected")) out << format ("{1} completed, {2} started.", num_completed, num_started) << '\n'; diff --git a/src/commands/CmdUDAs.cpp b/src/commands/CmdUDAs.cpp index 5b06c7d75..9acef008e 100644 --- a/src/commands/CmdUDAs.cpp +++ b/src/commands/CmdUDAs.cpp @@ -36,8 +36,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdUDAs::CmdUDAs () { @@ -61,7 +59,7 @@ int CmdUDAs::execute (std::string& output) std::stringstream out; std::vector udas; - for (auto& name : context.config) + for (auto& name : Context::getContext ().config) { if (name.first.substr (0, 4) == "uda." && name.first.find (".type") != std::string::npos) @@ -84,7 +82,7 @@ int CmdUDAs::execute (std::string& output) // Render a list of UDA name, type, label, allowed values, // possible default value, and finally the usage count. Table table; - table.width (context.getWidth ()); + table.width (Context::getContext ().getWidth ()); table.add ("Name"); table.add ("Type"); table.add ("Label"); @@ -95,10 +93,10 @@ int CmdUDAs::execute (std::string& output) for (auto& uda : udas) { - std::string type = context.config.get ("uda." + uda + ".type"); - std::string label = context.config.get ("uda." + uda + ".label"); - std::string values = context.config.get ("uda." + uda + ".values"); - std::string defval = context.config.get ("uda." + uda + ".default"); + std::string type = Context::getContext ().config.get ("uda." + uda + ".type"); + std::string label = Context::getContext ().config.get ("uda." + uda + ".label"); + std::string values = Context::getContext ().config.get ("uda." + uda + ".values"); + std::string defval = Context::getContext ().config.get ("uda." + uda + ".default"); if (label == "") label = uda; @@ -137,7 +135,7 @@ int CmdUDAs::execute (std::string& output) { for (auto& att : i.data) if (att.first.substr (0, 11) != "annotation_" && - context.columns.find (att.first) == context.columns.end ()) + Context::getContext ().columns.find (att.first) == Context::getContext ().columns.end ()) orphans[att.first]++; } @@ -145,7 +143,7 @@ int CmdUDAs::execute (std::string& output) { // Display the orphans and their counts. Table orphanTable; - orphanTable.width (context.getWidth ()); + orphanTable.width (Context::getContext ().getWidth ()); orphanTable.add ("Orphan UDA"); orphanTable.add ("Usage Count"); setHeaderUnderline (orphanTable); @@ -190,7 +188,7 @@ CmdCompletionUDAs::CmdCompletionUDAs () int CmdCompletionUDAs::execute (std::string& output) { std::vector udas; - for (auto& name : context.config) + for (auto& name : Context::getContext ().config) { if (name.first.substr (0, 4) == "uda." && name.first.find (".type") != std::string::npos) diff --git a/src/commands/CmdUndo.cpp b/src/commands/CmdUndo.cpp index 0018da368..b0431166e 100644 --- a/src/commands/CmdUndo.cpp +++ b/src/commands/CmdUndo.cpp @@ -28,8 +28,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdUndo::CmdUndo () { @@ -49,7 +47,7 @@ CmdUndo::CmdUndo () //////////////////////////////////////////////////////////////////////////////// int CmdUndo::execute (std::string&) { - context.tdb2.revert (); + Context::getContext ().tdb2.revert (); return 0; } diff --git a/src/commands/CmdUnique.cpp b/src/commands/CmdUnique.cpp index b1399db09..0b67dbdc6 100644 --- a/src/commands/CmdUnique.cpp +++ b/src/commands/CmdUnique.cpp @@ -32,8 +32,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdUnique::CmdUnique () { @@ -63,13 +61,13 @@ int CmdUnique::execute (std::string& output) std::string attribute {}; // Just the first arg. - auto words = context.cli2.getWords (); + auto words = Context::getContext ().cli2.getWords (); if (words.size () == 0) throw std::string ("An attribute must be specified. See 'task _columns'."); attribute = words[0]; std::string canonical; - if (! context.cli2.canonicalize (canonical, "attribute", attribute)) + if (! Context::getContext ().cli2.canonicalize (canonical, "attribute", attribute)) throw std::string ("You must specify an attribute or UDA."); // Find the unique set of matching tasks. @@ -92,7 +90,7 @@ int CmdUnique::execute (std::string& output) for (auto& value : values) output += value + '\n'; - context.headers.clear (); + Context::getContext ().headers.clear (); return 0; } diff --git a/src/commands/CmdUrgency.cpp b/src/commands/CmdUrgency.cpp index aa83e16e1..0f4e8f130 100644 --- a/src/commands/CmdUrgency.cpp +++ b/src/commands/CmdUrgency.cpp @@ -34,8 +34,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdUrgency::CmdUrgency () { @@ -62,7 +60,7 @@ int CmdUrgency::execute (std::string& output) if (filtered.size () == 0) { - context.footnote ("No tasks specified."); + Context::getContext ().footnote ("No tasks specified."); return 1; } diff --git a/src/commands/CmdVersion.cpp b/src/commands/CmdVersion.cpp index 46560ee9e..77706a3ad 100644 --- a/src/commands/CmdVersion.cpp +++ b/src/commands/CmdVersion.cpp @@ -36,8 +36,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// CmdVersion::CmdVersion () { @@ -60,7 +58,7 @@ int CmdVersion::execute (std::string& output) std::stringstream out; // Create a table for the disclaimer. - int width = context.getWidth (); + int width = Context::getContext ().getWidth (); Table disclaimer; disclaimer.width (width); disclaimer.add (""); @@ -73,7 +71,7 @@ int CmdVersion::execute (std::string& output) link.set (link.addRow (), 0, "Documentation for Taskwarrior can be found using 'man task', 'man taskrc', 'man task-color', 'man task-sync' or at http://taskwarrior.org"); Color bold; - if (context.color ()) + if (Context::getContext ().color ()) bold = Color ("bold"); out << '\n' diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 79c7583e0..830c81a13 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -90,8 +90,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// void Command::factory (std::map & all) { @@ -174,7 +172,7 @@ void Command::factory (std::map & all) // Instantiate a command object for each custom report. std::vector reports; - for (auto &i : context.config) + for (auto &i : Context::getContext ().config) { if (i.first.substr (0, 7) == "report.") { @@ -194,7 +192,7 @@ void Command::factory (std::map & all) c = new CmdCustom ( report, "task " + report, - context.config.get ("report." + report + ".description")); + Context::getContext ().config.get ("report." + report + ".description")); all[c->keyword ()] = c; } @@ -334,8 +332,8 @@ bool Command::permission ( // What remains are write commands that have not yet selected 'all' or 'quit'. // Describe the task. - bool confirmation = context.config.getBoolean ("confirmation"); - unsigned int bulk = context.config.getInteger ("bulk"); + bool confirmation = Context::getContext ().config.getBoolean ("confirmation"); + unsigned int bulk = Context::getContext ().config.getInteger ("bulk"); // Quantity 1 modifications have optional confirmation, and only (y/n). if (quantity == 1) @@ -353,7 +351,7 @@ bool Command::permission ( if ((bulk == 0 || quantity < bulk) && (!_needs_confirm || !confirmation)) return true; - if (context.verbose ("blank") && !_first_iteration) + if (Context::getContext ().verbose ("blank") && !_first_iteration) std::cout << '\n'; int answer = confirm4 (question); _first_iteration = false; diff --git a/src/dependency.cpp b/src/dependency.cpp index 55c972981..af51f314e 100644 --- a/src/dependency.cpp +++ b/src/dependency.cpp @@ -36,15 +36,13 @@ #define STRING_DEPEND_BLOCKED "Task {1} is blocked by:" -extern Context context; - //////////////////////////////////////////////////////////////////////////////// std::vector dependencyGetBlocked (const Task& task) { auto uuid = task.get ("uuid"); std::vector blocked; - for (auto& it : context.tdb2.pending.get_tasks ()) + for (auto& it : Context::getContext ().tdb2.pending.get_tasks ()) if (it.getStatus () != Task::completed && it.getStatus () != Task::deleted && it.has ("depends") && @@ -61,7 +59,7 @@ std::vector dependencyGetBlocking (const Task& task) std::vector blocking; if (depends != "") - for (auto& it : context.tdb2.pending.get_tasks ()) + for (auto& it : Context::getContext ().tdb2.pending.get_tasks ()) if (it.getStatus () != Task::completed && it.getStatus () != Task::deleted && depends.find (it.get ("uuid")) != std::string::npos) @@ -95,7 +93,7 @@ bool dependencyIsCircular (const Task& task) // fact that we do not visit any task twice for (unsigned int i = 0; i < deps_current.size (); i++) { - if (context.tdb2.get (deps_current[i], current)) + if (Context::getContext ().tdb2.get (deps_current[i], current)) { auto current_uuid = current.get ("uuid"); @@ -160,7 +158,7 @@ void dependencyChainOnComplete (Task& task) auto blocked = dependencyGetBlocked (task); // Nag about broken chain. - if (context.config.getBoolean ("dependency.reminder")) + if (Context::getContext ().config.getBoolean ("dependency.reminder")) { std::cout << format (STRING_DEPEND_BLOCKED, task.identifier ()) << '\n'; @@ -172,7 +170,7 @@ void dependencyChainOnComplete (Task& task) // If there are both blocking and blocked tasks, the chain is broken. if (blocked.size ()) { - if (context.config.getBoolean ("dependency.reminder")) + if (Context::getContext ().config.getBoolean ("dependency.reminder")) { std::cout << "and is blocking:\n"; @@ -180,7 +178,7 @@ void dependencyChainOnComplete (Task& task) std::cout << " " << b.id << ' ' << b.get ("description") << '\n'; } - if (!context.config.getBoolean ("dependency.confirmation") || + if (!Context::getContext ().config.getBoolean ("dependency.confirmation") || confirm ("Would you like the dependency chain fixed?")) { // Repair the chain - everything in blocked should now depend on @@ -195,10 +193,10 @@ void dependencyChainOnComplete (Task& task) // Now update TDB2, now that the updates have all occurred. for (auto& left : blocked) - context.tdb2.modify (left); + Context::getContext ().tdb2.modify (left); for (auto& right : blocking) - context.tdb2.modify (right); + Context::getContext ().tdb2.modify (right); } } } @@ -207,7 +205,7 @@ void dependencyChainOnComplete (Task& task) //////////////////////////////////////////////////////////////////////////////// void dependencyChainOnStart (Task& task) { - if (context.config.getBoolean ("dependency.reminder")) + if (Context::getContext ().config.getBoolean ("dependency.reminder")) { auto blocking = dependencyGetBlocking (task); diff --git a/src/feedback.cpp b/src/feedback.cpp index 8aa100404..6e5837804 100644 --- a/src/feedback.cpp +++ b/src/feedback.cpp @@ -40,8 +40,6 @@ #include #include -extern Context context; - static void countTasks (const std::vector &, const std::string&, int&, int&); //////////////////////////////////////////////////////////////////////////////// @@ -242,16 +240,16 @@ std::string taskInfoDifferences ( //////////////////////////////////////////////////////////////////////////////// std::string renderAttribute (const std::string& name, const std::string& value, const std::string& format /* = "" */) { - if (context.columns.find (name) != context.columns.end ()) + if (Context::getContext ().columns.find (name) != Context::getContext ().columns.end ()) { - Column* col = context.columns[name]; + Column* col = Context::getContext ().columns[name]; if (col && col->type () == "date" && value != "") { Datetime d ((time_t)strtol (value.c_str (), NULL, 10)); if (format == "") - return d.toString (context.config.get ("dateformat")); + return d.toString (Context::getContext ().config.get ("dateformat")); return d.toString (format); } @@ -265,7 +263,7 @@ std::string renderAttribute (const std::string& name, const std::string& value, // void feedback_affected (const std::string& effect) { - if (context.verbose ("affected")) + if (Context::getContext ().verbose ("affected")) std::cout << effect << "\n"; } @@ -277,7 +275,7 @@ void feedback_affected (const std::string& effect) // {1} Quantity void feedback_affected (const std::string& effect, int quantity) { - if (context.verbose ("affected")) + if (Context::getContext ().verbose ("affected")) std::cout << format (effect, quantity) << "\n"; } @@ -291,7 +289,7 @@ void feedback_affected (const std::string& effect, int quantity) // {2} Description void feedback_affected (const std::string& effect, const Task& task) { - if (context.verbose ("affected")) + if (Context::getContext ().verbose ("affected")) { std::cout << format (effect, task.identifier (true), @@ -346,7 +344,7 @@ void feedback_reserved_tags (const std::string& tag) // Implements feedback when adding special tags to a task. void feedback_special_tags (const Task& task, const std::string& tag) { - if (context.verbose ("special")) + if (Context::getContext ().verbose ("special")) { std::string msg; std::string explanation; @@ -372,7 +370,7 @@ void feedback_special_tags (const Task& task, const std::string& tag) // Unblocked '' void feedback_unblocked (const Task& task) { - if (context.verbose ("affected")) + if (Context::getContext ().verbose ("affected")) { // Get a list of tasks that depended on this task. auto blocked = dependencyGetBlocked (task); @@ -404,18 +402,18 @@ void feedback_unblocked (const Task& task) /////////////////////////////////////////////////////////////////////////////// void feedback_backlog () { - if (context.config.get ("taskd.server") != "" && - context.verbose ("sync")) + if (Context::getContext ().config.get ("taskd.server") != "" && + Context::getContext ().verbose ("sync")) { int count = 0; - std::vector lines = context.tdb2.backlog.get_lines (); + std::vector lines = Context::getContext ().tdb2.backlog.get_lines (); for (auto& line : lines) if ((line)[0] == '{') ++count; if (count) - context.footnote (format (count > 1 ? "There are {1} local changes. Sync required." - : "There is {1} local change. Sync required.", count)); + Context::getContext ().footnote (format (count > 1 ? "There are {1} local changes. Sync required." + : "There is {1} local change. Sync required.", count)); } } @@ -434,7 +432,7 @@ std::string onProjectChange (Task& task, bool scope /* = true */) // Count pending and done tasks, for this project. int count_pending = 0; int count_done = 0; - std::vector all = context.tdb2.all_tasks (); + std::vector all = Context::getContext ().tdb2.all_tasks (); countTasks (all, project, count_pending, count_done); // count_done count_pending percentage @@ -483,7 +481,7 @@ std::string onExpiration (Task& task) { std::stringstream msg; - if (context.verbose ("affected")) + if (Context::getContext ().verbose ("affected")) msg << format ("Task {1} '{2}' expired and was deleted.", task.identifier (true), task.get ("description")); diff --git a/src/legacy.cpp b/src/legacy.cpp index 35ee0783a..5f8426028 100644 --- a/src/legacy.cpp +++ b/src/legacy.cpp @@ -32,8 +32,6 @@ #define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'." -extern Context context; - //////////////////////////////////////////////////////////////////////////////// void legacyColumnMap (std::string& name) { @@ -57,7 +55,7 @@ void legacyColumnMap (std::string& name) auto found = legacyMap.find (name); if (found != legacyMap.end ()) { - context.footnote (format (STRING_LEGACY_PRIORITY, name, found->second)); + Context::getContext ().footnote (format (STRING_LEGACY_PRIORITY, name, found->second)); name = found->second; } } @@ -85,7 +83,7 @@ void legacySortColumnMap (std::string& name) auto found = legacyMap.find (name); if (found != legacyMap.end ()) { - context.footnote (format (STRING_LEGACY_PRIORITY, name, found->second)); + Context::getContext ().footnote (format (STRING_LEGACY_PRIORITY, name, found->second)); name = found->second; } } @@ -94,7 +92,7 @@ void legacySortColumnMap (std::string& name) std::string legacyCheckForDeprecatedVariables () { std::vector deprecated; - for (auto& it : context.config) + for (auto& it : Context::getContext ().config) { // 2014-07-04: report.*.limit removed. // 2016-02-24: alias._query removed. @@ -135,12 +133,12 @@ std::string legacyCheckForDeprecatedVariables () std::string legacyCheckForDeprecatedColumns () { std::vector deprecated; - for (auto& it : context.config) + for (auto& it : Context::getContext ().config) { if (it.first.find ("report") == 0) { // Deprecated in 2.0.0 - std::string value = context.config.get (it.first); + std::string value = Context::getContext ().config.get (it.first); if (value.find ("entry_time") != std::string::npos || value.find ("start_time") != std::string::npos || value.find ("end_time") != std::string::npos) @@ -156,7 +154,7 @@ std::string legacyCheckForDeprecatedColumns () out << "Your .taskrc file contains reports with deprecated columns. Please check for entry_time, start_time or end_time in:\n"; for (const auto& dep : deprecated) - out << " " << dep << "=" << context.config.get (dep) << "\n"; + out << " " << dep << "=" << Context::getContext ().config.get (dep) << "\n"; out << "\n"; } diff --git a/src/main.cpp b/src/main.cpp index 0c5133185..f3778c22c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,13 +30,14 @@ #include #include -Context context; - //////////////////////////////////////////////////////////////////////////////// int main (int argc, const char** argv) { int status {0}; + Context globalContext; + Context::setContext (&globalContext); + // Lightweight version checking that doesn't require initialization or any I/O. if (argc == 2 && !strcmp (argv[1], "--version")) { @@ -46,9 +47,9 @@ int main (int argc, const char** argv) { try { - status = context.initialize (argc, argv); + status = Context::getContext ().initialize (argc, argv); if (status == 0) - status = context.run (); + status = Context::getContext ().run (); } catch (const std::string& error) diff --git a/src/nag.cpp b/src/nag.cpp index ab0a7b209..3e06e5746 100644 --- a/src/nag.cpp +++ b/src/nag.cpp @@ -27,8 +27,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// // Returns a Boolean indicator as to whether a nag message was generated, so // that commands can control the number of nag messages displayed (ie one is @@ -42,18 +40,18 @@ bool nag (Task& task) if (task.hasTag ("nonag")) return false; - auto msg = context.config.get ("nag"); + auto msg = Context::getContext ().config.get ("nag"); if (msg != "") { // Scan all pending, non-recurring tasks. - auto pending = context.tdb2.pending.get_tasks (); + auto pending = Context::getContext ().tdb2.pending.get_tasks (); for (auto& t : pending) { if ((t.getStatus () == Task::pending || t.getStatus () == Task::waiting) && t.urgency () > task.urgency ()) { - context.footnote (msg); + Context::getContext ().footnote (msg); return true; } } diff --git a/src/recur.cpp b/src/recur.cpp index c9aecdf96..e5edd1357 100644 --- a/src/recur.cpp +++ b/src/recur.cpp @@ -46,9 +46,6 @@ #include #include -// Global context for use by all. -extern Context context; - //////////////////////////////////////////////////////////////////////////////// // Scans all tasks, and for any recurring tasks, determines whether any new // child tasks need to be generated to fill gaps. @@ -61,10 +58,10 @@ void handleRecurrence () // Recurrence can be disabled. // Note: This is currently a workaround for TD-44, TW-1520. - if (! context.config.getBoolean ("recurrence")) + if (! Context::getContext ().config.getBoolean ("recurrence")) return; - auto tasks = context.tdb2.pending.get_tasks (); + auto tasks = Context::getContext ().tdb2.pending.get_tasks (); Datetime now; // Look at all tasks and find any recurring ones. @@ -79,8 +76,8 @@ void handleRecurrence () { // Determine the end date. t.setStatus (Task::deleted); - context.tdb2.modify (t); - context.footnote (onExpiration (t)); + Context::getContext ().tdb2.modify (t); + Context::getContext ().footnote (onExpiration (t)); continue; } @@ -98,7 +95,7 @@ void handleRecurrence () Task rec (t); // Clone the parent. rec.setStatus (Task::pending); // Change the status. - rec.id = context.tdb2.next_id (); // New ID. + rec.id = Context::getContext ().tdb2.next_id (); // New ID. rec.set ("uuid", uuid ()); // New UUID. rec.set ("parent", t.get ("uuid")); // Remember mom. rec.setAsNow ("entry"); // New entry date. @@ -123,7 +120,7 @@ void handleRecurrence () rec.remove ("mask"); // Remove the mask of the parent. // Add the new task to the DB. - context.tdb2.add (rec); + Context::getContext ().tdb2.add (rec); } ++i; @@ -133,10 +130,10 @@ void handleRecurrence () if (changed) { t.set ("mask", mask); - context.tdb2.modify (t); + Context::getContext ().tdb2.modify (t); - if (context.verbose ("recur")) - context.footnote (format ("Creating recurring task instance '{1}'", t.get ("description"))); + if (Context::getContext ().verbose ("recur")) + Context::getContext ().footnote (format ("Creating recurring task instance '{1}'", t.get ("description"))); } } } @@ -164,7 +161,7 @@ bool generateDueDates (Task& parent, std::vector & allDue) specificEnd = true; } - auto recurrence_limit = context.config.getInteger ("recurrence.limit"); + auto recurrence_limit = Context::getContext ().config.getInteger ("recurrence.limit"); int recurrence_counter = 0; Datetime now; for (Datetime i = due; ; i = getNextRecurrence (i, recur)) @@ -375,7 +372,7 @@ void updateRecurrenceMask (Task& task) Task parent; if (uuid != "" && - context.tdb2.get (uuid, parent)) + Context::getContext ().tdb2.get (uuid, parent)) { unsigned int index = strtol (task.get ("imask").c_str (), NULL, 10); auto mask = parent.get ("mask"); @@ -401,7 +398,7 @@ void updateRecurrenceMask (Task& task) } parent.set ("mask", mask); - context.tdb2.modify (parent); + Context::getContext ().tdb2.modify (parent); } } diff --git a/src/recur2.cpp b/src/recur2.cpp index 8a027c654..491eaa945 100644 --- a/src/recur2.cpp +++ b/src/recur2.cpp @@ -32,8 +32,6 @@ #include #include -extern Context context; - //////////////////////////////////////////////////////////////////////////////// // Checklist: // - last: Most recently generated instance integer. The first instance @@ -73,7 +71,7 @@ static Datetime generateNextDueDate ( Duration dur (period); auto normalized = dur.formatISO (); - context.debug (" period " + period + " --> " + normalized); + Context::getContext ().debug (" period " + period + " --> " + normalized); if (! dur._year && dur._month && @@ -271,13 +269,13 @@ static std::vector generateAllDueDates (const Task& templateTask) // Determine due date, recur period and until date. Datetime due (templateTask.get_date ("due")); - context.debug (" due " + due.toISOLocalExtended ()); + Context::getContext ().debug (" due " + due.toISOLocalExtended ()); auto recur = templateTask.get ("recur"); - context.debug (" recur " + recur); + Context::getContext ().debug (" recur " + recur); auto lastN = std::max (1, templateTask.get_int ("last")); - context.debug (format (" last {1}", lastN)); + Context::getContext ().debug (format (" last {1}", lastN)); bool end_in_sight = false; Datetime until; @@ -285,11 +283,11 @@ static std::vector generateAllDueDates (const Task& templateTask) { until = Datetime (templateTask.get ("until")); end_in_sight = true; - context.debug (" until " + until.toISOLocalExtended ()); + Context::getContext ().debug (" until " + until.toISOLocalExtended ()); } - auto recurrence_limit = context.config.getInteger ("recurrence.limit"); - context.debug (format (" recurrence.limit {1}", recurrence_limit)); + auto recurrence_limit = Context::getContext ().config.getInteger ("recurrence.limit"); + Context::getContext ().debug (format (" recurrence.limit {1}", recurrence_limit)); int recurrence_counter = 0; Datetime now; @@ -321,8 +319,8 @@ static std::vector generateAllDueDates (const Task& templateTask) //////////////////////////////////////////////////////////////////////////////// static void synthesizeTasks (const Task& templateTask) { - context.debug ("synthesizeTasks start"); - context.debug (" template " + templateTask.get ("uuid")); + Context::getContext ().debug ("synthesizeTasks start"); + Context::getContext ().debug (" template " + templateTask.get ("uuid")); // TODO 'due' = starting point // TODO 'recur' = frequency @@ -330,11 +328,11 @@ static void synthesizeTasks (const Task& templateTask) auto all = generateAllDueDates (templateTask); for (auto& date : all) - context.debug (" date " + date.toISOLocalExtended ()); + Context::getContext ().debug (" date " + date.toISOLocalExtended ()); // TODO Create task instances for each period between N and now. - context.debug ("synthesizeTasks end"); + Context::getContext ().debug ("synthesizeTasks end"); } //////////////////////////////////////////////////////////////////////////////// @@ -342,8 +340,8 @@ static void synthesizeTasks (const Task& templateTask) void handleRecurrence2 () { // Note: Disabling recurrence is currently a workaround for TD-44, TW-1520. - if (context.config.getBoolean ("recurrence")) - for (auto& t : context.tdb2.pending.get_tasks ()) + if (Context::getContext ().config.getBoolean ("recurrence")) + for (auto& t : Context::getContext ().tdb2.pending.get_tasks ()) if (t.getStatus () == Task::recurring) synthesizeTasks (t); } @@ -353,7 +351,7 @@ void handleRecurrence2 () void handleUntil () { Datetime now; - auto tasks = context.tdb2.pending.get_tasks (); + auto tasks = Context::getContext ().tdb2.pending.get_tasks (); for (auto& t : tasks) { // TODO What about expiring template tasks? @@ -363,10 +361,10 @@ void handleUntil () auto until = Datetime (t.get_date ("until")); if (until < now) { - context.debug (format ("handleUntil: recurrence expired until {1} < now {2}", until.toISOLocalExtended (), now.toISOLocalExtended ())); + Context::getContext ().debug (format ("handleUntil: recurrence expired until {1} < now {2}", until.toISOLocalExtended (), now.toISOLocalExtended ())); t.setStatus (Task::deleted); - context.tdb2.modify(t); - context.footnote (onExpiration (t)); + Context::getContext ().tdb2.modify(t); + Context::getContext ().footnote (onExpiration (t)); } } } diff --git a/src/rules.cpp b/src/rules.cpp index ae4df2db1..8517f5a5e 100644 --- a/src/rules.cpp +++ b/src/rules.cpp @@ -31,8 +31,6 @@ #include #include -extern Context context; - static std::map gsColor; static std::vector gsPrecedence; static Datetime now; @@ -41,7 +39,7 @@ static Datetime now; void initializeColorRules () { // If color is not enable/supported, short circuit. - if (! context.color ()) + if (! Context::getContext ().color ()) return; try @@ -52,7 +50,7 @@ void initializeColorRules () // Load all the configuration values, filter to only the ones that begin with // "color.", then store name/value in gsColor, and name in rules. std::vector rules; - for (const auto& v : context.config) + for (const auto& v : Context::getContext ().config) { if (! v.first.compare (0, 6, "color.", 6)) { @@ -66,7 +64,7 @@ void initializeColorRules () // Load the rule.precedence.color list, split it, then autocomplete against // the 'rules' vector loaded above. std::vector results; - auto precedence = split (context.config.get ("rule.precedence.color"), ','); + auto precedence = split (Context::getContext ().config.get ("rule.precedence.color"), ','); for (const auto& p : precedence) { @@ -81,7 +79,7 @@ void initializeColorRules () catch (const std::string& e) { - context.error (e); + Context::getContext ().error (e); } } @@ -149,7 +147,7 @@ static void colorizeTag (Task& task, const std::string& rule, const Color& base, static void colorizeProject (Task& task, const std::string& rule, const Color& base, Color& c, bool merge) { // Observe the case sensitivity setting. - bool sensitive = context.config.getBoolean ("search.case.sensitive"); + bool sensitive = Context::getContext ().config.getBoolean ("search.case.sensitive"); auto project = task.get ("project"); auto rule_trunc = rule.substr (14); @@ -178,7 +176,7 @@ static void colorizeTagNone (Task& task, const Color& base, Color& c, bool merge static void colorizeKeyword (Task& task, const std::string& rule, const Color& base, Color& c, bool merge) { // Observe the case sensitivity setting. - auto sensitive = context.config.getBoolean ("search.case.sensitive"); + auto sensitive = Context::getContext ().config.getBoolean ("search.case.sensitive"); // The easiest thing to check is the description, because it is just one // attribute. @@ -286,14 +284,14 @@ static void colorizeDeleted (Task& task, const Color& base, Color& c, bool merge void autoColorize (Task& task, Color& c) { // The special tag 'nocolor' overrides all auto and specific colorization. - if (! context.color () || + if (! Context::getContext ().color () || task.hasTag ("nocolor")) { c = Color (); return; } - auto merge = context.config.getBoolean ("rule.color.merge"); + auto merge = Context::getContext ().config.getBoolean ("rule.color.merge"); // Note: c already contains colors specifically assigned via command. // Note: These rules form a hierarchy - the last rule is King, hence the diff --git a/src/sort.cpp b/src/sort.cpp index 8dae4a339..ef1fb1950 100644 --- a/src/sort.cpp +++ b/src/sort.cpp @@ -35,8 +35,6 @@ #include #include -extern Context context; - static std::vector * global_data = NULL; static std::vector global_keys; static bool sort_compare (int, int); @@ -58,7 +56,7 @@ void sort_tasks ( if (order.size ()) std::stable_sort (order.begin (), order.end (), sort_compare); - context.time_sort_us += timer.total_us (); + Context::getContext ().time_sort_us += timer.total_us (); } //////////////////////////////////////////////////////////////////////////////// @@ -79,7 +77,7 @@ static bool sort_compare (int left, int right) for (auto& k : global_keys) { - context.decomposeSortField (k, field, ascending, breakIndicator); + Context::getContext ().decomposeSortField (k, field, ascending, breakIndicator); // Urgency. if (field == "urgency") @@ -170,8 +168,8 @@ static bool sort_compare (int left, int right) return !ascending; // Sort on the first dependency. - left_number = context.tdb2.id (left_string.substr (0, 36)); - right_number = context.tdb2.id (right_string.substr (0, 36)); + left_number = Context::getContext ().tdb2.id (left_string.substr (0, 36)); + right_number = Context::getContext ().tdb2.id (right_string.substr (0, 36)); if (left_number == right_number) continue; @@ -196,7 +194,7 @@ static bool sort_compare (int left, int right) } // UDAs. - else if ((column = context.columns[field]) != NULL) + else if ((column = Context::getContext ().columns[field]) != NULL) { std::string type = column->type (); if (type == "numeric") diff --git a/src/util.cpp b/src/util.cpp index 1f9222cb8..0f4c9a09a 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -63,8 +63,6 @@ #define STRING_UTIL_CONFIRM_ALL_U "All" #define STRING_UTIL_CONFIRM_QUIT "quit" -extern Context context; - static const char* newline = "\n"; static const char* noline = ""; @@ -107,7 +105,7 @@ int confirm4 (const std::string& question) std::string answer {""}; std::getline (std::cin, answer); - context.debug ("STDIN '" + answer + '\''); + Context::getContext ().debug ("STDIN '" + answer + '\''); answer = std::cin.eof () ? STRING_UTIL_CONFIRM_QUIT : Lexer::lowerCase (Lexer::trim (answer)); autoComplete (answer, options, matches, 1); // Hard-coded 1. } @@ -278,32 +276,32 @@ bool nontrivial (const std::string& input) //////////////////////////////////////////////////////////////////////////////// const char* optionalBlankLine () { - return context.verbose ("blank") ? newline : noline; + return Context::getContext ().verbose ("blank") ? newline : noline; } //////////////////////////////////////////////////////////////////////////////// void setHeaderUnderline (Table& table) { // If an alternating row color is specified, notify the table. - if (context.color ()) + if (Context::getContext ().color ()) { - Color alternate (context.config.get ("color.alternate")); + Color alternate (Context::getContext ().config.get ("color.alternate")); table.colorOdd (alternate); table.intraColorOdd (alternate); - if (context.config.getBoolean ("fontunderline")) + if (Context::getContext ().config.getBoolean ("fontunderline")) { - table.colorHeader (Color ("underline " + context.config.get ("color.label"))); + table.colorHeader (Color ("underline " + Context::getContext ().config.get ("color.label"))); } else { - table.colorHeader (Color (context.config.get ("color.label"))); + table.colorHeader (Color (Context::getContext ().config.get ("color.label"))); table.underlineHeaders (); } } else { - if (context.config.getBoolean ("fontunderline")) + if (Context::getContext ().config.getBoolean ("fontunderline")) table.colorHeader (Color ("underline")); else table.underlineHeaders (); diff --git a/test/col.t.cpp b/test/col.t.cpp index e750239e8..d65ad891c 100644 --- a/test/col.t.cpp +++ b/test/col.t.cpp @@ -30,8 +30,6 @@ #include #include -Context context; - //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { diff --git a/test/dom.t.cpp b/test/dom.t.cpp index 5296282dc..398dd9d01 100644 --- a/test/dom.t.cpp +++ b/test/dom.t.cpp @@ -25,13 +25,9 @@ //////////////////////////////////////////////////////////////////////////////// #include -#include // TODO Remove. #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// bool providerString (const std::string& path, Variant& var) @@ -72,7 +68,7 @@ int main (int, char**) dom.addSource ("name.next", &providerString); dom.addSource ("name.size", &providerString); dom.addSource ("foo", &providerString); - std::cout << dom.dump () << '\n'; + t.diag (dom.dump ()); t.is (dom.count (), 4, "DOM now contains 4 nodes"); t.ok (dom.valid ("name"), "DOM 'name' valid"); diff --git a/test/eval.t.cpp b/test/eval.t.cpp index 53f485224..907ce8fb5 100644 --- a/test/eval.t.cpp +++ b/test/eval.t.cpp @@ -27,9 +27,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// // A few hard-coded symbols. diff --git a/test/t.t.cpp b/test/t.t.cpp index d6628ed8f..7aa3c3d1e 100644 --- a/test/t.t.cpp +++ b/test/t.t.cpp @@ -29,8 +29,6 @@ #include #include -Context context; - //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { diff --git a/test/util.t.cpp b/test/util.t.cpp index 3acd11322..3ee45ae00 100644 --- a/test/util.t.cpp +++ b/test/util.t.cpp @@ -31,8 +31,6 @@ #include #include -Context context; - //////////////////////////////////////////////////////////////////////////////// int main (int, char**) { diff --git a/test/variant_add.t.cpp b/test/variant_add.t.cpp index b0b1bf6f7..048f9c44d 100644 --- a/test/variant_add.t.cpp +++ b/test/variant_add.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; #define EPSILON 0.001 diff --git a/test/variant_and.t.cpp b/test/variant_and.t.cpp index 2055bb870..cbf1eb3a7 100644 --- a/test/variant_and.t.cpp +++ b/test/variant_and.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_cast.t.cpp b/test/variant_cast.t.cpp index 864e5783f..6ae0e4062 100644 --- a/test/variant_cast.t.cpp +++ b/test/variant_cast.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; #define EPSILON 0.001 diff --git a/test/variant_divide.t.cpp b/test/variant_divide.t.cpp index 1699b942a..7b2cd4515 100644 --- a/test/variant_divide.t.cpp +++ b/test/variant_divide.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; #define EPSILON 0.0001 diff --git a/test/variant_equal.t.cpp b/test/variant_equal.t.cpp index 21c9c2aa0..e8350f8de 100644 --- a/test/variant_equal.t.cpp +++ b/test/variant_equal.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_exp.t.cpp b/test/variant_exp.t.cpp index 1514a0ebc..a1ef6bf5d 100644 --- a/test/variant_exp.t.cpp +++ b/test/variant_exp.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_gt.t.cpp b/test/variant_gt.t.cpp index 9e641da61..35c591065 100644 --- a/test/variant_gt.t.cpp +++ b/test/variant_gt.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_gte.t.cpp b/test/variant_gte.t.cpp index bbd718535..42937570c 100644 --- a/test/variant_gte.t.cpp +++ b/test/variant_gte.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_inequal.t.cpp b/test/variant_inequal.t.cpp index ef6c84790..adced2a2e 100644 --- a/test/variant_inequal.t.cpp +++ b/test/variant_inequal.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_lt.t.cpp b/test/variant_lt.t.cpp index 0804d50b2..e90b081b9 100644 --- a/test/variant_lt.t.cpp +++ b/test/variant_lt.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_lte.t.cpp b/test/variant_lte.t.cpp index 9c02aabe3..e04f1cad0 100644 --- a/test/variant_lte.t.cpp +++ b/test/variant_lte.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_match.t.cpp b/test/variant_match.t.cpp index 54e64f4d0..2a2440122 100644 --- a/test/variant_match.t.cpp +++ b/test/variant_match.t.cpp @@ -28,10 +28,8 @@ #include #include #include -#include #include -Context context; Task task; //////////////////////////////////////////////////////////////////////////////// diff --git a/test/variant_math.t.cpp b/test/variant_math.t.cpp index 5c08da02a..6430e6f7e 100644 --- a/test/variant_math.t.cpp +++ b/test/variant_math.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; #define EPSILON 0.001 diff --git a/test/variant_modulo.t.cpp b/test/variant_modulo.t.cpp index 5a807d2b7..53d2037cb 100644 --- a/test/variant_modulo.t.cpp +++ b/test/variant_modulo.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; #define EPSILON 0.0001 diff --git a/test/variant_multiply.t.cpp b/test/variant_multiply.t.cpp index 1c006c1f8..506432418 100644 --- a/test/variant_multiply.t.cpp +++ b/test/variant_multiply.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; #define EPSILON 0.0001 diff --git a/test/variant_nomatch.t.cpp b/test/variant_nomatch.t.cpp index 2f22fa3d8..74861f055 100644 --- a/test/variant_nomatch.t.cpp +++ b/test/variant_nomatch.t.cpp @@ -28,10 +28,8 @@ #include #include #include -#include #include -Context context; Task task; //////////////////////////////////////////////////////////////////////////////// diff --git a/test/variant_not.t.cpp b/test/variant_not.t.cpp index bf378fe11..c0908579b 100644 --- a/test/variant_not.t.cpp +++ b/test/variant_not.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_or.t.cpp b/test/variant_or.t.cpp index d96d128aa..7f1a5e3a4 100644 --- a/test/variant_or.t.cpp +++ b/test/variant_or.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_partial.t.cpp b/test/variant_partial.t.cpp index ee4086494..09e7cee0d 100644 --- a/test/variant_partial.t.cpp +++ b/test/variant_partial.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**) diff --git a/test/variant_subtract.t.cpp b/test/variant_subtract.t.cpp index 83e1c2b07..382e296c0 100644 --- a/test/variant_subtract.t.cpp +++ b/test/variant_subtract.t.cpp @@ -28,10 +28,6 @@ #include #include #include -#include - -Context context; - #define EPSILON 0.001 diff --git a/test/variant_xor.t.cpp b/test/variant_xor.t.cpp index 154e287ca..15365f4a6 100644 --- a/test/variant_xor.t.cpp +++ b/test/variant_xor.t.cpp @@ -28,9 +28,6 @@ #include #include #include -#include - -Context context; //////////////////////////////////////////////////////////////////////////////// int main (int, char**)