mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
- Added "task oldest" command
- Added "task newest" command
This commit is contained in:
parent
feb9959907
commit
0c17986303
6 changed files with 335 additions and 135 deletions
10
ChangeLog
10
ChangeLog
|
@ -11,13 +11,15 @@ Configurable columns in reports
|
|||
|
||||
------ reality -----------------------------------
|
||||
|
||||
1.3.0 (?)
|
||||
1.3.0 (6/18/2008)
|
||||
+ "task calendar" now displays multiple months per line, adjustable by the
|
||||
"monthsperline" configuration variable. Feature added by Damian Glenny
|
||||
+ "task export" can now filter tasks like the reports.
|
||||
+ Factored out code to filter tasks.
|
||||
+ "task export" can now filter tasks like the reports
|
||||
+ Factored out code to filter tasks
|
||||
+ Displays shorter message when a command is entered incorrectly, and the
|
||||
full usage for "task help".
|
||||
full usage for "task help"
|
||||
+ "task oldest" shows the oldest tasks
|
||||
+ "task newest" shows the newest tasks
|
||||
+ Bug: Segmentation fault when no "dateformat" configuration variable
|
||||
specified
|
||||
+ Bug: Fixed bug whereby if you have more than one task with a due date, 7
|
||||
|
|
22
TUTORIAL
22
TUTORIAL
|
@ -379,6 +379,22 @@ with no arguments will generate a help message that lists all these commands.
|
|||
|
||||
|
||||
|
||||
% task oldest
|
||||
-------------
|
||||
|
||||
Lists the oldest tasks. Shows 10 tasks by default, but can be set via the
|
||||
"oldest" configuration variable.
|
||||
|
||||
|
||||
|
||||
% task newest
|
||||
-------------
|
||||
|
||||
Lists the newest tasks. Shows 10 tasks by default, but can be set via the
|
||||
"newest" configuration variable.
|
||||
|
||||
|
||||
|
||||
% task history
|
||||
--------------
|
||||
|
||||
|
@ -691,6 +707,12 @@ Configuring Task
|
|||
monthsperline Determines how many months the "task calendar" command
|
||||
renders across the screen. Defaults to 1.
|
||||
|
||||
oldest Determines how many tasks are shown on the "oldest"
|
||||
report. Defaults to 10.
|
||||
|
||||
newest Determines how many tasks are shown on the "newest"
|
||||
report. Defaults to 10.
|
||||
|
||||
color May be "on" or "off". Determines whether task uses
|
||||
color.
|
||||
|
||||
|
|
|
@ -126,7 +126,9 @@ static const char* commands[] =
|
|||
"list",
|
||||
"long",
|
||||
"ls",
|
||||
"newest",
|
||||
"next",
|
||||
"oldest",
|
||||
"overdue",
|
||||
"projects",
|
||||
"start",
|
||||
|
|
416
src/task.cpp
416
src/task.cpp
|
@ -152,6 +152,14 @@ void shortUsage (Config& conf)
|
|||
table.addCell (row, 1, "task overdue");
|
||||
table.addCell (row, 2, "Shows all incomplete tasks that are beyond their due date");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task oldest");
|
||||
table.addCell (row, 2, "Shows the oldest tasks");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task newest");
|
||||
table.addCell (row, 2, "Shows the newest tasks");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task stats");
|
||||
table.addCell (row, 2, "Shows task database statistics");
|
||||
|
@ -183,137 +191,7 @@ void shortUsage (Config& conf)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
void longUsage (Config& conf)
|
||||
{
|
||||
Table table;
|
||||
int width = 80;
|
||||
#ifdef HAVE_LIBNCURSES
|
||||
if (conf.get ("curses", true))
|
||||
{
|
||||
WINDOW* w = initscr ();
|
||||
width = w->_maxx + 1;
|
||||
endwin ();
|
||||
}
|
||||
#endif
|
||||
|
||||
table.addColumn (" ");
|
||||
table.addColumn (" ");
|
||||
table.addColumn (" ");
|
||||
|
||||
table.setColumnJustification (0, Table::left);
|
||||
table.setColumnJustification (1, Table::left);
|
||||
table.setColumnJustification (2, Table::left);
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
table.setColumnWidth (2, Table::flexible);
|
||||
table.setTableWidth (width);
|
||||
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||
|
||||
int row = table.addRow ();
|
||||
table.addCell (row, 0, "Usage:");
|
||||
table.addCell (row, 1, "task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task add [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Adds a new task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task list [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Lists all tasks matching the specified criteria");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task long [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Lists all task, all data, matching the specified criteria");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task ls [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Minimal listing of all tasks matching the specified criteria");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task completed [tags] [attrs] desc...");
|
||||
table.addCell (row, 2, "Chronological listing of all completed tasks matching the specified criteria");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task ID [tags] [attrs] [desc...]");
|
||||
table.addCell (row, 2, "Modifies the existing task with provided arguments");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task ID /from/to/");
|
||||
table.addCell (row, 2, "Perform the substitution on the desc, for fixing mistakes");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task delete ID");
|
||||
table.addCell (row, 2, "Deletes the specified task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task info ID");
|
||||
table.addCell (row, 2, "Shows all data, metadata for specified task");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task start ID");
|
||||
table.addCell (row, 2, "Marks specified task as started, starts the clock ticking");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task done ID");
|
||||
table.addCell (row, 2, "Marks the specified task as completed");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task projects");
|
||||
table.addCell (row, 2, "Shows a list of all project names used, and how many tasks are in each");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task tags");
|
||||
table.addCell (row, 2, "Shows a list of all tags used");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task summary");
|
||||
table.addCell (row, 2, "Shows a report of task status by project");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task history");
|
||||
table.addCell (row, 2, "Shows a report of task history, by month");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task next");
|
||||
table.addCell (row, 2, "Shows the most important tasks for each project");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task calendar");
|
||||
table.addCell (row, 2, "Shows a monthly calendar, with due tasks marked");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task active");
|
||||
table.addCell (row, 2, "Shows all task that are started, but not completed");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task overdue");
|
||||
table.addCell (row, 2, "Shows all incomplete tasks that are beyond their due date");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task stats");
|
||||
table.addCell (row, 2, "Shows task database statistics");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task usage");
|
||||
table.addCell (row, 2, "Shows task command usage frequency");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task export");
|
||||
table.addCell (row, 2, "Exports all tasks as a CSV file");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task color");
|
||||
table.addCell (row, 2, "Displays all possible colors");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task version");
|
||||
table.addCell (row, 2, "Shows the task version number");
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 1, "task help");
|
||||
table.addCell (row, 2, "Shows the long usage text");
|
||||
|
||||
std::cout << table.render ()
|
||||
<< std::endl;
|
||||
shortUsage (conf);
|
||||
|
||||
std::cout
|
||||
<< "ID is the numeric identifier displayed by the 'task list' command" << "\n"
|
||||
|
@ -404,6 +282,8 @@ int main (int argc, char** argv)
|
|||
else if (command == "calendar") handleReportCalendar (tdb, task, conf);
|
||||
else if (command == "active") handleReportActive (tdb, task, conf);
|
||||
else if (command == "overdue") handleReportOverdue (tdb, task, conf);
|
||||
else if (command == "oldest") handleReportOldest (tdb, task, conf);
|
||||
else if (command == "newest") handleReportNewest (tdb, task, conf);
|
||||
else if (command == "stats") handleReportStats (tdb, task, conf);
|
||||
else if (command == "usage") handleReportUsage (tdb, task, conf);
|
||||
else if (command == "" && task.getId ()) handleModify (tdb, task, conf);
|
||||
|
@ -2212,6 +2092,280 @@ void handleReportOverdue (const TDB& tdb, T& task, Config& conf)
|
|||
std::cout << "No overdue tasks." << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Successively apply filters based on the task object built from the command
|
||||
// line. Tasks that match all the specified criteria are listed.
|
||||
void handleReportOldest (const TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
// Determine window size, and set table accordingly.
|
||||
int width = 80;
|
||||
#ifdef HAVE_LIBNCURSES
|
||||
if (conf.get ("curses", true))
|
||||
{
|
||||
WINDOW* w = initscr ();
|
||||
width = w->_maxx + 1;
|
||||
endwin ();
|
||||
}
|
||||
#endif
|
||||
|
||||
tdb.gc ();
|
||||
|
||||
// Get the pending tasks.
|
||||
std::vector <T> tasks;
|
||||
tdb.pendingT (tasks);
|
||||
|
||||
initializeColorRules (conf);
|
||||
|
||||
bool showAge = conf.get ("showage", true);
|
||||
unsigned int quantity = conf.get ("oldest", 10);
|
||||
|
||||
// Create a table for output.
|
||||
Table table;
|
||||
table.setTableWidth (width);
|
||||
table.addColumn ("ID");
|
||||
table.addColumn ("Project");
|
||||
table.addColumn ("Pri");
|
||||
table.addColumn ("Due");
|
||||
table.addColumn ("Active");
|
||||
if (showAge) table.addColumn ("Age");
|
||||
table.addColumn ("Description");
|
||||
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
table.setColumnUnderline (2);
|
||||
table.setColumnUnderline (3);
|
||||
table.setColumnUnderline (4);
|
||||
table.setColumnUnderline (5);
|
||||
if (showAge) table.setColumnUnderline (6);
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
table.setColumnWidth (2, Table::minimum);
|
||||
table.setColumnWidth (3, Table::minimum);
|
||||
table.setColumnWidth (4, Table::minimum);
|
||||
if (showAge) table.setColumnWidth (5, Table::minimum);
|
||||
table.setColumnWidth ((showAge ? 6 : 5), Table::flexible);
|
||||
|
||||
table.setColumnJustification (0, Table::right);
|
||||
table.setColumnJustification (3, Table::right);
|
||||
if (showAge) table.setColumnJustification (5, Table::right);
|
||||
|
||||
table.sortOn (3, Table::ascendingDate);
|
||||
table.sortOn (2, Table::descendingPriority);
|
||||
table.sortOn (1, Table::ascendingCharacter);
|
||||
|
||||
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||
|
||||
filter (tasks, task);
|
||||
for (unsigned int i = 0; i < min (quantity, tasks.size ()); ++i)
|
||||
{
|
||||
T refTask (tasks[i]);
|
||||
|
||||
// Now format the matching task.
|
||||
bool imminent = false;
|
||||
bool overdue = false;
|
||||
Date now;
|
||||
std::string due = refTask.getAttribute ("due");
|
||||
if (due.length ())
|
||||
{
|
||||
Date dt (::atoi (due.c_str ()));
|
||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||
|
||||
overdue = (dt < now) ? true : false;
|
||||
Date nextweek = now + 7 * 86400;
|
||||
imminent = dt < nextweek ? true : false;
|
||||
}
|
||||
|
||||
std::string active;
|
||||
if (refTask.getAttribute ("start") != "")
|
||||
active = "*";
|
||||
|
||||
std::string age;
|
||||
std::string created = refTask.getAttribute ("entry");
|
||||
if (created.length ())
|
||||
{
|
||||
Date dt (::atoi (created.c_str ()));
|
||||
formatTimeDeltaDays (age, (time_t) (now - dt));
|
||||
}
|
||||
|
||||
// All criteria match, so add refTask to the output table.
|
||||
int row = table.addRow ();
|
||||
table.addCell (row, 0, refTask.getId ());
|
||||
table.addCell (row, 1, refTask.getAttribute ("project"));
|
||||
table.addCell (row, 2, refTask.getAttribute ("priority"));
|
||||
table.addCell (row, 3, due);
|
||||
table.addCell (row, 4, active);
|
||||
if (showAge) table.addCell (row, 5, age);
|
||||
table.addCell (row, (showAge ? 6 : 5), refTask.getDescription ());
|
||||
|
||||
if (conf.get ("color", true))
|
||||
{
|
||||
Text::color fg = Text::colorCode (refTask.getAttribute ("fg"));
|
||||
Text::color bg = Text::colorCode (refTask.getAttribute ("bg"));
|
||||
autoColorize (refTask, fg, bg);
|
||||
table.setRowFg (row, fg);
|
||||
table.setRowBg (row, bg);
|
||||
|
||||
if (fg == Text::nocolor)
|
||||
{
|
||||
if (overdue)
|
||||
table.setCellFg (row, 3, Text::red);
|
||||
else if (imminent)
|
||||
table.setCellFg (row, 3, Text::yellow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (table.rowCount ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
<< table.render ()
|
||||
<< optionalBlankLine (conf)
|
||||
<< table.rowCount ()
|
||||
<< (table.rowCount () == 1 ? " task" : " tasks")
|
||||
<< std::endl;
|
||||
else
|
||||
std::cout << "No matches."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Successively apply filters based on the task object built from the command
|
||||
// line. Tasks that match all the specified criteria are listed.
|
||||
void handleReportNewest (const TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
// Determine window size, and set table accordingly.
|
||||
int width = 80;
|
||||
#ifdef HAVE_LIBNCURSES
|
||||
if (conf.get ("curses", true))
|
||||
{
|
||||
WINDOW* w = initscr ();
|
||||
width = w->_maxx + 1;
|
||||
endwin ();
|
||||
}
|
||||
#endif
|
||||
|
||||
tdb.gc ();
|
||||
|
||||
// Get the pending tasks.
|
||||
std::vector <T> tasks;
|
||||
tdb.pendingT (tasks);
|
||||
|
||||
initializeColorRules (conf);
|
||||
|
||||
bool showAge = conf.get ("showage", true);
|
||||
int quantity = conf.get ("newest", 10);
|
||||
|
||||
// Create a table for output.
|
||||
Table table;
|
||||
table.setTableWidth (width);
|
||||
table.addColumn ("ID");
|
||||
table.addColumn ("Project");
|
||||
table.addColumn ("Pri");
|
||||
table.addColumn ("Due");
|
||||
table.addColumn ("Active");
|
||||
if (showAge) table.addColumn ("Age");
|
||||
table.addColumn ("Description");
|
||||
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
table.setColumnUnderline (2);
|
||||
table.setColumnUnderline (3);
|
||||
table.setColumnUnderline (4);
|
||||
table.setColumnUnderline (5);
|
||||
if (showAge) table.setColumnUnderline (6);
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::minimum);
|
||||
table.setColumnWidth (2, Table::minimum);
|
||||
table.setColumnWidth (3, Table::minimum);
|
||||
table.setColumnWidth (4, Table::minimum);
|
||||
if (showAge) table.setColumnWidth (5, Table::minimum);
|
||||
table.setColumnWidth ((showAge ? 6 : 5), Table::flexible);
|
||||
|
||||
table.setColumnJustification (0, Table::right);
|
||||
table.setColumnJustification (3, Table::right);
|
||||
if (showAge) table.setColumnJustification (5, Table::right);
|
||||
|
||||
table.sortOn (3, Table::ascendingDate);
|
||||
table.sortOn (2, Table::descendingPriority);
|
||||
table.sortOn (1, Table::ascendingCharacter);
|
||||
|
||||
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
|
||||
|
||||
filter (tasks, task);
|
||||
int total = tasks.size ();
|
||||
for (int i = total - 1; i >= max (0, total - quantity); --i)
|
||||
{
|
||||
T refTask (tasks[i]);
|
||||
|
||||
// Now format the matching task.
|
||||
bool imminent = false;
|
||||
bool overdue = false;
|
||||
Date now;
|
||||
std::string due = refTask.getAttribute ("due");
|
||||
if (due.length ())
|
||||
{
|
||||
Date dt (::atoi (due.c_str ()));
|
||||
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
|
||||
|
||||
overdue = (dt < now) ? true : false;
|
||||
Date nextweek = now + 7 * 86400;
|
||||
imminent = dt < nextweek ? true : false;
|
||||
}
|
||||
|
||||
std::string active;
|
||||
if (refTask.getAttribute ("start") != "")
|
||||
active = "*";
|
||||
|
||||
std::string age;
|
||||
std::string created = refTask.getAttribute ("entry");
|
||||
if (created.length ())
|
||||
{
|
||||
Date dt (::atoi (created.c_str ()));
|
||||
formatTimeDeltaDays (age, (time_t) (now - dt));
|
||||
}
|
||||
|
||||
// All criteria match, so add refTask to the output table.
|
||||
int row = table.addRow ();
|
||||
table.addCell (row, 0, refTask.getId ());
|
||||
table.addCell (row, 1, refTask.getAttribute ("project"));
|
||||
table.addCell (row, 2, refTask.getAttribute ("priority"));
|
||||
table.addCell (row, 3, due);
|
||||
table.addCell (row, 4, active);
|
||||
if (showAge) table.addCell (row, 5, age);
|
||||
table.addCell (row, (showAge ? 6 : 5), refTask.getDescription ());
|
||||
|
||||
if (conf.get ("color", true))
|
||||
{
|
||||
Text::color fg = Text::colorCode (refTask.getAttribute ("fg"));
|
||||
Text::color bg = Text::colorCode (refTask.getAttribute ("bg"));
|
||||
autoColorize (refTask, fg, bg);
|
||||
table.setRowFg (row, fg);
|
||||
table.setRowBg (row, bg);
|
||||
|
||||
if (fg == Text::nocolor)
|
||||
{
|
||||
if (overdue)
|
||||
table.setCellFg (row, 3, Text::red);
|
||||
else if (imminent)
|
||||
table.setCellFg (row, 3, Text::yellow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (table.rowCount ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
<< table.render ()
|
||||
<< optionalBlankLine (conf)
|
||||
<< table.rowCount ()
|
||||
<< (table.rowCount () == 1 ? " task" : " tasks")
|
||||
<< std::endl;
|
||||
else
|
||||
std::cout << "No matches."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleReportStats (const TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#include "T.h"
|
||||
#include "../auto.h"
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
@ -69,6 +73,8 @@ void handleReportCalendar (const TDB&, T&, Config&);
|
|||
void handleReportActive (const TDB&, T&, Config&);
|
||||
void handleReportOverdue (const TDB&, T&, Config&);
|
||||
void handleReportStats (const TDB&, T&, Config&);
|
||||
void handleReportOldest (const TDB&, T&, Config&);
|
||||
void handleReportNewest (const TDB&, T&, Config&);
|
||||
void handleVersion (Config&);
|
||||
void handleExport (const TDB&, T&, Config&);
|
||||
void handleDelete (const TDB&, T&, Config&);
|
||||
|
|
14
task.html
14
task.html
|
@ -182,6 +182,8 @@ a img { border: none; padding: 0; margin: 0; }
|
|||
<li>Displays shorter message when a command is entered incorrectly,
|
||||
and the full usage for "task help"
|
||||
<li>"task export" can now filter tasks like the reports
|
||||
<li>"task oldest" shows the oldest tasks
|
||||
<li>"task newest" shows the newest tasks
|
||||
<li>Fixed bug where task generates a segmentation fault for several
|
||||
commands, when no "dateformat" configuration variable was present
|
||||
<li>Fixed bug whereby if you have more than one task with a due date,
|
||||
|
@ -760,6 +762,18 @@ ID Project Pri Description
|
|||
12 Errand L Remember to deposit bonus check
|
||||
...</code></pre>
|
||||
|
||||
<strong>% task oldest</strong>
|
||||
<p>
|
||||
Lists the oldest tasks. Shows 10 tasks by default, but can be
|
||||
set via the "oldest" configuration variable.
|
||||
</p>
|
||||
|
||||
<strong>% task newest</strong>
|
||||
<p>
|
||||
Lists the newest tasks. Shows 10 tasks by default, but can be
|
||||
set via the "newest" configuration variable.
|
||||
</p>
|
||||
|
||||
<strong>% task /from/to/</strong>
|
||||
<p>
|
||||
If a task has been entered with a typo, it can be easily corrected
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue