mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Feature #800
- Added feature #800, adding a new command 'columns' that lists all the columns available for custom reports, and includes their formatting options (thanks to T. Charles Yun).
This commit is contained in:
parent
3a5370ddf1
commit
27a04b29f5
28 changed files with 372 additions and 64 deletions
|
@ -82,6 +82,9 @@
|
||||||
their descriptions.
|
their descriptions.
|
||||||
+ Added feature #779, which uses more relevant and consistent terms on the
|
+ Added feature #779, which uses more relevant and consistent terms on the
|
||||||
'burndown' charts.
|
'burndown' charts.
|
||||||
|
+ Added feature #800, adding a new command 'columns' that lists all the columns
|
||||||
|
available for custom reports, and includes their formatting options (thanks
|
||||||
|
to T. Charles Yun).
|
||||||
|
|
||||||
# Tracked Bugs, sorted by ID.
|
# Tracked Bugs, sorted by ID.
|
||||||
+ Fixed bug #403, which disambiguates certain commands involving numbers.
|
+ Fixed bug #403, which disambiguates certain commands involving numbers.
|
||||||
|
|
1
NEWS
1
NEWS
|
@ -23,6 +23,7 @@ New Features in taskwarrior 2.0.0
|
||||||
- Filtering now available on most read-only commands.
|
- Filtering now available on most read-only commands.
|
||||||
- The done, delete, start and stop commands now allow modification to the
|
- The done, delete, start and stop commands now allow modification to the
|
||||||
task and annotations.
|
task and annotations.
|
||||||
|
- New 'columns' command to list the supported columns and formats.
|
||||||
|
|
||||||
Please refer to the ChangeLog file for full details. There are too many to
|
Please refer to the ChangeLog file for full details. There are too many to
|
||||||
list here.
|
list here.
|
||||||
|
|
|
@ -152,6 +152,12 @@ std::string Date::toISO ()
|
||||||
return iso.str ();
|
return iso.str ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
double Date::toJulian ()
|
||||||
|
{
|
||||||
|
return (mT / 86400.0) + 2440587.5;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Date::toEpoch (time_t& epoch)
|
void Date::toEpoch (time_t& epoch)
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
time_t toEpoch ();
|
time_t toEpoch ();
|
||||||
std::string toEpochString ();
|
std::string toEpochString ();
|
||||||
std::string toISO ();
|
std::string toISO ();
|
||||||
|
double toJulian ();
|
||||||
void toMDY (int&, int&, int&);
|
void toMDY (int&, int&, int&);
|
||||||
const std::string toString (const std::string& format = "m/d/Y") const;
|
const std::string toString (const std::string& format = "m/d/Y") const;
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ std::string ViewTask::render (std::vector <Task>& data, std::vector <int>& seque
|
||||||
for (i = _columns.begin (); i != _columns.end (); ++i)
|
for (i = _columns.begin (); i != _columns.end (); ++i)
|
||||||
{
|
{
|
||||||
// Headers factor in to width calculations.
|
// Headers factor in to width calculations.
|
||||||
int global_min = utf8_length ((*i)->getLabel ());
|
int global_min = utf8_length ((*i)->label ());
|
||||||
int global_ideal = global_min;
|
int global_ideal = global_min;
|
||||||
|
|
||||||
for (unsigned int s = 0; s < sequence.size (); ++s)
|
for (unsigned int s = 0; s < sequence.size (); ++s)
|
||||||
|
|
|
@ -115,7 +115,7 @@ std::string ViewText::render ()
|
||||||
for (unsigned int col = 0; col < _columns.size (); ++col)
|
for (unsigned int col = 0; col < _columns.size (); ++col)
|
||||||
{
|
{
|
||||||
// Headers factor in to width calculations.
|
// Headers factor in to width calculations.
|
||||||
int global_min = utf8_length (_columns[col]->getLabel ());
|
int global_min = utf8_length (_columns[col]->label ());
|
||||||
int global_ideal = global_min;
|
int global_ideal = global_min;
|
||||||
|
|
||||||
for (unsigned int row = 0; row < _data.size (); ++row)
|
for (unsigned int row = 0; row < _data.size (); ++row)
|
||||||
|
|
|
@ -43,8 +43,22 @@ ColumnDate::ColumnDate ()
|
||||||
{
|
{
|
||||||
_name = "";
|
_name = "";
|
||||||
_type = "date";
|
_type = "date";
|
||||||
_style = "default";
|
_style = "formatted";
|
||||||
_label = "";
|
_label = "";
|
||||||
|
|
||||||
|
_styles.push_back ("formatted");
|
||||||
|
_styles.push_back ("julian");
|
||||||
|
_styles.push_back ("epoch");
|
||||||
|
_styles.push_back ("iso");
|
||||||
|
_styles.push_back ("age");
|
||||||
|
|
||||||
|
Date now;
|
||||||
|
now -= 125; // So that "age" is non-zero.
|
||||||
|
_examples.push_back (now.toString (context.config.get ("dateformat")));
|
||||||
|
_examples.push_back (format (now.toJulian (), 13, 12));
|
||||||
|
_examples.push_back (now.toEpochString ());
|
||||||
|
_examples.push_back (now.toISO ());
|
||||||
|
_examples.push_back (Duration (Date () - now).formatCompact ());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -68,7 +82,8 @@ void ColumnDate::measure (Task& task, int& minimum, int& maximum)
|
||||||
{
|
{
|
||||||
Date date ((time_t) strtol (task.get (_name).c_str (), NULL, 10));
|
Date date ((time_t) strtol (task.get (_name).c_str (), NULL, 10));
|
||||||
|
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "formatted")
|
||||||
{
|
{
|
||||||
// Determine the output date format, which uses a hierarchy of definitions.
|
// Determine the output date format, which uses a hierarchy of definitions.
|
||||||
// rc.report.<report>.dateformat
|
// rc.report.<report>.dateformat
|
||||||
|
@ -84,9 +99,7 @@ void ColumnDate::measure (Task& task, int& minimum, int& maximum)
|
||||||
}
|
}
|
||||||
else if (_style == "julian")
|
else if (_style == "julian")
|
||||||
{
|
{
|
||||||
// (JD − 2440587.5) × 86400
|
minimum = maximum = format (date.toJulian (), 13, 12).length ();
|
||||||
double julian = (date.toEpoch () / 86400.0) + 2440587.5;
|
|
||||||
minimum = maximum = format (julian, 13, 12).length ();
|
|
||||||
}
|
}
|
||||||
else if (_style == "epoch")
|
else if (_style == "epoch")
|
||||||
{
|
{
|
||||||
|
@ -115,7 +128,8 @@ void ColumnDate::render (
|
||||||
{
|
{
|
||||||
if (task.has (_name))
|
if (task.has (_name))
|
||||||
{
|
{
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "formatted")
|
||||||
{
|
{
|
||||||
// Determine the output date format, which uses a hierarchy of definitions.
|
// Determine the output date format, which uses a hierarchy of definitions.
|
||||||
// rc.report.<report>.dateformat
|
// rc.report.<report>.dateformat
|
||||||
|
@ -135,13 +149,11 @@ void ColumnDate::render (
|
||||||
}
|
}
|
||||||
else if (_style == "julian")
|
else if (_style == "julian")
|
||||||
{
|
{
|
||||||
double julian = (Date ((time_t) strtol (task.get (_name).c_str (), NULL, 10))
|
|
||||||
.toEpoch () / 86400.0) + 2440587.5;
|
|
||||||
|
|
||||||
lines.push_back (
|
lines.push_back (
|
||||||
color.colorize (
|
color.colorize (
|
||||||
rightJustify (
|
rightJustify (
|
||||||
format (julian, 13, 12), width)));
|
format (Date ((time_t) strtol (task.get (_name).c_str (), NULL, 10))
|
||||||
|
.toJulian (), 13, 12), width)));
|
||||||
}
|
}
|
||||||
else if (_style == "epoch")
|
else if (_style == "epoch")
|
||||||
{
|
{
|
||||||
|
@ -169,18 +181,6 @@ void ColumnDate::render (
|
||||||
rightJustify (
|
rightJustify (
|
||||||
Duration (now - date).formatCompact (), width)));
|
Duration (now - date).formatCompact (), width)));
|
||||||
}
|
}
|
||||||
else if (_style == "short")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (_style == "active")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (_style == "countdown")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (_style == "remaining")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,16 @@ ColumnDepends::ColumnDepends ()
|
||||||
{
|
{
|
||||||
_name = "depends";
|
_name = "depends";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "list";
|
||||||
_label = STRING_COLUMN_LABEL_DEP;
|
_label = STRING_COLUMN_LABEL_DEP;
|
||||||
|
|
||||||
|
_styles.push_back ("list");
|
||||||
|
_styles.push_back ("count");
|
||||||
|
_styles.push_back ("indicator");
|
||||||
|
|
||||||
|
_examples.push_back ("1 2 10");
|
||||||
|
_examples.push_back ("[3]");
|
||||||
|
_examples.push_back (context.config.get ("dependency.indicator"));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -76,7 +84,8 @@ void ColumnDepends::measure (Task& task, int& minimum, int& maximum)
|
||||||
|
|
||||||
if (_style == "indicator") minimum = maximum = context.config.get ("dependency.indicator").length ();
|
if (_style == "indicator") minimum = maximum = context.config.get ("dependency.indicator").length ();
|
||||||
else if (_style == "count") minimum = maximum = 2 + format ((int) blocking.size ()).length ();
|
else if (_style == "count") minimum = maximum = 2 + format ((int) blocking.size ()).length ();
|
||||||
else if (_style == "default")
|
else if (_style == "default" ||
|
||||||
|
_style == "list")
|
||||||
{
|
{
|
||||||
minimum = maximum = 0;
|
minimum = maximum = 0;
|
||||||
if (task.has ("depends"))
|
if (task.has ("depends"))
|
||||||
|
@ -129,7 +138,8 @@ void ColumnDepends::render (
|
||||||
color.colorize (
|
color.colorize (
|
||||||
rightJustify ("[" + format ((int)blocking.size ()) + "]", width)));
|
rightJustify ("[" + format ((int)blocking.size ()) + "]", width)));
|
||||||
}
|
}
|
||||||
else if (_style == "default")
|
else if (_style == "default" ||
|
||||||
|
_style == "list")
|
||||||
{
|
{
|
||||||
std::vector <int> blocking_ids;
|
std::vector <int> blocking_ids;
|
||||||
std::vector <Task>::iterator t;
|
std::vector <Task>::iterator t;
|
||||||
|
|
|
@ -42,8 +42,35 @@ ColumnDescription::ColumnDescription ()
|
||||||
{
|
{
|
||||||
_name = "description";
|
_name = "description";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "combined";
|
||||||
_label = STRING_COLUMN_LABEL_DESC;
|
_label = STRING_COLUMN_LABEL_DESC;
|
||||||
|
|
||||||
|
_styles.push_back ("combined");
|
||||||
|
_styles.push_back ("desc");
|
||||||
|
_styles.push_back ("oneline");
|
||||||
|
_styles.push_back ("truncated");
|
||||||
|
_styles.push_back ("count");
|
||||||
|
|
||||||
|
std::string t = Date ().toString (context.config.get ("dateformat"));
|
||||||
|
std::string d = STRING_COLUMN_EXAMPLES_DESC;
|
||||||
|
std::string a1 = STRING_COLUMN_EXAMPLES_ANNO1;
|
||||||
|
std::string a2 = STRING_COLUMN_EXAMPLES_ANNO2;
|
||||||
|
std::string a3 = STRING_COLUMN_EXAMPLES_ANNO3;
|
||||||
|
std::string a4 = STRING_COLUMN_EXAMPLES_ANNO4;
|
||||||
|
|
||||||
|
_examples.push_back (d
|
||||||
|
+ "\n " + t + " " + a1
|
||||||
|
+ "\n " + t + " " + a2
|
||||||
|
+ "\n " + t + " " + a3
|
||||||
|
+ "\n " + t + " " + a4);
|
||||||
|
_examples.push_back (d);
|
||||||
|
_examples.push_back (d
|
||||||
|
+ " " + t + " " + a1
|
||||||
|
+ " " + t + " " + a2
|
||||||
|
+ " " + t + " " + a3
|
||||||
|
+ " " + t + " " + a4);
|
||||||
|
_examples.push_back (d.substr (0, 20) + "...");
|
||||||
|
_examples.push_back (d + " [4]");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -66,7 +93,8 @@ void ColumnDescription::measure (Task& task, int& minimum, int& maximum)
|
||||||
// The text
|
// The text
|
||||||
// <indent> <date> <anno>
|
// <indent> <date> <anno>
|
||||||
// ...
|
// ...
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "combined")
|
||||||
{
|
{
|
||||||
int indent = context.config.getInteger ("indent.annotation");
|
int indent = context.config.getInteger ("indent.annotation");
|
||||||
std::string format = context.config.get ("dateformat.annotation");
|
std::string format = context.config.get ("dateformat.annotation");
|
||||||
|
@ -149,7 +177,8 @@ void ColumnDescription::render (
|
||||||
// This is a description
|
// This is a description
|
||||||
// <date> <anno>
|
// <date> <anno>
|
||||||
// ...
|
// ...
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "combined")
|
||||||
{
|
{
|
||||||
int indent = context.config.getInteger ("indent.annotation");
|
int indent = context.config.getInteger ("indent.annotation");
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,12 @@ ColumnDue::ColumnDue ()
|
||||||
{
|
{
|
||||||
_name = "due";
|
_name = "due";
|
||||||
_label = STRING_COLUMN_LABEL_DUE;
|
_label = STRING_COLUMN_LABEL_DUE;
|
||||||
|
|
||||||
|
_styles.push_back ("countdown");
|
||||||
|
|
||||||
|
Date now;
|
||||||
|
now += 125;
|
||||||
|
_examples.push_back (Duration (now - Date ()).formatCompact ());
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -40,8 +40,12 @@ ColumnID::ColumnID ()
|
||||||
{
|
{
|
||||||
_name = "id";
|
_name = "id";
|
||||||
_type = "number";
|
_type = "number";
|
||||||
_style = "default";
|
_style = "number";
|
||||||
_label = STRING_COLUMN_LABEL_ID;
|
_label = STRING_COLUMN_LABEL_ID;
|
||||||
|
|
||||||
|
_styles.push_back ("number");
|
||||||
|
|
||||||
|
_examples.push_back ("123");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -69,7 +73,8 @@ void ColumnID::measure (Task& task, int& minimum, int& maximum)
|
||||||
|
|
||||||
minimum = maximum = length;
|
minimum = maximum = length;
|
||||||
|
|
||||||
if (_style != "default")
|
if (_style != "default" &&
|
||||||
|
_style != "number")
|
||||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,14 @@ ColumnPriority::ColumnPriority ()
|
||||||
{
|
{
|
||||||
_name = "priority";
|
_name = "priority";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "short";
|
||||||
_label = STRING_COLUMN_LABEL_PRI;
|
_label = STRING_COLUMN_LABEL_PRI;
|
||||||
|
|
||||||
|
_styles.push_back ("short");
|
||||||
|
_styles.push_back ("long");
|
||||||
|
|
||||||
|
_examples.push_back ("H");
|
||||||
|
_examples.push_back ("High");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -86,7 +92,8 @@ void ColumnPriority::measure (Task& task, int& minimum, int& maximum)
|
||||||
else if (priority == "M") minimum = maximum = 6;
|
else if (priority == "M") minimum = maximum = 6;
|
||||||
else if (priority == "L") minimum = maximum = 3;
|
else if (priority == "L") minimum = maximum = 3;
|
||||||
}
|
}
|
||||||
else if (_style != "default")
|
else if (_style != "default" &&
|
||||||
|
_style != "short")
|
||||||
throw format (STRING_COLUMN_BAD_FORMAT, "priority", _style);
|
throw format (STRING_COLUMN_BAD_FORMAT, "priority", _style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,14 @@ ColumnProject::ColumnProject ()
|
||||||
{
|
{
|
||||||
_name = "project";
|
_name = "project";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "full";
|
||||||
_label = STRING_COLUMN_LABEL_PROJECT;
|
_label = STRING_COLUMN_LABEL_PROJECT;
|
||||||
|
|
||||||
|
_styles.push_back ("full");
|
||||||
|
_styles.push_back ("parent");
|
||||||
|
|
||||||
|
_examples.push_back (STRING_COLUMN_EXAMPLES_PROJ);
|
||||||
|
_examples.push_back (STRING_COLUMN_EXAMPLES_PAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -66,7 +72,8 @@ void ColumnProject::measure (Task& task, int& minimum, int& maximum)
|
||||||
if (period != std::string::npos)
|
if (period != std::string::npos)
|
||||||
project = project.substr (0, period);
|
project = project.substr (0, period);
|
||||||
}
|
}
|
||||||
else if (_style != "default")
|
else if (_style != "default" &&
|
||||||
|
_style != "full")
|
||||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||||
|
|
||||||
minimum = longestWord (project);
|
minimum = longestWord (project);
|
||||||
|
|
|
@ -39,8 +39,14 @@ ColumnRecur::ColumnRecur ()
|
||||||
{
|
{
|
||||||
_name = "recur";
|
_name = "recur";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "duration";
|
||||||
_label = STRING_COLUMN_LABEL_RECUR;
|
_label = STRING_COLUMN_LABEL_RECUR;
|
||||||
|
|
||||||
|
_styles.push_back ("duration");
|
||||||
|
_styles.push_back ("indicator");
|
||||||
|
|
||||||
|
_examples.push_back ("weekly");
|
||||||
|
_examples.push_back (context.config.get ("recurrence.indicator"));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -69,7 +75,8 @@ void ColumnRecur::setStyle (const std::string& value)
|
||||||
// Set the minimum and maximum widths for the value.
|
// Set the minimum and maximum widths for the value.
|
||||||
void ColumnRecur::measure (Task& task, int& minimum, int& maximum)
|
void ColumnRecur::measure (Task& task, int& minimum, int& maximum)
|
||||||
{
|
{
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "duration")
|
||||||
{
|
{
|
||||||
minimum = maximum = task.get ("recur").length ();
|
minimum = maximum = task.get ("recur").length ();
|
||||||
}
|
}
|
||||||
|
@ -89,7 +96,8 @@ void ColumnRecur::render (
|
||||||
int width,
|
int width,
|
||||||
Color& color)
|
Color& color)
|
||||||
{
|
{
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "duration")
|
||||||
{
|
{
|
||||||
lines.push_back (color.colorize (rightJustify (task.get ("recur"), width)));
|
lines.push_back (color.colorize (rightJustify (task.get ("recur"), width)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,10 @@ ColumnStart::ColumnStart ()
|
||||||
{
|
{
|
||||||
_name = "start";
|
_name = "start";
|
||||||
_label = STRING_COLUMN_LABEL_STARTED;
|
_label = STRING_COLUMN_LABEL_STARTED;
|
||||||
|
|
||||||
|
_styles.push_back ("active");
|
||||||
|
|
||||||
|
_examples.push_back (context.config.get ("active.indicator"));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -39,8 +39,14 @@ ColumnStatus::ColumnStatus ()
|
||||||
{
|
{
|
||||||
_name = "status";
|
_name = "status";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "long";
|
||||||
_label = STRING_COLUMN_LABEL_STATUS;
|
_label = STRING_COLUMN_LABEL_STATUS;
|
||||||
|
|
||||||
|
_styles.push_back ("long");
|
||||||
|
_styles.push_back ("short");
|
||||||
|
|
||||||
|
_examples.push_back (STRING_COLUMN_LABEL_STAT_PE);
|
||||||
|
_examples.push_back (STRING_COLUMN_LABEL_STAT_P);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -71,7 +77,8 @@ void ColumnStatus::measure (Task& task, int& minimum, int& maximum)
|
||||||
{
|
{
|
||||||
Task::status status = task.getStatus ();
|
Task::status status = task.getStatus ();
|
||||||
|
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "long")
|
||||||
{
|
{
|
||||||
if (status == Task::pending ||
|
if (status == Task::pending ||
|
||||||
status == Task::deleted ||
|
status == Task::deleted ||
|
||||||
|
@ -101,7 +108,8 @@ void ColumnStatus::render (
|
||||||
Task::status status = task.getStatus ();
|
Task::status status = task.getStatus ();
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "long")
|
||||||
{
|
{
|
||||||
if (status == Task::pending) value = STRING_COLUMN_LABEL_STAT_PE;
|
if (status == Task::pending) value = STRING_COLUMN_LABEL_STAT_PE;
|
||||||
else if (status == Task::completed) value = STRING_COLUMN_LABEL_STAT_CO;
|
else if (status == Task::completed) value = STRING_COLUMN_LABEL_STAT_CO;
|
||||||
|
|
|
@ -39,8 +39,18 @@ ColumnString::ColumnString ()
|
||||||
{
|
{
|
||||||
_name = "string";
|
_name = "string";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "left";
|
||||||
_label = "";
|
_label = "";
|
||||||
|
|
||||||
|
_styles.push_back ("left");
|
||||||
|
_styles.push_back ("right");
|
||||||
|
_styles.push_back ("left_fixed");
|
||||||
|
_styles.push_back ("right_fixed");
|
||||||
|
|
||||||
|
_styles.push_back ("Hello (wrapped) ");
|
||||||
|
_styles.push_back (" Hello (wrapped)");
|
||||||
|
_styles.push_back ("Hello (no-wrap) ");
|
||||||
|
_styles.push_back (" Hello (no-wrap)");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -40,8 +40,16 @@ ColumnTags::ColumnTags ()
|
||||||
{
|
{
|
||||||
_name = "tags";
|
_name = "tags";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "list";
|
||||||
_label = STRING_COLUMN_LABEL_TAGS;
|
_label = STRING_COLUMN_LABEL_TAGS;
|
||||||
|
|
||||||
|
_styles.push_back ("list");
|
||||||
|
_styles.push_back ("indicator");
|
||||||
|
_styles.push_back ("count");
|
||||||
|
|
||||||
|
_examples.push_back (STRING_COLUMN_EXAMPLES_TAGS);
|
||||||
|
_examples.push_back (context.config.get ("tag.indicator"));
|
||||||
|
_examples.push_back ("[2]");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -78,7 +86,8 @@ void ColumnTags::measure (Task& task, int& minimum, int& maximum)
|
||||||
|
|
||||||
if (_style == "indicator") minimum = maximum = context.config.get ("tag.indicator").length ();
|
if (_style == "indicator") minimum = maximum = context.config.get ("tag.indicator").length ();
|
||||||
else if (_style == "count") minimum = maximum = 3;
|
else if (_style == "count") minimum = maximum = 3;
|
||||||
else if (_style == "default")
|
else if (_style == "default" ||
|
||||||
|
_style == "list")
|
||||||
{
|
{
|
||||||
std::string tags = task.get (_name);
|
std::string tags = task.get (_name);
|
||||||
minimum = 0;
|
minimum = 0;
|
||||||
|
@ -122,7 +131,8 @@ void ColumnTags::render (
|
||||||
color.colorize (
|
color.colorize (
|
||||||
rightJustify ("[" + format ((int)all.size ()) + "]", width)));
|
rightJustify ("[" + format ((int)all.size ()) + "]", width)));
|
||||||
}
|
}
|
||||||
else if (_style == "default")
|
else if (_style == "default" ||
|
||||||
|
_style == "list")
|
||||||
{
|
{
|
||||||
std::replace (tags.begin (), tags.end (), ',', ' ');
|
std::replace (tags.begin (), tags.end (), ',', ' ');
|
||||||
std::vector <std::string> all;
|
std::vector <std::string> all;
|
||||||
|
|
|
@ -40,8 +40,14 @@ ColumnUUID::ColumnUUID ()
|
||||||
{
|
{
|
||||||
_name = "uuid";
|
_name = "uuid";
|
||||||
_type = "string";
|
_type = "string";
|
||||||
_style = "default";
|
_style = "long";
|
||||||
_label = STRING_COLUMN_LABEL_UUID;
|
_label = STRING_COLUMN_LABEL_UUID;
|
||||||
|
|
||||||
|
_styles.push_back ("long");
|
||||||
|
_styles.push_back ("short");
|
||||||
|
|
||||||
|
_examples.push_back ("f30cb9c3-3fc0-483f-bfb2-3bf134f00694");
|
||||||
|
_examples.push_back ("34f00694");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -59,7 +65,7 @@ bool ColumnUUID::validate (std::string& value)
|
||||||
// Set the minimum and maximum widths for the value.
|
// Set the minimum and maximum widths for the value.
|
||||||
void ColumnUUID::measure (Task&, int& minimum, int& maximum)
|
void ColumnUUID::measure (Task&, int& minimum, int& maximum)
|
||||||
{
|
{
|
||||||
if (_style == "default") minimum = maximum = 36;
|
if (_style == "default" || _style == "long") minimum = maximum = 36;
|
||||||
else if (_style == "short") minimum = maximum = 8;
|
else if (_style == "short") minimum = maximum = 8;
|
||||||
else
|
else
|
||||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||||
|
@ -74,7 +80,8 @@ void ColumnUUID::render (
|
||||||
{
|
{
|
||||||
// f30cb9c3-3fc0-483f-bfb2-3bf134f00694 default
|
// f30cb9c3-3fc0-483f-bfb2-3bf134f00694 default
|
||||||
// 34f00694 short
|
// 34f00694 short
|
||||||
if (_style == "default")
|
if (_style == "default" ||
|
||||||
|
_style == "long")
|
||||||
lines.push_back (color.colorize (leftJustify (task.get (_name), width)));
|
lines.push_back (color.colorize (leftJustify (task.get (_name), width)));
|
||||||
|
|
||||||
else if (_style == "short")
|
else if (_style == "short")
|
||||||
|
|
|
@ -39,8 +39,14 @@ ColumnUrgency::ColumnUrgency ()
|
||||||
{
|
{
|
||||||
_name = "urgency";
|
_name = "urgency";
|
||||||
_type = "number";
|
_type = "number";
|
||||||
_style = "default";
|
_style = "real";
|
||||||
_label = STRING_COLUMN_LABEL_URGENCY;
|
_label = STRING_COLUMN_LABEL_URGENCY;
|
||||||
|
|
||||||
|
_styles.push_back ("real");
|
||||||
|
_styles.push_back ("integer");
|
||||||
|
|
||||||
|
_examples.push_back ("4.6");
|
||||||
|
_examples.push_back ("4");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -52,9 +58,17 @@ ColumnUrgency::~ColumnUrgency ()
|
||||||
// Set the minimum and maximum widths for the value.
|
// Set the minimum and maximum widths for the value.
|
||||||
void ColumnUrgency::measure (Task& task, int& minimum, int& maximum)
|
void ColumnUrgency::measure (Task& task, int& minimum, int& maximum)
|
||||||
{
|
{
|
||||||
|
if (_style == "default" ||
|
||||||
|
_style == "real")
|
||||||
|
{
|
||||||
minimum = maximum = format (task.urgency (), 4, 3).length ();
|
minimum = maximum = format (task.urgency (), 4, 3).length ();
|
||||||
|
}
|
||||||
|
else if (_style == "integer")
|
||||||
|
{
|
||||||
|
minimum = maximum = format ((int)task.urgency ()).length ();
|
||||||
|
}
|
||||||
|
|
||||||
if (_style != "default")
|
else
|
||||||
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,10 +79,21 @@ void ColumnUrgency::render (
|
||||||
int width,
|
int width,
|
||||||
Color& color)
|
Color& color)
|
||||||
{
|
{
|
||||||
|
if (_style == "default" ||
|
||||||
|
_style == "real")
|
||||||
|
{
|
||||||
lines.push_back (
|
lines.push_back (
|
||||||
color.colorize (
|
color.colorize (
|
||||||
rightJustify (
|
rightJustify (
|
||||||
format (task.urgency (), 4, 3), width)));
|
format (task.urgency (), 4, 3), width)));
|
||||||
|
}
|
||||||
|
else if (_style == "integer")
|
||||||
|
{
|
||||||
|
lines.push_back (
|
||||||
|
color.colorize (
|
||||||
|
rightJustify (
|
||||||
|
format ((int)task.urgency ()), width)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -45,9 +45,11 @@ public:
|
||||||
bool operator== (const Column&) const; // TODO Is this necessary?
|
bool operator== (const Column&) const; // TODO Is this necessary?
|
||||||
~Column ();
|
~Column ();
|
||||||
|
|
||||||
std::string getStyle () { return _style; }
|
std::string style () const { return _style; }
|
||||||
std::string getLabel () { return _label; }
|
std::string label () const { return _label; }
|
||||||
std::string type () const { return _type; }
|
std::string type () const { return _type; }
|
||||||
|
std::vector <std::string> styles () const { return _styles; }
|
||||||
|
std::vector <std::string> examples () const { return _examples; }
|
||||||
|
|
||||||
virtual void setStyle (const std::string& value) { _style = value; }
|
virtual void setStyle (const std::string& value) { _style = value; }
|
||||||
virtual void setLabel (const std::string& value) { _label = value; }
|
virtual void setLabel (const std::string& value) { _label = value; }
|
||||||
|
@ -66,6 +68,8 @@ protected:
|
||||||
std::string _style;
|
std::string _style;
|
||||||
std::string _label;
|
std::string _label;
|
||||||
std::string _report;
|
std::string _report;
|
||||||
|
std::vector <std::string> _styles;
|
||||||
|
std::vector <std::string> _examples;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,6 +13,7 @@ set (commands_SRCS Command.cpp Command.h
|
||||||
CmdCalendar.cpp CmdCalendar.h
|
CmdCalendar.cpp CmdCalendar.h
|
||||||
CmdCommands.cpp CmdCommands.h
|
CmdCommands.cpp CmdCommands.h
|
||||||
CmdColor.cpp CmdColor.h
|
CmdColor.cpp CmdColor.h
|
||||||
|
CmdColumns.cpp CmdColumns.h
|
||||||
CmdConfig.cpp CmdConfig.h
|
CmdConfig.cpp CmdConfig.h
|
||||||
CmdCount.cpp CmdCount.h
|
CmdCount.cpp CmdCount.h
|
||||||
CmdCustom.cpp CmdCustom.h
|
CmdCustom.cpp CmdCustom.h
|
||||||
|
|
97
src/commands/CmdColumns.cpp
Normal file
97
src/commands/CmdColumns.cpp
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// taskwarrior - a command line task list manager.
|
||||||
|
//
|
||||||
|
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License as published by the Free Software
|
||||||
|
// Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
// version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program; if not, write to the
|
||||||
|
//
|
||||||
|
// Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor,
|
||||||
|
// Boston, MA
|
||||||
|
// 02110-1301
|
||||||
|
// USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define L10N // Localization complete.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <Context.h>
|
||||||
|
#include <ViewText.h>
|
||||||
|
#include <Color.h>
|
||||||
|
#include <text.h>
|
||||||
|
#include <i18n.h>
|
||||||
|
#include <main.h>
|
||||||
|
#include <CmdColumns.h>
|
||||||
|
|
||||||
|
extern Context context;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CmdColumns::CmdColumns ()
|
||||||
|
{
|
||||||
|
_keyword = "columns";
|
||||||
|
_usage = "task columns";
|
||||||
|
_description = STRING_CMD_COLUMNS_USAGE;
|
||||||
|
_read_only = true;
|
||||||
|
_displays_id = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int CmdColumns::execute (std::string& output)
|
||||||
|
{
|
||||||
|
// Include all columns in the table.
|
||||||
|
std::vector <std::string> names;
|
||||||
|
std::map <std::string, Column*>::const_iterator col;
|
||||||
|
for (col = context.columns.begin (); col != context.columns.end (); ++col)
|
||||||
|
names.push_back (col->first);
|
||||||
|
|
||||||
|
std::sort (names.begin (), names.end ());
|
||||||
|
|
||||||
|
// Render a list of project names from the map.
|
||||||
|
ViewText formats;
|
||||||
|
formats.width (context.getWidth ());
|
||||||
|
formats.add (Column::factory ("string", STRING_COLUMN_LABEL_COLUMN));
|
||||||
|
formats.add (Column::factory ("string", STRING_COLUMN_LABEL_STYLES));
|
||||||
|
formats.add (Column::factory ("string", STRING_COLUMN_LABEL_EXAMPLES));
|
||||||
|
|
||||||
|
Color alternate (context.config.get ("color.alternate"));
|
||||||
|
formats.colorOdd (alternate);
|
||||||
|
formats.intraColorOdd (alternate);
|
||||||
|
|
||||||
|
std::vector <std::string>::iterator name;
|
||||||
|
for (name = names.begin (); name != names.end (); ++name)
|
||||||
|
{
|
||||||
|
const std::vector <std::string> styles = context.columns[*name]->styles ();
|
||||||
|
const std::vector <std::string> examples = context.columns[*name]->examples ();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < styles.size (); ++i)
|
||||||
|
{
|
||||||
|
int row = formats.addRow ();
|
||||||
|
formats.set (row, 0, i == 0 ? *name : "");
|
||||||
|
formats.set (row, 1, styles[i] + (i == 0 ? "*" : ""));
|
||||||
|
formats.set (row, 2, i < examples.size () ? examples[i] : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output = optionalBlankLine ()
|
||||||
|
+ formats.render ()
|
||||||
|
+ "\n"
|
||||||
|
+ STRING_CMD_COLUMNS_NOTE
|
||||||
|
+ "\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
42
src/commands/CmdColumns.h
Normal file
42
src/commands/CmdColumns.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// taskwarrior - a command line task list manager.
|
||||||
|
//
|
||||||
|
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU General Public License as published by the Free Software
|
||||||
|
// Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
// version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
// details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along with
|
||||||
|
// this program; if not, write to the
|
||||||
|
//
|
||||||
|
// Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor,
|
||||||
|
// Boston, MA
|
||||||
|
// 02110-1301
|
||||||
|
// USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_CMDCOLUMNS
|
||||||
|
#define INCLUDED_CMDCOLUMNS
|
||||||
|
#define L10N // Localization complete.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <Command.h>
|
||||||
|
|
||||||
|
class CmdColumns : public Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CmdColumns ();
|
||||||
|
int execute (std::string&);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
|
@ -43,6 +43,7 @@
|
||||||
#include <CmdBurndown.h>
|
#include <CmdBurndown.h>
|
||||||
#include <CmdCalendar.h>
|
#include <CmdCalendar.h>
|
||||||
#include <CmdColor.h>
|
#include <CmdColor.h>
|
||||||
|
#include <CmdColumns.h>
|
||||||
#include <CmdCommands.h>
|
#include <CmdCommands.h>
|
||||||
#include <CmdConfig.h>
|
#include <CmdConfig.h>
|
||||||
#include <CmdCount.h>
|
#include <CmdCount.h>
|
||||||
|
@ -102,6 +103,7 @@ void Command::factory (std::map <std::string, Command*>& all)
|
||||||
c = new CmdBurndownWeekly (); all[c->keyword ()] = c;
|
c = new CmdBurndownWeekly (); all[c->keyword ()] = c;
|
||||||
c = new CmdCalendar (); all[c->keyword ()] = c;
|
c = new CmdCalendar (); all[c->keyword ()] = c;
|
||||||
c = new CmdColor (); all[c->keyword ()] = c;
|
c = new CmdColor (); all[c->keyword ()] = c;
|
||||||
|
c = new CmdColumns (); all[c->keyword ()] = c;
|
||||||
c = new CmdCompletionCommands (); all[c->keyword ()] = c;
|
c = new CmdCompletionCommands (); all[c->keyword ()] = c;
|
||||||
c = new CmdCompletionConfig (); all[c->keyword ()] = c;
|
c = new CmdCompletionConfig (); all[c->keyword ()] = c;
|
||||||
c = new CmdCompletionIds (); all[c->keyword ()] = c;
|
c = new CmdCompletionIds (); all[c->keyword ()] = c;
|
||||||
|
|
15
src/en-US.h
15
src/en-US.h
|
@ -155,6 +155,19 @@
|
||||||
#define STRING_COLUMN_LABEL_FG "Foreground color"
|
#define STRING_COLUMN_LABEL_FG "Foreground color"
|
||||||
#define STRING_COLUMN_LABEL_BG "Background color"
|
#define STRING_COLUMN_LABEL_BG "Background color"
|
||||||
#define STRING_COLUMN_LABEL_DATE "Date"
|
#define STRING_COLUMN_LABEL_DATE "Date"
|
||||||
|
#define STRING_COLUMN_LABEL_COLUMN "Columns"
|
||||||
|
#define STRING_COLUMN_LABEL_STYLES "Supported Formats"
|
||||||
|
#define STRING_COLUMN_LABEL_EXAMPLES "Example"
|
||||||
|
|
||||||
|
// Column Examples
|
||||||
|
#define STRING_COLUMN_EXAMPLES_TAGS "home @chore"
|
||||||
|
#define STRING_COLUMN_EXAMPLES_PROJ "home.garden"
|
||||||
|
#define STRING_COLUMN_EXAMPLES_PAR "home"
|
||||||
|
#define STRING_COLUMN_EXAMPLES_DESC "Move your clothes down on to the lower peg"
|
||||||
|
#define STRING_COLUMN_EXAMPLES_ANNO1 "Immediately before your lunch"
|
||||||
|
#define STRING_COLUMN_EXAMPLES_ANNO2 "If you are playing in the match this afternoon"
|
||||||
|
#define STRING_COLUMN_EXAMPLES_ANNO3 "Before you write your letter home"
|
||||||
|
#define STRING_COLUMN_EXAMPLES_ANNO4 "If you're not getting your hair cut"
|
||||||
|
|
||||||
// commands/Cmd*
|
// commands/Cmd*
|
||||||
#define STRING_CMD_CONFLICT "Custom report '{1}' conflicts with built-in task command."
|
#define STRING_CMD_CONFLICT "Custom report '{1}' conflicts with built-in task command."
|
||||||
|
@ -287,6 +300,8 @@
|
||||||
#define STRING_CMD_ANNO_DONE "Annotated {1} '{2}'"
|
#define STRING_CMD_ANNO_DONE "Annotated {1} '{2}'"
|
||||||
#define STRING_CMD_ANNO_SUMMARY "Annotated {1} task."
|
#define STRING_CMD_ANNO_SUMMARY "Annotated {1} task."
|
||||||
#define STRING_CMD_ANNO_SUMMARY_N "Annotated {1} tasks."
|
#define STRING_CMD_ANNO_SUMMARY_N "Annotated {1} tasks."
|
||||||
|
#define STRING_CMD_COLUMNS_USAGE "Displays supported columns and styles."
|
||||||
|
#define STRING_CMD_COLUMNS_NOTE "* Means default format, and therefore optionsl. For example, 'due' and 'due.formatted' are equivalent."
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
#define STRING_CONFIG_OVERNEST "Configuration file nested to more than 10 levels deep - this has to be a mistake."
|
#define STRING_CONFIG_OVERNEST "Configuration file nested to more than 10 levels deep - this has to be a mistake."
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue