Command - denotate

- Implemented denotate in the new style.
This commit is contained in:
Paul Beckingham 2011-08-02 00:56:29 -04:00
parent 8154222ef1
commit e5ae145df2
4 changed files with 51 additions and 42 deletions

View file

@ -41,7 +41,7 @@ extern Context context;
CmdAnnotate::CmdAnnotate () CmdAnnotate::CmdAnnotate ()
{ {
_keyword = "annotate"; _keyword = "annotate";
_usage = "task annotate ID desc..."; _usage = "task <filter> annotate <modifications>";
_description = STRING_CMD_ANNO_USAGE; _description = STRING_CMD_ANNO_USAGE;
_read_only = false; _read_only = false;
_displays_id = false; _displays_id = false;

View file

@ -25,10 +25,13 @@
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#define L10N // Localization complete.
#include <sstream> #include <sstream>
#include <Context.h> #include <Context.h>
#include <Permission.h> #include <Permission.h>
#include <text.h> #include <text.h>
#include <i18n.h>
#include <main.h> #include <main.h>
#include <CmdDenotate.h> #include <CmdDenotate.h>
@ -38,8 +41,8 @@ extern Context context;
CmdDenotate::CmdDenotate () CmdDenotate::CmdDenotate ()
{ {
_keyword = "denotate"; _keyword = "denotate";
_usage = "task denotate ID desc..."; _usage = "task <filter> denotate <pattern>";
_description = "Deletes an annotation from an existing task."; _description = STRING_CMD_DENO_USAGE;
_read_only = false; _read_only = false;
_displays_id = false; _displays_id = false;
} }
@ -48,52 +51,54 @@ CmdDenotate::CmdDenotate ()
int CmdDenotate::execute (std::string& output) int CmdDenotate::execute (std::string& output)
{ {
int rc = 0; int rc = 0;
int count = 0;
/*
if (!context.task.has ("description"))
throw std::string ("Description needed to delete an annotation.");
if (context.sequence.size () == 0)
throw std::string ("A task ID is needed to delete an annotation.");
bool sensitive = context.config.getBoolean ("search.case.sensitive");
std::stringstream out; std::stringstream out;
std::vector <Task> tasks; std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking")); context.tdb.lock (context.config.getBoolean ("locking"));
Filter filter; context.tdb.loadPending (tasks);
context.tdb.loadPending (tasks, filter);
context.filter.applySequence (tasks, context.sequence); // Apply filter.
if (tasks.size () == 0) std::vector <Task> filtered;
filter (tasks, filtered);
if (filtered.size () == 0)
{ {
context.footnote ("No tasks specified."); context.footnote (STRING_FEEDBACK_NO_TASKS_SP);
return 1; return 1;
} }
bool sensitive = context.config.getBoolean ("search.case.sensitive");
// Apply the command line modifications to the completed task.
A3 words = context.a3.extract_modifications ();
if (!words.size ())
throw std::string (STRING_CMD_DENO_WORDS);
std::string pattern = words.combine ();
Permission permission; Permission permission;
if (context.sequence.size () > (size_t) context.config.getInteger ("bulk")) if (filtered.size () > (size_t) context.config.getInteger ("bulk"))
permission.bigSequence (); permission.bigSequence ();
std::vector <Task>::iterator task; std::vector <Task>::iterator task;
for (task = tasks.begin (); task != tasks.end (); ++task) for (task = filtered.begin (); task != filtered.end (); ++task)
{ {
Task before (*task); Task before (*task);
std::string desc = context.task.get ("description");
std::vector <Att> annotations; std::vector <Att> annotations;
task->getAnnotations (annotations); task->getAnnotations (annotations);
if (annotations.size () == 0) if (annotations.size () == 0)
throw std::string ("The specified task has no annotations that can be deleted."); throw std::string (STRING_CMD_DENO_NONE);
std::vector <Att>::iterator i; std::vector <Att>::iterator i;
std::string anno; std::string anno;
bool match = false;; bool match = false;
for (i = annotations.begin (); i != annotations.end (); ++i) for (i = annotations.begin (); i != annotations.end (); ++i)
{ {
anno = i->value (); anno = i->value ();
if (anno == desc) if (anno == pattern)
{ {
match = true; match = true;
annotations.erase (i); annotations.erase (i);
@ -106,11 +111,10 @@ int CmdDenotate::execute (std::string& output)
for (i = annotations.begin (); i != annotations.end (); ++i) for (i = annotations.begin (); i != annotations.end (); ++i)
{ {
anno = i->value (); anno = i->value ();
std::string::size_type loc = find (anno, desc, sensitive); std::string::size_type loc = find (anno, pattern, sensitive);
if (loc != std::string::npos) if (loc != std::string::npos)
{ {
match = true;
annotations.erase (i); annotations.erase (i);
task->setAnnotations (annotations); task->setAnnotations (annotations);
break; break;
@ -123,26 +127,27 @@ int CmdDenotate::execute (std::string& output)
// Only allow valid tasks. // Only allow valid tasks.
task->validate (); task->validate ();
if (permission.confirmed (before, taskDifferences (before, *task) + "Proceed with change?")) if (permission.confirmed (before,
taskDifferences (before, *task) + STRING_CMD_DONE_PROCEED))
{ {
++count;
context.tdb.update (*task); context.tdb.update (*task);
if (context.config.getBoolean ("echo.command")) if (context.config.getBoolean ("echo.command"))
out << "Found annotation '" out << format (STRING_CMD_DENO_FOUND, anno)
<< anno << "\n";
<< "' and deleted it.\n";
} }
} }
else else
out << "Did not find any matching annotation to be deleted for '" out << format (STRING_CMD_DENO_NOMATCH, pattern)
<< desc << "\n";
<< "'.\n";
} }
context.tdb.commit (); if (count)
context.tdb.commit ();
context.tdb.unlock (); context.tdb.unlock ();
output = out.str (); output = out.str ();
*/
return rc; return rc;
} }

View file

@ -303,6 +303,11 @@
#define STRING_CMD_COLUMNS_USAGE "Displays supported columns and styles." #define STRING_CMD_COLUMNS_USAGE "Displays supported columns and styles."
#define STRING_CMD_COLUMNS_NOTE "* Means default format, and therefore optional. For example, 'due' and 'due.formatted' are equivalent." #define STRING_CMD_COLUMNS_NOTE "* Means default format, and therefore optional. For example, 'due' and 'due.formatted' are equivalent."
#define STRING_CMD_COLUMNS_USAGE2 "Displays only a list of supported columns." #define STRING_CMD_COLUMNS_USAGE2 "Displays only a list of supported columns."
#define STRING_CMD_DENO_USAGE "Deletes an annotation."
#define STRING_CMD_DENO_WORDS "An annotation pattern must be provided."
#define STRING_CMD_DENO_NONE "The specified task has no annotations that can be deleted."
#define STRING_CMD_DENO_FOUND "Found annotation '{1}' and deleted it."
#define STRING_CMD_DENO_NOMATCH "Did not find any matching annotation to be deleted for '{1}'."
// 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."

View file

@ -62,16 +62,15 @@ sleep 1;
qx{../src/task rc:denotate.rc 1 annotate Kermit and Miss Piggy}; qx{../src/task rc:denotate.rc 1 annotate Kermit and Miss Piggy};
my $output = qx{../src/task rc:denotate.rc rrr}; my $output = qx{../src/task rc:denotate.rc rrr};
like ($output, qr/1 one/, 'task 1'); like ($output, qr/1 one/, 'task 1');
like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Ernie/ms, 'first annotation'); like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Ernie/ms, 'first annotation');
like ($output, qr/Ernie.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'second annotation'); like ($output, qr/Ernie.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'second annotation');
like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Bibo/ms, 'third annotation'); like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Bibo/ms, 'third annotation'); # 5
like ($output, qr/Bibo.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'fourth annotation'); like ($output, qr/Bibo.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'fourth annotation');
like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'fifth annotation'); like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'fifth annotation');
like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit/ms, 'sixth annotation'); like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit/ms, 'sixth annotation');
like ($output, qr/Kermit.+\d{1,2}\/\d{1,2}\/\d{4} Kermit and Miss Piggy/ms, 'seventh annotation'); like ($output, qr/Kermit.+\d{1,2}\/\d{1,2}\/\d{4} Kermit and Miss Piggy/ms, 'seventh annotation');
like ($output, qr/1 task/, 'count'); like ($output, qr/1 task/, 'count'); # 10
qx{../src/task rc:denotate.rc 1 denotate Ernie}; qx{../src/task rc:denotate.rc 1 denotate Ernie};
$output = qx{../src/task rc:denotate.rc rrr}; $output = qx{../src/task rc:denotate.rc rrr};
@ -85,7 +84,7 @@ like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Kermit the
qx{../src/task rc:denotate.rc 1 denotate BErt}; qx{../src/task rc:denotate.rc 1 denotate BErt};
$output = qx{../src/task rc:denotate.rc rrr}; $output = qx{../src/task rc:denotate.rc rrr};
like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'Denotate is case sensitive'); like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'Denotate is case sensitive'); # 15
like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Kermit the frog still second annoation'); like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Kermit the frog still second annoation');
qx{../src/task rc:denotate.rc 1 denotate Kermit}; qx{../src/task rc:denotate.rc 1 denotate Kermit};
@ -93,7 +92,7 @@ $output = qx{../src/task rc:denotate.rc rrr};
like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'Exact match deletion - Bert'); like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'Exact match deletion - Bert');
like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Exact match deletion - Kermit the frog'); like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Exact match deletion - Kermit the frog');
like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Exact match deletion - Kermit the frog'); like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Exact match deletion - Kermit the frog');
like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit and Miss Piggy/ms, 'Exact match deletion - Kermit and Miss Piggy'); like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit and Miss Piggy/ms, 'Exact match deletion - Kermit and Miss Piggy'); # 20
qx{../src/task rc:denotate.rc 1 denotate Kermit the}; qx{../src/task rc:denotate.rc 1 denotate Kermit the};
$output = qx{../src/task rc:denotate.rc rrr}; $output = qx{../src/task rc:denotate.rc rrr};
@ -101,10 +100,10 @@ like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'Delet
like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Delete just one annotation - Kermit the frog'); like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Delete just one annotation - Kermit the frog');
like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit and Miss Piggy/ms, 'Delete just one annotation - Kermit and Miss Piggy'); like ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit and Miss Piggy/ms, 'Delete just one annotation - Kermit and Miss Piggy');
qx{../src/task rc:denotate.rc 1 denotate Kermit a}; $output = qx{../src/task rc:denotate.rc 1 denotate Kermit a};
$output = qx{../src/task rc:denotate.rc rrr}; $output = qx{../src/task rc:denotate.rc rrr};
like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'Delete partial match - Bert'); like ($output, qr/one.+\d{1,2}\/\d{1,2}\/\d{4} Bert/ms, 'Delete partial match - Bert');
like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Delete partial match - Kermit the frog'); like ($output, qr/Bert.+\d{1,2}\/\d{1,2}\/\d{4} Kermit the frog/ms, 'Delete partial match - Kermit the frog'); # 25
unlike ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit and Miss Piggy/ms, 'Delete partial match - Kermit and Miss Piggy'); unlike ($output, qr/frog.+\d{1,2}\/\d{1,2}\/\d{4} Kermit and Miss Piggy/ms, 'Delete partial match - Kermit and Miss Piggy');
# Cleanup. # Cleanup.