- 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:
Paul Beckingham 2011-07-16 13:08:23 -04:00
parent 3a5370ddf1
commit 27a04b29f5
28 changed files with 372 additions and 64 deletions

View file

@ -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
View file

@ -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.

View file

@ -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)
{ {

View file

@ -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;

View file

@ -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)

View file

@ -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)

View file

@ -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")
{
}
} }
} }

View file

@ -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;

View file

@ -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");

View file

@ -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 ());
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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);

View file

@ -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)));
} }

View file

@ -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"));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -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;

View file

@ -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)");
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -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;

View file

@ -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")

View file

@ -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)));
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -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

View file

@ -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

View 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
View 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
////////////////////////////////////////////////////////////////////////////////

View file

@ -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;

View file

@ -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."