- Added feature #546, which is a 'count' command that counts tasks, and is
  intended to help scripts that manipulate task output.
- Added unit tests.
- Added man page description.
This commit is contained in:
Paul Beckingham 2010-11-26 10:39:00 -05:00
parent 4c40784328
commit d7de67d242
10 changed files with 129 additions and 0 deletions

View file

@ -5,6 +5,8 @@
+ Added burndown charts - burndown.daily, burndown.weekly, burndown.monthly, + Added burndown charts - burndown.daily, burndown.weekly, burndown.monthly,
that use color.burndown.pending, color.burndown.started and that use color.burndown.pending, color.burndown.started and
color.burndown.done colors. color.burndown.done colors.
+ Added feature #546, which is a 'count' command that counts tasks, and is
intended to help scripts that manipulate task output.
+ Fixed bug #529, where the 'depends' attribute was not mentioned in the + Fixed bug #529, where the 'depends' attribute was not mentioned in the
task man page (thanks to Dirk Deimeke). task man page (thanks to Dirk Deimeke).
+ Fixed bug #535 which omitted the holidays-NO.rc file from the packages + Fixed bug #535 which omitted the holidays-NO.rc file from the packages

3
NEWS
View file

@ -2,6 +2,7 @@
New Features in taskwarrior 1.9.4 New Features in taskwarrior 1.9.4
- New burndown charts. - New burndown charts.
- New 'count' helper command.
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.
@ -10,6 +11,8 @@ New commands in taskwarrior 1.9.4
- 'burndown.daily', 'burndown.weekly', 'burndown.monthly', also with - 'burndown.daily', 'burndown.weekly', 'burndown.monthly', also with
'burndown' that is an alias to burndown.weekly. 'burndown' that is an alias to burndown.weekly.
- 'count' accepts a filter, and simply returns a count of the tasks
matching the filter. Used as a helper command by scripts.
New configuration options in taskwarrior 1.9.4 New configuration options in taskwarrior 1.9.4

View file

@ -188,6 +188,10 @@ Overwrites the task database with those files found at the URL.
Displays all possible colors, a named sample, or a legend containing all Displays all possible colors, a named sample, or a legend containing all
currently defined colors. currently defined colors.
.TP
.B count [filter]
Displays only a count of tasks matching the filter.
.TP .TP
.B version .B version
Shows the taskwarrior version number Shows the taskwarrior version number

View file

@ -145,6 +145,7 @@ void Cmd::load ()
commands.push_back ("burndown.daily"); commands.push_back ("burndown.daily");
commands.push_back ("burndown.weekly"); commands.push_back ("burndown.weekly");
commands.push_back ("burndown.monthly"); commands.push_back ("burndown.monthly");
commands.push_back ("count");
// Commands whose names are localized. // Commands whose names are localized.
commands.push_back (context.stringtable.get (CMD_ADD, "add")); commands.push_back (context.stringtable.get (CMD_ADD, "add"));
@ -250,6 +251,7 @@ bool Cmd::isReadOnlyCommand ()
command == "burndown.daily" || command == "burndown.daily" ||
command == "burndown.weekly" || command == "burndown.weekly" ||
command == "burndown.monthly" || command == "burndown.monthly" ||
command == "count" ||
command == context.stringtable.get (CMD_CALENDAR, "calendar") || command == context.stringtable.get (CMD_CALENDAR, "calendar") ||
command == context.stringtable.get (CMD_COLORS, "colors") || command == context.stringtable.get (CMD_COLORS, "colors") ||
command == context.stringtable.get (CMD_DIAGNOSTICS, "diagnostics") || command == context.stringtable.get (CMD_DIAGNOSTICS, "diagnostics") ||

View file

@ -249,6 +249,7 @@ int Context::dispatch (std::string &out)
else if (cmd.command == "push") { handlePush (out); } else if (cmd.command == "push") { handlePush (out); }
else if (cmd.command == "pull") { handlePull (out); } else if (cmd.command == "pull") { handlePull (out); }
else if (cmd.command == "diagnostics") { handleDiagnostics (out); } else if (cmd.command == "diagnostics") { handleDiagnostics (out); }
else if (cmd.command == "count") { rc = handleCount (out); }
else if (cmd.command == "_projects") { rc = handleCompletionProjects (out); } else if (cmd.command == "_projects") { rc = handleCompletionProjects (out); }
else if (cmd.command == "_tags") { rc = handleCompletionTags (out); } else if (cmd.command == "_tags") { rc = handleCompletionTags (out); }
else if (cmd.command == "_commands") { rc = handleCompletionCommands (out); } else if (cmd.command == "_commands") { rc = handleCompletionCommands (out); }

View file

@ -147,6 +147,8 @@ Hooks::Hooks ()
validProgramEvents.push_back ("post-done-command"); validProgramEvents.push_back ("post-done-command");
validProgramEvents.push_back ("pre-duplicate-command"); validProgramEvents.push_back ("pre-duplicate-command");
validProgramEvents.push_back ("post-duplicate-command"); validProgramEvents.push_back ("post-duplicate-command");
validProgramEvents.push_back ("pre-count-command");
validProgramEvents.push_back ("post-count-command");
validProgramEvents.push_back ("pre-edit-command"); validProgramEvents.push_back ("pre-edit-command");
validProgramEvents.push_back ("post-edit-command"); validProgramEvents.push_back ("post-edit-command");
validProgramEvents.push_back ("pre-export-command"); validProgramEvents.push_back ("pre-export-command");

View file

@ -2032,6 +2032,37 @@ int handleDuplicate (std::string& outs)
return rc; return rc;
} }
////////////////////////////////////////////////////////////////////////////////
int handleCount (std::string& outs)
{
int rc = 0;
if (context.hooks.trigger ("pre-count-command"))
{
// Scan the pending tasks, applying any filter.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
// Find number of matching tasks. Skip recurring parent tasks.
int count = 0;
std::vector <Task>::iterator it;
for (it = tasks.begin (); it != tasks.end (); ++it)
if (it->getStatus () != Task::recurring)
++count;
std::stringstream out;
out << count << "\n";
outs = out.str ();
context.hooks.trigger ("post-count-command");
}
return rc;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifdef FEATURE_SHELL #ifdef FEATURE_SHELL
void handleShell () void handleShell ()

View file

@ -78,6 +78,7 @@ int handleColor (std::string&);
int handleAnnotate (std::string&); int handleAnnotate (std::string&);
int handleDenotate (std::string&); int handleDenotate (std::string&);
int handleDuplicate (std::string&); int handleDuplicate (std::string&);
int handleCount (std::string&);
void handleUndo (); void handleUndo ();
void handleMerge (std::string&); void handleMerge (std::string&);
void handlePush (std::string&); void handlePush (std::string&);

View file

@ -244,6 +244,10 @@ int shortUsage (std::string& outs)
table.addCell (row, 2, "Displays all possible colors, a named sample, or a " table.addCell (row, 2, "Displays all possible colors, a named sample, or a "
"legend containing all currently defined colors."); "legend containing all currently defined colors.");
row = table.addRow ();
table.addCell (row, 1, "task count [filter]");
table.addCell (row, 2, "Shows only the number of matching tasks.");
row = table.addRow (); row = table.addRow ();
table.addCell (row, 1, "task version"); table.addCell (row, 1, "task version");
table.addCell (row, 2, "Shows the task version number."); table.addCell (row, 2, "Shows the task version number.");

79
src/tests/count.t Executable file
View file

@ -0,0 +1,79 @@
#! /usr/bin/perl
################################################################################
## taskwarrior - a command line task list manager.
##
## Copyright 2010, 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
##
################################################################################
use strict;
use warnings;
use Test::More tests => 10;
# Create the rc file.
if (open my $fh, '>', 'count.rc')
{
print $fh "data.location=.\n",
"confirmation=off\n";
close $fh;
ok (-r 'count.rc', 'Created count.rc');
}
# Test the count command.
qx{../task rc:count.rc add one};
qx{../task rc:count.rc log two};
qx{../task rc:count.rc add three};
qx{../task rc:count.rc delete 3};
qx{../task rc:count.rc add four wait:eom};
qx{../task rc:count.rc add five due:eom recur:monthly};
my $output = qx{../task rc:count.rc count};
like ($output, qr/^5$/ms, 'count');
$output = qx{../task rc:count.rc count status:deleted};
like ($output, qr/^1$/ms, 'count status:deleted');
$output = qx{../task rc:count.rc count e};
like ($output, qr/^3$/ms, 'count e');
$output = qx{../task rc:count.rc count description.startswith:f};
like ($output, qr/^2$/ms, 'count description.startswith:f');
$output = qx{../task rc:count.rc count due.any:};
like ($output, qr/^1$/ms, 'count due.any:');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'undo.data';
ok (!-r 'undo.data', 'Removed undo.data');
unlink 'count.rc';
ok (!-r 'count.rc', 'Removed count.rc');
exit 0;