From 96fe3f42ba795bb46e1a2b735acf43933dfc330a Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 5 Feb 2012 20:56:46 -0500 Subject: [PATCH] Minor Refactoring - Added support for more type-specific checks of attribute values. - Added support for more type-specific attribute rendering. - Improved generalized methods for checking columns in a report. - Added unit tests. - Minor code cleanup. - Added secret hidden feature for internal testing. --- src/Directory.cpp | 1 - src/Duration.cpp | 8 +- src/E9.cpp | 1 - src/Hooks.cpp | 1 - src/Path.cpp | 1 - src/RX.cpp | 1 - src/Taskmod.cpp | 1 - src/Timer.cpp | 1 - src/Transport.cpp | 1 - src/TransportCurl.cpp | 1 - src/TransportRSYNC.cpp | 1 - src/TransportSSH.cpp | 1 - src/Uri.cpp | 1 - src/ViewText.cpp | 1 - src/columns/CMakeLists.txt | 1 + src/columns/ColBg.cpp | 1 - src/columns/ColDate.cpp | 1 - src/columns/ColDepends.cpp | 1 - src/columns/ColDescription.cpp | 1 - src/columns/ColDue.cpp | 1 - src/columns/ColEnd.cpp | 1 - src/columns/ColEntry.cpp | 1 - src/columns/ColFg.cpp | 1 - src/columns/ColID.cpp | 1 - src/columns/ColIMask.cpp | 1 - src/columns/ColMask.cpp | 1 - src/columns/ColParent.cpp | 1 - src/columns/ColPriority.cpp | 1 - src/columns/ColProject.cpp | 1 - src/columns/ColRecur.cpp | 1 - src/columns/ColStart.cpp | 1 - src/columns/ColStatus.cpp | 1 - src/columns/ColString.cpp | 1 - src/columns/ColTags.cpp | 1 - src/columns/ColUDA.cpp | 155 ++++++++++++++++++++++++++++++++ src/columns/ColUDA.h | 52 +++++++++++ src/columns/ColUUID.cpp | 1 - src/columns/ColUntil.cpp | 1 - src/columns/ColUrgency.cpp | 1 - src/columns/ColWait.cpp | 1 - src/columns/Column.cpp | 55 ++++++++++++ src/columns/Column.h | 2 + src/commands/CmdBurndown.cpp | 1 - src/commands/CmdCalendar.cpp | 1 - src/commands/CmdColor.cpp | 1 - src/commands/CmdColumns.cpp | 1 - src/commands/CmdCommands.cpp | 1 - src/commands/CmdConfig.cpp | 1 - src/commands/CmdCount.cpp | 1 - src/commands/CmdCustom.cpp | 1 - src/commands/CmdDiagnostics.cpp | 1 - src/commands/CmdExec.cpp | 1 - src/commands/CmdExport.cpp | 1 - src/commands/CmdHelp.cpp | 1 - src/commands/CmdHistory.cpp | 1 - src/commands/CmdImport.cpp | 1 - src/commands/CmdInfo.cpp | 18 +++- src/commands/CmdInstall.cpp | 1 - src/commands/CmdLog.cpp | 1 - src/commands/CmdLogo.cpp | 1 - src/commands/CmdMerge.cpp | 1 - src/commands/CmdProjects.cpp | 1 - src/commands/CmdPull.cpp | 1 - src/commands/CmdPush.cpp | 1 - src/commands/CmdReports.cpp | 1 - src/commands/CmdShell.cpp | 1 - src/commands/CmdShow.cpp | 2 +- src/commands/CmdSummary.cpp | 1 - src/commands/CmdTags.cpp | 1 - src/commands/CmdTimesheet.cpp | 1 - src/commands/CmdUndo.cpp | 1 - src/commands/CmdUrgency.cpp | 1 - src/commands/CmdVersion.cpp | 1 - src/commands/Command.cpp | 45 +++++++++- src/en-US.h | 4 +- src/interactive.cpp | 1 - src/legacy.cpp | 1 - src/recur.cpp | 1 - src/rules.cpp | 1 - src/sort.cpp | 1 - src/utf8.cpp | 1 - test/duration.t.cpp | 6 +- test/nibbler.t.cpp | 13 ++- 83 files changed, 351 insertions(+), 81 deletions(-) create mode 100644 src/columns/ColUDA.cpp create mode 100644 src/columns/ColUDA.h diff --git a/src/Directory.cpp b/src/Directory.cpp index bdfcb653a..378769879 100644 --- a/src/Directory.cpp +++ b/src/Directory.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/Duration.cpp b/src/Duration.cpp index 04451aa71..6c70a9a80 100644 --- a/src/Duration.cpp +++ b/src/Duration.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include @@ -401,6 +400,13 @@ void Duration::parse (const std::string& input) else _negative = false; + // If no units are provided, assume seconds. + if (n.depleted ()) + { + _secs = (long) value; + return; + } + std::string units; n.getUntilEOS (units); diff --git a/src/E9.cpp b/src/E9.cpp index 8f0f014a8..f86c818c6 100644 --- a/src/E9.cpp +++ b/src/E9.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/Hooks.cpp b/src/Hooks.cpp index 3e929a335..9d6ae0564 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/Path.cpp b/src/Path.cpp index 70cf3f80c..f9bd216bd 100644 --- a/src/Path.cpp +++ b/src/Path.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/RX.cpp b/src/RX.cpp index c7c231e4a..8e5317c15 100644 --- a/src/RX.cpp +++ b/src/RX.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/Taskmod.cpp b/src/Taskmod.cpp index 57c419561..8ae89809e 100644 --- a/src/Taskmod.cpp +++ b/src/Taskmod.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/Timer.cpp b/src/Timer.cpp index 86d52d402..eb03ebb9f 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/Transport.cpp b/src/Transport.cpp index aa76fb9b6..8b3afc655 100644 --- a/src/Transport.cpp +++ b/src/Transport.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/TransportCurl.cpp b/src/TransportCurl.cpp index be6d05e87..1c1a52459 100644 --- a/src/TransportCurl.cpp +++ b/src/TransportCurl.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/TransportRSYNC.cpp b/src/TransportRSYNC.cpp index 2dc8cc3e1..f3d2e276e 100644 --- a/src/TransportRSYNC.cpp +++ b/src/TransportRSYNC.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/TransportSSH.cpp b/src/TransportSSH.cpp index ce5197ed7..889c7a671 100644 --- a/src/TransportSSH.cpp +++ b/src/TransportSSH.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/Uri.cpp b/src/Uri.cpp index 32f35da7f..334948210 100644 --- a/src/Uri.cpp +++ b/src/Uri.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/ViewText.cpp b/src/ViewText.cpp index 86378bf38..88fcf16d6 100644 --- a/src/ViewText.cpp +++ b/src/ViewText.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/CMakeLists.txt b/src/columns/CMakeLists.txt index 698d24d73..db1c19907 100644 --- a/src/columns/CMakeLists.txt +++ b/src/columns/CMakeLists.txt @@ -27,6 +27,7 @@ set (columns_SRCS Column.cpp Column.h ColTags.cpp ColTags.h ColUntil.cpp ColUntil.h ColUrgency.cpp ColUrgency.h + ColUDA.cpp ColUDA.h ColUUID.cpp ColUUID.h ColWait.cpp ColWait.h) diff --git a/src/columns/ColBg.cpp b/src/columns/ColBg.cpp index 8a5f86943..9283c5b29 100644 --- a/src/columns/ColBg.cpp +++ b/src/columns/ColBg.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColDate.cpp b/src/columns/ColDate.cpp index cef872f4d..8588a7276 100644 --- a/src/columns/ColDate.cpp +++ b/src/columns/ColDate.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColDepends.cpp b/src/columns/ColDepends.cpp index 7c56d6656..e83c93c76 100644 --- a/src/columns/ColDepends.cpp +++ b/src/columns/ColDepends.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColDescription.cpp b/src/columns/ColDescription.cpp index e59e5567f..55ebdae5a 100644 --- a/src/columns/ColDescription.cpp +++ b/src/columns/ColDescription.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColDue.cpp b/src/columns/ColDue.cpp index 789cdedf5..0bea97d89 100644 --- a/src/columns/ColDue.cpp +++ b/src/columns/ColDue.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColEnd.cpp b/src/columns/ColEnd.cpp index 2cd40e1ce..6dbf856a6 100644 --- a/src/columns/ColEnd.cpp +++ b/src/columns/ColEnd.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColEntry.cpp b/src/columns/ColEntry.cpp index 6195ef5fe..b1c3b1fb8 100644 --- a/src/columns/ColEntry.cpp +++ b/src/columns/ColEntry.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColFg.cpp b/src/columns/ColFg.cpp index a3b1d9525..ab584bf3d 100644 --- a/src/columns/ColFg.cpp +++ b/src/columns/ColFg.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColID.cpp b/src/columns/ColID.cpp index ccd7fe784..827240c3f 100644 --- a/src/columns/ColID.cpp +++ b/src/columns/ColID.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColIMask.cpp b/src/columns/ColIMask.cpp index 1ffbdd343..6d8698e32 100644 --- a/src/columns/ColIMask.cpp +++ b/src/columns/ColIMask.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColMask.cpp b/src/columns/ColMask.cpp index 997f84fcd..ced4321c3 100644 --- a/src/columns/ColMask.cpp +++ b/src/columns/ColMask.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColParent.cpp b/src/columns/ColParent.cpp index baf76fccc..942e93ce0 100644 --- a/src/columns/ColParent.cpp +++ b/src/columns/ColParent.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColPriority.cpp b/src/columns/ColPriority.cpp index 02e9ab337..aa12240e6 100644 --- a/src/columns/ColPriority.cpp +++ b/src/columns/ColPriority.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColProject.cpp b/src/columns/ColProject.cpp index a0c451512..62dc4f766 100644 --- a/src/columns/ColProject.cpp +++ b/src/columns/ColProject.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColRecur.cpp b/src/columns/ColRecur.cpp index 22ecf4b37..e78108f99 100644 --- a/src/columns/ColRecur.cpp +++ b/src/columns/ColRecur.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColStart.cpp b/src/columns/ColStart.cpp index 6ba6677c3..9dfc0c8c9 100644 --- a/src/columns/ColStart.cpp +++ b/src/columns/ColStart.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColStatus.cpp b/src/columns/ColStatus.cpp index cbbf1716f..7817c31c6 100644 --- a/src/columns/ColStatus.cpp +++ b/src/columns/ColStatus.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColString.cpp b/src/columns/ColString.cpp index 5bad12052..9c90479ed 100644 --- a/src/columns/ColString.cpp +++ b/src/columns/ColString.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColTags.cpp b/src/columns/ColTags.cpp index a31be0417..f6012b4e6 100644 --- a/src/columns/ColTags.cpp +++ b/src/columns/ColTags.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColUDA.cpp b/src/columns/ColUDA.cpp new file mode 100644 index 000000000..f191a2d63 --- /dev/null +++ b/src/columns/ColUDA.cpp @@ -0,0 +1,155 @@ +//////////////////////////////////////////////////////////////////////////////// +// taskwarrior - a command line task list manager. +// +// Copyright 2006-2012, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#define L10N // Localization complete. + +#include +#include +#include +#include +#include +#include + +extern Context context; + +//////////////////////////////////////////////////////////////////////////////// +ColumnUDA::ColumnUDA () +{ + _name = ""; + _type = "string"; + _style = "default"; + _label = ""; + + _hyphenate = (_type == "string") ? true : false; + + _styles.push_back (_style); + + // TODO _examples.push_back ("?"); +} + +//////////////////////////////////////////////////////////////////////////////// +ColumnUDA::~ColumnUDA () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// Set the minimum and maximum widths for the value. +// +void ColumnUDA::measure (Task& task, int& minimum, int& maximum) +{ + if (_style == "default") + { + std::string value = task.get (_name); + + if (_type == "date") + { + // Determine the output date format, which uses a hierarchy of definitions. + // rc.report..dateformat + // rc.dateformat.report + // rc.dateformat. + Date date ((time_t) strtol (value.c_str (), NULL, 10)); + std::string format = context.config.get ("report." + _report + ".dateformat"); + if (format == "") + format = context.config.get ("dateformat.report"); + if (format == "") + format = context.config.get ("dateformat"); + + minimum = maximum = date.toString (format).length (); + } + else if (_type == "duration") + { + minimum = maximum = Duration (value).formatCompact ().length (); + } + else if (_type == "string") + { + std::string stripped = Color::strip (value); + maximum = longestLine (stripped); + minimum = longestWord (stripped); + } + else if (_type == "numeric") + { + minimum = maximum = value.length (); + } + } + else + throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); +} + +//////////////////////////////////////////////////////////////////////////////// +void ColumnUDA::render ( + std::vector & lines, + Task& task, + int width, + Color& color) +{ + if (_style == "default") + { + std::string value = task.get (_name); + + if (_type == "date") + { + // Determine the output date format, which uses a hierarchy of definitions. + // rc.report..dateformat + // rc.dateformat.report + // rc.dateformat. + std::string format = context.config.get ("report." + _report + ".dateformat"); + if (format == "") + format = context.config.get ("dateformat.report"); + if (format == "") + format = context.config.get ("dateformat"); + + lines.push_back ( + color.colorize ( + leftJustify ( + Date ((time_t) strtol (value.c_str (), NULL, 10)) + .toString (format), width))); + } + else if (_type == "duration") + { + lines.push_back ( + color.colorize ( + rightJustify ( + Duration (value).formatCompact (), + width))); + } + else if (_type == "string") + { + std::vector raw; + wrapText (raw, value, width, _hyphenate); + + std::vector ::iterator i; + for (i = raw.begin (); i != raw.end (); ++i) + lines.push_back (color.colorize (leftJustify (*i, width))); + } + else if (_type == "numeric") + { + lines.push_back (color.colorize (rightJustify (value, width))); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColUDA.h b/src/columns/ColUDA.h new file mode 100644 index 000000000..7a8e13e12 --- /dev/null +++ b/src/columns/ColUDA.h @@ -0,0 +1,52 @@ +//////////////////////////////////////////////////////////////////////////////// +// taskwarrior - a command line task list manager. +// +// Copyright 2006-2012, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_COLUDA +#define INCLUDED_COLUDA +#define L10N // Localization complete. + +#include +#include +#include +#include +#include + +class ColumnUDA : public Column +{ +public: + ColumnUDA (); + ~ColumnUDA (); + + void measure (Task&, int&, int&); + void render (std::vector &, Task&, int, Color&); + +private: + bool _hyphenate; +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColUUID.cpp b/src/columns/ColUUID.cpp index 49202bb85..44f706c40 100644 --- a/src/columns/ColUUID.cpp +++ b/src/columns/ColUUID.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColUntil.cpp b/src/columns/ColUntil.cpp index aa1528264..5e7d648fb 100644 --- a/src/columns/ColUntil.cpp +++ b/src/columns/ColUntil.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColUrgency.cpp b/src/columns/ColUrgency.cpp index 3ce4068d0..755531965 100644 --- a/src/columns/ColUrgency.cpp +++ b/src/columns/ColUrgency.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/ColWait.cpp b/src/columns/ColWait.cpp index 10522a5c7..76461fde9 100644 --- a/src/columns/ColWait.cpp +++ b/src/columns/ColWait.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/columns/Column.cpp b/src/columns/Column.cpp index 70544ea68..e1f6712d1 100644 --- a/src/columns/Column.cpp +++ b/src/columns/Column.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -103,6 +104,11 @@ Column* Column::factory (const std::string& name, const std::string& report) // Special non-task column. else if (column_name == "string") c = new ColumnString (); + + // UDA. + else if (context.config.get ("uda." + column_name + ".type") != "") + c = Column::uda (column_name); + else throw format (STRING_COLUMN_BAD_NAME, column_name); @@ -138,6 +144,55 @@ void Column::factory (std::map & all) c = new ColumnUrgency (); all[c->_name] = c; c = new ColumnUUID (); all[c->_name] = c; c = new ColumnWait (); all[c->_name] = c; + + Column::uda (all); +} + +//////////////////////////////////////////////////////////////////////////////// +void Column::uda (std::map & all) +{ + // For each UDA, instantiate and initialize ColumnUDA(). + std::map udas; + std::vector names; + context.config.all (names); + + std::vector ::iterator i; + for (i = names.begin (); i != names.end (); ++i) + { + if (i->substr (0, 4) == "uda.") + { + std::string::size_type period = 4; + if ((period = i->find ('.', period)) != std::string::npos) + udas[i->substr (4, period - 4)] = 0; + } + } + + std::map ::iterator uda; + for (uda = udas.begin (); uda != udas.end (); ++uda) + { + Column* c = Column::uda (uda->first); + all[c->_name] = c; + } +} + +//////////////////////////////////////////////////////////////////////////////// +Column* Column::uda (const std::string& name) +{ + Column* c = new ColumnUDA (); + c->_name = name; + + std::string key = "uda." + name + ".type"; + c->_type = context.config.get (key); + if (c->_type != "string" && + c->_type != "date" && + c->_type != "duration" && + c->_type != "numeric") + throw std::string (STRING_UDA_TYPE); + + key = "uda." + name + ".label"; + if (context.config.get (key) != "") + c->_label = context.config.get (key); + return c; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/Column.h b/src/columns/Column.h index 563504593..38ee856bb 100644 --- a/src/columns/Column.h +++ b/src/columns/Column.h @@ -39,6 +39,8 @@ class Column public: static Column* factory (const std::string&, const std::string&); static void factory (std::map &); + static void uda (std::map &); + static Column* uda (const std::string&); Column (); Column (const Column&); diff --git a/src/commands/CmdBurndown.cpp b/src/commands/CmdBurndown.cpp index 49d920b7f..fa8a76c48 100644 --- a/src/commands/CmdBurndown.cpp +++ b/src/commands/CmdBurndown.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdCalendar.cpp b/src/commands/CmdCalendar.cpp index b0cd4dde9..bb417fb87 100644 --- a/src/commands/CmdCalendar.cpp +++ b/src/commands/CmdCalendar.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdColor.cpp b/src/commands/CmdColor.cpp index 83eb26f05..fa43dd447 100644 --- a/src/commands/CmdColor.cpp +++ b/src/commands/CmdColor.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdColumns.cpp b/src/commands/CmdColumns.cpp index 18ef55ae2..c6d203281 100644 --- a/src/commands/CmdColumns.cpp +++ b/src/commands/CmdColumns.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdCommands.cpp b/src/commands/CmdCommands.cpp index 6da9fb54d..716029835 100644 --- a/src/commands/CmdCommands.cpp +++ b/src/commands/CmdCommands.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdConfig.cpp b/src/commands/CmdConfig.cpp index 9b8448952..263117c7a 100644 --- a/src/commands/CmdConfig.cpp +++ b/src/commands/CmdConfig.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdCount.cpp b/src/commands/CmdCount.cpp index 51d2993a6..6b04d4b3e 100644 --- a/src/commands/CmdCount.cpp +++ b/src/commands/CmdCount.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdCustom.cpp b/src/commands/CmdCustom.cpp index 159c3b5e4..0b99e9ec1 100644 --- a/src/commands/CmdCustom.cpp +++ b/src/commands/CmdCustom.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdDiagnostics.cpp b/src/commands/CmdDiagnostics.cpp index 2a9d5d29b..a7fd6feb5 100644 --- a/src/commands/CmdDiagnostics.cpp +++ b/src/commands/CmdDiagnostics.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdExec.cpp b/src/commands/CmdExec.cpp index 84c123ad7..07b7178a0 100644 --- a/src/commands/CmdExec.cpp +++ b/src/commands/CmdExec.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdExport.cpp b/src/commands/CmdExport.cpp index ed318424d..cf8c3b821 100644 --- a/src/commands/CmdExport.cpp +++ b/src/commands/CmdExport.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index fb68860fc..4fd0ce6e5 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdHistory.cpp b/src/commands/CmdHistory.cpp index 31dc3c613..737276faf 100644 --- a/src/commands/CmdHistory.cpp +++ b/src/commands/CmdHistory.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index 3d3d5025f..480513c59 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index e7beda2d0..1d34f1cca 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include @@ -308,6 +307,23 @@ int CmdInfo::execute (std::string& output) view.set (row, 0, STRING_COLUMN_LABEL_URGENCY); view.set (row, 1, trimLeft (format (task->urgency (), 4, 4))); + // Show any UDAs + std::vector all = task->all (); + std::vector ::iterator att; + for (att = all.begin (); att != all.end (); ++att) + { + if (context.config.get ("uda." + *att + ".type") != "") + { + Column* col = context.columns[*att]; + if (col) + { + row = view.addRow (); + view.set (row, 0, col->label ()); + view.set (row, 1, task->get (*att)); + } + } + } + // Create a second table, containing undo log change details. ViewText journal; diff --git a/src/commands/CmdInstall.cpp b/src/commands/CmdInstall.cpp index 84ee1043e..a4566b2a0 100644 --- a/src/commands/CmdInstall.cpp +++ b/src/commands/CmdInstall.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdLog.cpp b/src/commands/CmdLog.cpp index 70f7c0ae1..2cf8392c4 100644 --- a/src/commands/CmdLog.cpp +++ b/src/commands/CmdLog.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdLogo.cpp b/src/commands/CmdLogo.cpp index 8568e92c3..7efe90b23 100644 --- a/src/commands/CmdLogo.cpp +++ b/src/commands/CmdLogo.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdMerge.cpp b/src/commands/CmdMerge.cpp index 3c116a6da..d9ebc9b46 100644 --- a/src/commands/CmdMerge.cpp +++ b/src/commands/CmdMerge.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdProjects.cpp b/src/commands/CmdProjects.cpp index dddf6330b..760ea1e4e 100644 --- a/src/commands/CmdProjects.cpp +++ b/src/commands/CmdProjects.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdPull.cpp b/src/commands/CmdPull.cpp index 3a197c84b..daebac322 100644 --- a/src/commands/CmdPull.cpp +++ b/src/commands/CmdPull.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdPush.cpp b/src/commands/CmdPush.cpp index d5c3531ea..0666335e2 100644 --- a/src/commands/CmdPush.cpp +++ b/src/commands/CmdPush.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdReports.cpp b/src/commands/CmdReports.cpp index d50e8752a..abb08e291 100644 --- a/src/commands/CmdReports.cpp +++ b/src/commands/CmdReports.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdShell.cpp b/src/commands/CmdShell.cpp index 1868b83af..629939ee8 100644 --- a/src/commands/CmdShell.cpp +++ b/src/commands/CmdShell.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdShow.cpp b/src/commands/CmdShow.cpp index ba42a9374..708d9ccbc 100644 --- a/src/commands/CmdShow.cpp +++ b/src/commands/CmdShow.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include @@ -232,6 +231,7 @@ int CmdShow::execute (std::string& output) i->substr (0, 5) != "push." && i->substr (0, 5) != "pull." && i->substr (0, 6) != "merge." && + i->substr (0, 4) != "uda." && i->substr (0, 21) != "urgency.user.project." && i->substr (0, 17) != "urgency.user.tag.") { diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index 94ce5a0f6..bc46e9999 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdTags.cpp b/src/commands/CmdTags.cpp index b6571ce5d..a13046973 100644 --- a/src/commands/CmdTags.cpp +++ b/src/commands/CmdTags.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdTimesheet.cpp b/src/commands/CmdTimesheet.cpp index 5635b9e6c..60e948ffa 100644 --- a/src/commands/CmdTimesheet.cpp +++ b/src/commands/CmdTimesheet.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdUndo.cpp b/src/commands/CmdUndo.cpp index b93aea694..cccdb2248 100644 --- a/src/commands/CmdUndo.cpp +++ b/src/commands/CmdUndo.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdUrgency.cpp b/src/commands/CmdUrgency.cpp index e1ffdb94e..14f153f47 100644 --- a/src/commands/CmdUrgency.cpp +++ b/src/commands/CmdUrgency.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/CmdVersion.cpp b/src/commands/CmdVersion.cpp index ef2551c91..e6eba5b8f 100644 --- a/src/commands/CmdVersion.cpp +++ b/src/commands/CmdVersion.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 8547504ec..98bb7b049 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -487,15 +489,56 @@ void Command::modify_task ( // If the date value is less than 5 years, it is a duration, not a // date, therefore add 'now'. - long l = strtol (result.c_str (), NULL, 10); + long l = (long) strtod (result.c_str (), NULL); if (labs (l) < 5 * 365 * 86400) { + Duration dur (result); Date now; now += l; + //now += dur; task.set (name, now.toEpochString ()); } else + { + Date d (result, context.config.get ("dateformat")); + task.set (name, d.toEpochString ()); + } + } + + // Durations too. + else if (column->type () == "duration") + { + // All values must be eval'd first. + A3 value_tokens; + value_tokens.capture (value); + value_tokens = value_tokens.postfix (value_tokens.tokenize (value_tokens)); + + E9 e (value_tokens); + std::string result = e.evalExpression (task); + context.debug (std::string ("Eval '") + value + "' --> '" + result + "'"); + + Duration d (result); + task.set (name, result); + } + + // Need handling for numeric types, used by UDAs. + else if (column->type () == "numeric") + { + A3 value_tokens; + value_tokens.capture (value); + value_tokens = value_tokens.postfix (value_tokens.tokenize (value_tokens)); + + E9 e (value_tokens); + std::string result = e.evalExpression (task); + context.debug (std::string ("Eval '") + value + "' --> '" + result + "'"); + + Nibbler n (result); + double d; + if (n.getNumber (d) && + n.depleted ()) task.set (name, result); + else + throw format (STRING_UDA_NUMERIC, result); } // By default, just add/remove it. diff --git a/src/en-US.h b/src/en-US.h index b0825f88b..392a75a23 100644 --- a/src/en-US.h +++ b/src/en-US.h @@ -574,7 +574,7 @@ #define STRING_DOM_CANNOT_SET "DOM: Cannot set '{1}'." // Duration -#define STRING_DURATION_UNRECOGNIZED "The duration '{1}' was not recognized." +#define STRING_DURATION_UNRECOGNIZED "The date/duration '{1}' was not recognized." // E9 #define STRING_E9_UNSUPPORTED "Unsupported operator '{1}'." @@ -657,6 +657,8 @@ #define STRING_TRIVIAL_INPUT "You must specify a command or a task to modify." #define STRING_ASSUME_INFO "No command specified - assuming 'information'." #define STRING_INFINITE_LOOP "Terminated substitution because more than {1} changes were made - infinite loop protection." +#define STRING_UDA_TYPE "User defined attributes may only be of type 'string', 'date', 'duration' or 'numeric'." +#define STRING_UDA_NUMERIC "The value '{1}' is not a valid numeric value." // Feedback #define STRING_FEEDBACK_NO_TASKS "No tasks." diff --git a/src/interactive.cpp b/src/interactive.cpp index 7ffb84afc..a9563d56b 100644 --- a/src/interactive.cpp +++ b/src/interactive.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/legacy.cpp b/src/legacy.cpp index f67e76778..08e1590cf 100644 --- a/src/legacy.cpp +++ b/src/legacy.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/recur.cpp b/src/recur.cpp index e05d2e061..c944a38a4 100644 --- a/src/recur.cpp +++ b/src/recur.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/rules.cpp b/src/rules.cpp index 6d6f2da11..088da9b97 100644 --- a/src/rules.cpp +++ b/src/rules.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/sort.cpp b/src/sort.cpp index a2dcf9a00..481c84b7f 100644 --- a/src/sort.cpp +++ b/src/sort.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/src/utf8.cpp b/src/utf8.cpp index cef0bafb9..1dcedb532 100644 --- a/src/utf8.cpp +++ b/src/utf8.cpp @@ -25,7 +25,6 @@ // //////////////////////////////////////////////////////////////////////////////// - #define L10N // Localization complete. #include diff --git a/test/duration.t.cpp b/test/duration.t.cpp index 7f2426681..3008b76c9 100644 --- a/test/duration.t.cpp +++ b/test/duration.t.cpp @@ -49,7 +49,7 @@ int convertDuration (const std::string& input) int main (int argc, char** argv) { - UnitTest t (643); + UnitTest t (644); Duration d; @@ -791,6 +791,10 @@ int main (int argc, char** argv) left -= right; t.is ((int)(time_t)left, 1, "3 -= 2, 3 is now 1"); t.is ((int)(time_t)right, 2, "3 -= 2, 2 is still 2"); + + // Assorted regression tests. + left = Duration ("-864000.00000"); + t.is ((int)(time_t)left, 864000, "-864000.00000 -> 864000"); } catch (const std::string& e) { t.diag (e); } diff --git a/test/nibbler.t.cpp b/test/nibbler.t.cpp index ebf3eead1..49e7e9809 100644 --- a/test/nibbler.t.cpp +++ b/test/nibbler.t.cpp @@ -39,15 +39,15 @@ int main (int argc, char** argv) { #ifdef NIBBLER_FEATURE_DATE #ifdef NIBBLER_FEATURE_REGEX - UnitTest t (296); + UnitTest t (299); #else - UnitTest t (272); + UnitTest t (275); #endif #else #ifdef NIBBLER_FEATURE_REGEX - UnitTest t (246); + UnitTest t (249); #else - UnitTest t (222); + UnitTest t (225); #endif #endif @@ -303,6 +303,11 @@ int main (int argc, char** argv) t.is (d, 2.0, 0.000001, "'2.0' : getNumber () -> '2.0'"); t.ok (n.depleted (), " '' : depleted () -> true"); + n = Nibbler ("-864000.00000"); + t.ok (n.getNumber (d), "'-864000.00000' : getNumber () -> true"); + t.is (d, -864000.0, "'-864000.00000' : getNumber () -> -864000.0"); + t.ok (n.depleted (), " '' : depleted () -> true"); + // bool getLiteral (const std::string&); t.diag ("Nibbler::getLiteral"); n = Nibbler ("foobar");