diff --git a/ChangeLog b/ChangeLog index 9bafc3b02..92b209f63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,7 @@ solarized-light-256.theme (thanks to Stefan Keel). + New 'dependency.indicator' configuration variable for the depends.indicator report field. + + New 'indent.annotation' for the 'description.default' field format. # Tracked Features, sorted by ID. + Added feature #523 & #659, adding 'status' as a reportable field (thanks to diff --git a/NEWS b/NEWS index a004cdf69..a59c98dc9 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,7 @@ New configuration options in taskwarrior 2.0.0 - Extension system now controlled by the 'extensions' configuration variable. - Two new solarized color themes. - New 'dependency.indicator' for the 'depends.indicator' report field format. + - New 'indent.annotation' for the description.default field format. Newly deprecated features in taskwarrior 2.0.0 diff --git a/doc/man/taskrc.5.in b/doc/man/taskrc.5.in index c02e91977..39a1eb41c 100644 --- a/doc/man/taskrc.5.in +++ b/doc/man/taskrc.5.in @@ -211,6 +211,11 @@ added to the description. Set to "none" the output of annotations is disabled and a "+" sign will be added if there are any annotations present. The default value is "full". +.TP +.B indent.annotation=1 +Controls the number of spaces to indent annotations when shown beneath the +description field. The default value is "1". + .TP .B next=2 Is a number, defaulting to 2, which is the number of tasks for each project that diff --git a/src/Config.cpp b/src/Config.cpp index b5b34942a..8c358e10b 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -73,6 +73,7 @@ std::string Config::defaults = "confirmation=yes # Confirmation on delete, big changes\n" "echo.command=yes # Details on command just run\n" "annotations=full # Level of verbosity for annotations: full, sparse or none\n" + "indent.annotation=1 # Indent spaces for annotations\n" "next=2 # How many tasks per project in next report\n" "bulk=2 # > 2 tasks considered 'a lot', for confirmation\n" "nag=You have more urgent tasks. # Nag message to keep you honest\n" // TODO diff --git a/src/Date.cpp b/src/Date.cpp index 07465fb68..3de267ed8 100644 --- a/src/Date.cpp +++ b/src/Date.cpp @@ -694,6 +694,38 @@ int Date::monthOfYear (const std::string& input) return -1; } +//////////////////////////////////////////////////////////////////////////////// +int Date::length (const std::string& format) +{ + int total = 0; + + std::string::const_iterator i; + for (i = format.begin (); i != format.end (); ++i) + { + switch (*i) + { + case 'm': + case 'M': + case 'd': + case 'D': + case 'y': + case 'A': + case 'b': + case 'B': + case 'V': + case 'h': + case 'H': + case 'N': + case 'S': total += 2; break; + case 'a': total += 3; break; + case 'Y': total += 4; break; + default: total += 1; break; + } + } + + return total; +} + //////////////////////////////////////////////////////////////////////////////// time_t Date::easter (int year) { diff --git a/src/Date.h b/src/Date.h index 24572b260..6bca65f48 100644 --- a/src/Date.h +++ b/src/Date.h @@ -69,6 +69,7 @@ public: static int weekOfYear (const std::string&); static int dayOfWeek (const std::string&); static int monthOfYear (const std::string&); + static int length (const std::string&); int month () const; int day () const; diff --git a/src/columns/ColDescription.cpp b/src/columns/ColDescription.cpp index a178ef0b4..8d3dcb4ad 100644 --- a/src/columns/ColDescription.cpp +++ b/src/columns/ColDescription.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -51,18 +52,25 @@ void ColumnDescription::measure (Task& task, int& minimum, int& maximum) { std::string description = task.get ("description"); -/* - std::vector annos; - task.getAnnotations (annos); -*/ - - // TODO Render Date () in appropriate format, to calculate length. - // The text // // ... if (_style == "default") { + int indent = context.config.getInteger ("indent.annotation"); + std::string format = context.config.get ("dateformat.annotation"); + if (format == "") + format = context.config.get ("dateformat"); + + minimum = Date::length (format); + maximum = description.length (); + + std::vector annos; + task.getAnnotations (annos); + std::vector ::iterator i; + for (i = annos.begin (); i != annos.end (); i++) + if (indent + i->value ().length () + minimum + 1 > maximum) + maximum = indent + i->value ().length () + minimum + 1; } // Just the text @@ -84,6 +92,18 @@ void ColumnDescription::measure (Task& task, int& minimum, int& maximum) // The text ... else if (_style == "oneline") { + std::string format = context.config.get ("dateformat.annotation"); + if (format == "") + format = context.config.get ("dateformat"); + + minimum = Date::length (format); + maximum = description.length (); + + std::vector annos; + task.getAnnotations (annos); + std::vector ::iterator i; + for (i = annos.begin (); i != annos.end (); i++) + maximum += i->value ().length () + minimum + 1; } // The te... @@ -96,35 +116,25 @@ void ColumnDescription::measure (Task& task, int& minimum, int& maximum) // The text [2] else if (_style == "count") { + std::vector annos; + task.getAnnotations (annos); + + // + ' ' + '[' + + ']' + maximum = description.length () + 3 + format ((int)annos.size ()).length (); + minimum = 0; + + Nibbler nibbler (description); + std::string word; + while (nibbler.getUntilWS (word)) + { + nibbler.skipWS (); + if (word.length () > minimum) + minimum = word.length (); + } } else throw std::string ("Unrecognized column format '") + _type + "." + _style + "'"; - -/* - std::string project = task.get ("project"); - - if (_style == "parent") - { - std::string::size_type period = project.find ('.'); - if (period != std::string::npos) - project = project.substr (0, period); - } - else if (_style != "default") - throw std::string ("Unrecognized column format '") + _type + "." + _style + "'"; - - minimum = 0; - maximum = project.length (); - - Nibbler nibbler (project); - std::string word; - while (nibbler.getUntilWS (word)) - { - nibbler.skipWS (); - if (word.length () > minimum) - minimum = word.length (); - } -*/ } //////////////////////////////////////////////////////////////////////////////// @@ -141,6 +151,29 @@ void ColumnDescription::render ( // ... if (_style == "default") { + std::vector annos; + task.getAnnotations (annos); + if (annos.size ()) + { + int indent = context.config.getInteger ("indent.annotation"); + std::string format = context.config.get ("dateformat.annotation"); + if (format == "") + format = context.config.get ("dateformat"); + + std::vector ::iterator i; + for (i = annos.begin (); i != annos.end (); i++) + { + Date dt (atoi (i->name ().substr (11).c_str ())); + description += "\n" + std::string (indent, ' ') + dt.toString (format) + " " + i->value (); + } + } + + std::vector raw; + wrapText (raw, description, width); + + std::vector ::iterator i; + for (i = raw.begin (); i != raw.end (); ++i) + lines.push_back (color.colorize (leftJustify (*i, width))); } // This is a description @@ -157,6 +190,28 @@ void ColumnDescription::render ( // This is a description ... else if (_style == "oneline") { + std::vector annos; + task.getAnnotations (annos); + if (annos.size ()) + { + std::string format = context.config.get ("dateformat.annotation"); + if (format == "") + format = context.config.get ("dateformat"); + + std::vector ::iterator i; + for (i = annos.begin (); i != annos.end (); i++) + { + Date dt (atoi (i->name ().substr (11).c_str ())); + description += " " + dt.toString (format) + " " + i->value (); + } + } + + std::vector raw; + wrapText (raw, description, width); + + std::vector ::iterator i; + for (i = raw.begin (); i != raw.end (); ++i) + lines.push_back (color.colorize (leftJustify (*i, width))); } // This is a des... @@ -172,6 +227,18 @@ void ColumnDescription::render ( // This is a description [2] else if (_style == "count") { + std::vector annos; + task.getAnnotations (annos); + + if (annos.size ()) + description += " [" + format ((int) annos.size ()) + "]"; + + std::vector raw; + wrapText (raw, description, width); + + std::vector ::iterator i; + for (i = raw.begin (); i != raw.end (); ++i) + lines.push_back (color.colorize (leftJustify (*i, width))); } } diff --git a/test/view.t.cpp b/test/view.t.cpp index 5b1c94e00..98ae8ac0e 100644 --- a/test/view.t.cpp +++ b/test/view.t.cpp @@ -47,6 +47,7 @@ int main (int argc, char** argv) context.config.set ("dependency.indicator", "D"); context.config.set ("recurrence.indicator", "R"); context.config.set ("dateformat", "Y-M-D"); + context.config.set ("indent.annotation", "2"); // Two sample tasks. Task t1 ("[" @@ -55,6 +56,7 @@ int main (int argc, char** argv) "description:\"This is the description text\" " "project:\"Home\" " "priority:\"H\" " + "annotation_1234567890:\"This is an annotation\" " "start:\"1234567890\" " "due:\"1234567890\" " "tags:\"one,two\"" @@ -94,8 +96,10 @@ int main (int argc, char** argv) // view.add (Column::factory ("tags.indicator")); view.add (Column::factory ("tags.count")); // view.add (Column::factory ("description")); - view.add (Column::factory ("description.desc")); +// view.add (Column::factory ("description.desc")); // view.add (Column::factory ("description.truncated")); + view.add (Column::factory ("description.oneline")); +// view.add (Column::factory ("description.count")); // view.add (Column::factory ("depends")); // view.add (Column::factory ("depends.count")); view.add (Column::factory ("depends.indicator"));