- Removed all obsolete hooks, except from commands.cpp, which is being
  worked on in parallel.
- Implemented new on-launch and on-exit unit tests.
This commit is contained in:
Paul Beckingham 2011-04-17 21:09:58 -04:00
parent 2f4efb28d6
commit 48eb4757f8
15 changed files with 2816 additions and 3246 deletions

View file

@ -124,7 +124,7 @@ void Context::initialize (int argc, char** argv)
// Hook system init, plus post-start event occurring at the first possible
// moment after hook initialization.
hooks.initialize ();
hooks.trigger ("post-start");
hooks.trigger ("on-launch");
}
////////////////////////////////////////////////////////////////////////////////
@ -189,41 +189,33 @@ int Context::run ()
}
// Dump all debug messages.
hooks.trigger ("pre-debug");
if (config.getBoolean ("debug"))
foreach (d, debugMessages)
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
std::cout << colorizeDebug (*d) << "\n";
else
std::cout << *d << "\n";
hooks.trigger ("post-debug");
// Dump all headers.
hooks.trigger ("pre-header");
if (config.getBoolean ("verbose"))
foreach (h, headers)
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
std::cout << colorizeHeader (*h) << "\n";
else
std::cout << *h << "\n";
hooks.trigger ("post-header");
// Dump the report output.
hooks.trigger ("pre-output");
std::cout << output;
hooks.trigger ("post-output");
// Dump all footnotes.
hooks.trigger ("pre-footnote");
if (config.getBoolean ("verbose"))
foreach (f, footnotes)
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
std::cout << colorizeFootnote (*f) << "\n";
else
std::cout << *f << "\n";
hooks.trigger ("post-footnote");
hooks.trigger ("pre-exit");
hooks.trigger ("on-exit");
return rc;
}
@ -234,8 +226,6 @@ int Context::dispatch (std::string &out)
Timer t ("Context::dispatch");
hooks.trigger ("pre-dispatch");
// For read-only commands, optionally update the xterm window title.
// Why just the read-only commands? Because this capability is to answer the
// question of 'what did I just do to generate this outout?'.
@ -310,15 +300,12 @@ int Context::dispatch (std::string &out)
rc = handleCustomReport (cmd.command, out); }
// If the command is not recognized, display usage.
else { hooks.trigger ("pre-usage-command");
rc = shortUsage (out);
hooks.trigger ("post-usage-command"); }
else { rc = shortUsage (out); }
// Only update the shadow file if such an update was not suppressed (shadow),
if (cmd.isWriteCommand () && !inShadow)
shadow ();
hooks.trigger ("post-dispatch");
return rc;
}

View file

@ -73,208 +73,19 @@ Hook& Hook::operator= (const Hook& other)
////////////////////////////////////////////////////////////////////////////////
Hooks::Hooks ()
{
/*
// New 2.x hooks.
validTaskEvents.push_back ("on-task-add");
validTaskEvents.push_back ("on-task-modify");
validTaskEvents.push_back ("on-task-complete");
validTaskEvents.push_back ("on-task-delete");
validTaskEvents.push_back ("on-task-add"); // Unimplemented
validTaskEvents.push_back ("on-task-modify"); // Unimplemented
validTaskEvents.push_back ("on-task-complete"); // Unimplemented
validTaskEvents.push_back ("on-task-delete"); // Unimplemented
validProgramEvents.push_back ("on-launch");
validProgramEvents.push_back ("on-exit");
validProgramEvents.push_back ("on-file-read");
validProgramEvents.push_back ("on-file-write");
validProgramEvents.push_back ("on-synch");
validProgramEvents.push_back ("on-gc");
*/
// Obsolete 1.x hooks.
validProgramEvents.push_back ("post-start");
validProgramEvents.push_back ("pre-exit");
validProgramEvents.push_back ("pre-file-read");
validProgramEvents.push_back ("post-file-read");
validProgramEvents.push_back ("pre-file-write");
validProgramEvents.push_back ("post-file-write");
validProgramEvents.push_back ("pre-gc");
validProgramEvents.push_back ("post-gc");
validProgramEvents.push_back ("post-commit");
validProgramEvents.push_back ("pre-fatal-error");
validProgramEvents.push_back ("pre-command-line");
validProgramEvents.push_back ("post-command-line");
validProgramEvents.push_back ("pre-command-line-override");
validProgramEvents.push_back ("post-command-line-override");
validProgramEvents.push_back ("pre-config-create");
validProgramEvents.push_back ("post-config-create");
validProgramEvents.push_back ("pre-config-read");
validProgramEvents.push_back ("post-config-read");
validProgramEvents.push_back ("pre-config-value-read");
validProgramEvents.push_back ("post-config-value-read");
validProgramEvents.push_back ("pre-config-value-write");
validProgramEvents.push_back ("post-config-value-write");
validProgramEvents.push_back ("pre-file-lock");
validProgramEvents.push_back ("post-file-lock");
validProgramEvents.push_back ("pre-file-unlock");
validProgramEvents.push_back ("post-file-unlock");
validProgramEvents.push_back ("pre-output");
validProgramEvents.push_back ("post-output");
validProgramEvents.push_back ("pre-debug");
validProgramEvents.push_back ("post-debug");
validProgramEvents.push_back ("pre-header");
validProgramEvents.push_back ("post-header");
validProgramEvents.push_back ("pre-footnote");
validProgramEvents.push_back ("post-footnote");
validProgramEvents.push_back ("pre-dispatch");
validProgramEvents.push_back ("post-dispatch");
validProgramEvents.push_back ("pre-archive");
validProgramEvents.push_back ("post-archive");
validProgramEvents.push_back ("pre-purge");
validProgramEvents.push_back ("post-purge");
validProgramEvents.push_back ("pre-recurrence");
validProgramEvents.push_back ("post-recurrence");
validProgramEvents.push_back ("pre-interactive");
validProgramEvents.push_back ("post-interactive");
validProgramEvents.push_back ("pre-undo");
validProgramEvents.push_back ("post-undo");
validProgramEvents.push_back ("pre-confirm");
validProgramEvents.push_back ("post-confirm");
validProgramEvents.push_back ("pre-shell-prompt");
validProgramEvents.push_back ("post-shell-prompt");
validProgramEvents.push_back ("pre-add-command");
validProgramEvents.push_back ("post-add-command");
validProgramEvents.push_back ("pre-annotate-command");
validProgramEvents.push_back ("post-annotate-command");
validProgramEvents.push_back ("pre-denotate-command");
validProgramEvents.push_back ("post-denotate-command");
validProgramEvents.push_back ("pre-append-command");
validProgramEvents.push_back ("post-append-command");
validProgramEvents.push_back ("pre-calendar-command");
validProgramEvents.push_back ("post-calendar-command");
validProgramEvents.push_back ("pre-color-command");
validProgramEvents.push_back ("post-color-command");
validProgramEvents.push_back ("pre-config-command");
validProgramEvents.push_back ("post-config-command");
validProgramEvents.push_back ("pre-custom-report-command");
validProgramEvents.push_back ("post-custom-report-command");
validProgramEvents.push_back ("pre-default-command");
validProgramEvents.push_back ("post-default-command");
validProgramEvents.push_back ("pre-delete-command");
validProgramEvents.push_back ("post-delete-command");
validProgramEvents.push_back ("pre-done-command");
validProgramEvents.push_back ("post-done-command");
validProgramEvents.push_back ("pre-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 ("post-edit-command");
validProgramEvents.push_back ("pre-export-command");
validProgramEvents.push_back ("post-export-command");
validProgramEvents.push_back ("pre-ghistory-command");
validProgramEvents.push_back ("post-ghistory-command");
validProgramEvents.push_back ("pre-history-command");
validProgramEvents.push_back ("post-history-command");
validProgramEvents.push_back ("pre-burndown-command");
validProgramEvents.push_back ("post-burndown-command");
validProgramEvents.push_back ("pre-import-command");
validProgramEvents.push_back ("post-import-command");
validProgramEvents.push_back ("pre-info-command");
validProgramEvents.push_back ("post-info-command");
validProgramEvents.push_back ("pre-merge-command");
validProgramEvents.push_back ("post-merge-command");
validProgramEvents.push_back ("pre-modify-command");
validProgramEvents.push_back ("post-modify-command");
validProgramEvents.push_back ("pre-prepend-command");
validProgramEvents.push_back ("post-prepend-command");
validProgramEvents.push_back ("pre-projects-command");
validProgramEvents.push_back ("post-projects-command");
validProgramEvents.push_back ("pre-pull-command");
validProgramEvents.push_back ("post-pull-command");
validProgramEvents.push_back ("pre-push-command");
validProgramEvents.push_back ("post-push-command");
validProgramEvents.push_back ("pre-shell-command");
validProgramEvents.push_back ("post-shell-command");
validProgramEvents.push_back ("pre-start-command");
validProgramEvents.push_back ("post-start-command");
validProgramEvents.push_back ("pre-stats-command");
validProgramEvents.push_back ("post-stats-command");
validProgramEvents.push_back ("pre-stop-command");
validProgramEvents.push_back ("post-stop-command");
validProgramEvents.push_back ("pre-summary-command");
validProgramEvents.push_back ("post-summary-command");
validProgramEvents.push_back ("pre-tags-command");
validProgramEvents.push_back ("post-tags-command");
validProgramEvents.push_back ("pre-timesheet-command");
validProgramEvents.push_back ("post-timesheet-command");
validProgramEvents.push_back ("pre-undo-command");
validProgramEvents.push_back ("post-undo-command");
validProgramEvents.push_back ("pre-usage-command");
validProgramEvents.push_back ("post-usage-command");
validProgramEvents.push_back ("pre-version-command");
validProgramEvents.push_back ("post-version-command");
validTaskEvents.push_back ("pre-display");
validTaskEvents.push_back ("pre-modification");
validTaskEvents.push_back ("post-modification");
validTaskEvents.push_back ("pre-delete");
validTaskEvents.push_back ("post-delete");
validTaskEvents.push_back ("pre-add");
validTaskEvents.push_back ("post-add");
validTaskEvents.push_back ("pre-undo");
validTaskEvents.push_back ("post-undo");
validTaskEvents.push_back ("pre-wait");
validTaskEvents.push_back ("post-wait");
validTaskEvents.push_back ("pre-unwait");
validTaskEvents.push_back ("post-unwait");
validTaskEvents.push_back ("pre-completed");
validTaskEvents.push_back ("post-completed");
validTaskEvents.push_back ("pre-priority-change");
validTaskEvents.push_back ("post-priority-change");
validTaskEvents.push_back ("pre-project-change");
validTaskEvents.push_back ("post-project-change");
validTaskEvents.push_back ("pre-substitution");
validTaskEvents.push_back ("post-substitution");
validTaskEvents.push_back ("pre-annotation");
validTaskEvents.push_back ("post-annotation");
validTaskEvents.push_back ("pre-tag");
validTaskEvents.push_back ("post-tag");
validTaskEvents.push_back ("pre-detag");
validTaskEvents.push_back ("post-detag");
validTaskEvents.push_back ("pre-colorization");
validTaskEvents.push_back ("post-colorization");
validFieldEvents.push_back ("format-number");
validFieldEvents.push_back ("format-date");
validFieldEvents.push_back ("format-duration");
validFieldEvents.push_back ("format-text");
validFieldEvents.push_back ("format-id");
validFieldEvents.push_back ("format-uuid");
validFieldEvents.push_back ("format-project");
validFieldEvents.push_back ("format-priority");
validFieldEvents.push_back ("format-priority_long");
validFieldEvents.push_back ("format-entry");
validFieldEvents.push_back ("format-start");
validFieldEvents.push_back ("format-end");
validFieldEvents.push_back ("format-due");
validFieldEvents.push_back ("format-countdown");
validFieldEvents.push_back ("format-countdown_compact");
validFieldEvents.push_back ("format-age");
validFieldEvents.push_back ("format-age_compact");
validFieldEvents.push_back ("format-active");
validFieldEvents.push_back ("format-tags");
validFieldEvents.push_back ("format-recur");
validFieldEvents.push_back ("format-recurrence_indicator");
validFieldEvents.push_back ("format-tag_indicator");
validFieldEvents.push_back ("format-description_only");
validFieldEvents.push_back ("format-description");
validFieldEvents.push_back ("format-wait");
validFieldEvents.push_back ("format-prompt");
validFieldEvents.push_back ("format-depends");
validProgramEvents.push_back ("on-file-read"); // Unimplemented
validProgramEvents.push_back ("on-file-write"); // Unimplemented
validProgramEvents.push_back ("on-synch"); // Unimplemented
validProgramEvents.push_back ("on-merge"); // Unimplemented
validProgramEvents.push_back ("on-gc"); // Unimplemented
}
////////////////////////////////////////////////////////////////////////////////
@ -395,36 +206,6 @@ bool Hooks::trigger (const std::string& event, Task& task)
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Field hooks.
bool Hooks::trigger (
const std::string& event,
const std::string& name,
std::string& value)
{
#ifdef HAVE_LIBLUA
std::vector <Hook>::iterator it;
for (it = all.begin (); it != all.end (); ++it)
{
if (it->event == event)
{
Timer timer (std::string ("Hooks::trigger ") + event);
if (validFieldEvent (event))
{
context.debug (std::string ("Event ") + event + " triggered");
if (! api.callFieldHook (it->file, it->function, name, value))
return false;
}
else
throw std::string ("Unrecognized hook event '") + event + "'.";
}
}
#endif
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool Hooks::validProgramEvent (const std::string& event)
{
@ -442,12 +223,4 @@ bool Hooks::validTaskEvent (const std::string& event)
return false;
}
bool Hooks::validFieldEvent (const std::string& event)
{
if (std::find (validFieldEvents.begin (), validFieldEvents.end (), event) != validFieldEvents.end ())
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -60,12 +60,10 @@ public:
bool trigger (const std::string&); // Program
bool trigger (const std::string&, Task&); // Task
bool trigger (const std::string&, const std::string&, std::string&); // Field
private:
bool validProgramEvent (const std::string&);
bool validTaskEvent (const std::string&);
bool validFieldEvent (const std::string&);
private:
#ifdef HAVE_LIBLUA
@ -75,7 +73,6 @@ private:
std::vector <std::string> validProgramEvents;
std::vector <std::string> validTaskEvents;
std::vector <std::string> validFieldEvents;
};
#endif

View file

@ -191,25 +191,21 @@ void TDB::location (const std::string& path)
////////////////////////////////////////////////////////////////////////////////
void TDB::lock (bool lockFile /* = true */)
{
if (context.hooks.trigger ("pre-file-lock"))
mLock = lockFile;
mPending.clear ();
mNew.clear ();
mCompleted.clear ();
mModified.clear ();
foreach (location, mLocations)
{
mLock = lockFile;
mPending.clear ();
mNew.clear ();
mCompleted.clear ();
mModified.clear ();
foreach (location, mLocations)
{
location->pending = openAndLock (location->path + "/pending.data");
location->completed = openAndLock (location->path + "/completed.data");
location->undo = openAndLock (location->path + "/undo.data");
}
mAllOpenAndLocked = true;
context.hooks.trigger ("post-file-lock");
location->pending = openAndLock (location->path + "/pending.data");
location->completed = openAndLock (location->path + "/completed.data");
location->undo = openAndLock (location->path + "/undo.data");
}
mAllOpenAndLocked = true;
}
////////////////////////////////////////////////////////////////////////////////
@ -492,7 +488,6 @@ void TDB::update (const Task& task)
int TDB::commit ()
{
Timer t ("TDB::commit");
context.hooks.trigger ("pre-commit");
int quantity = mNew.size () + mModified.size ();
@ -512,7 +507,6 @@ int TDB::commit ()
writeUndo (*task, mLocations[0].undo);
mNew.clear ();
context.hooks.trigger ("post-commit");
return quantity;
}
@ -579,7 +573,6 @@ int TDB::commit ()
mNew.clear ();
}
context.hooks.trigger ("post-commit");
return quantity;
}
@ -713,7 +706,6 @@ int TDB::nextId ()
////////////////////////////////////////////////////////////////////////////////
void TDB::undo ()
{
context.hooks.trigger ("pre-undo");
Directory location (context.config.get ("data.location"));
std::string undoFile = location.data + "/undo.data";
@ -997,7 +989,6 @@ void TDB::undo ()
!confirm ("The undo command is not reversible. Are you sure you want to revert to the previous state?"))
{
std::cout << "No changes made.\n";
context.hooks.trigger ("post-undo");
return;
}
@ -1035,7 +1026,6 @@ void TDB::undo ()
// Rewrite files.
File::write (pendingFile, p);
File::write (undoFile, u);
context.hooks.trigger ("post-undo");
return;
}
}
@ -1074,7 +1064,6 @@ void TDB::undo ()
}
std::cout << "Undo complete.\n";
context.hooks.trigger ("post-undo");
return;
}
}

View file

@ -341,25 +341,21 @@ void TDB::location (const std::string& path)
////////////////////////////////////////////////////////////////////////////////
void TDB::lock (bool lockFile /* = true */)
{
if (context.hooks.trigger ("pre-file-lock"))
mLock = lockFile;
mPending.clear ();
mNew.clear ();
mCompleted.clear ();
mModified.clear ();
foreach (location, mLocations)
{
mLock = lockFile;
mPending.clear ();
mNew.clear ();
mCompleted.clear ();
mModified.clear ();
foreach (location, mLocations)
{
location->pending = openAndLock (location->path + "/pending.data");
location->completed = openAndLock (location->path + "/completed.data");
location->undo = openAndLock (location->path + "/undo.data");
}
mAllOpenAndLocked = true;
context.hooks.trigger ("post-file-lock");
location->pending = openAndLock (location->path + "/pending.data");
location->completed = openAndLock (location->path + "/completed.data");
location->undo = openAndLock (location->path + "/undo.data");
}
mAllOpenAndLocked = true;
}
////////////////////////////////////////////////////////////////////////////////
@ -642,7 +638,6 @@ void TDB::update (const Task& task)
int TDB::commit ()
{
Timer t ("TDB::commit");
context.hooks.trigger ("pre-commit");
int quantity = mNew.size () + mModified.size ();
@ -662,7 +657,6 @@ int TDB::commit ()
writeUndo (*task, mLocations[0].undo);
mNew.clear ();
context.hooks.trigger ("post-commit");
return quantity;
}
@ -729,7 +723,6 @@ int TDB::commit ()
mNew.clear ();
}
context.hooks.trigger ("post-commit");
return quantity;
}
@ -863,7 +856,6 @@ int TDB::nextId ()
////////////////////////////////////////////////////////////////////////////////
void TDB::undo ()
{
context.hooks.trigger ("pre-undo");
Directory location (context.config.get ("data.location"));
std::string undoFile = location.data + "/undo.data";
@ -1147,7 +1139,6 @@ void TDB::undo ()
!confirm ("The undo command is not reversible. Are you sure you want to revert to the previous state?"))
{
std::cout << "No changes made.\n";
context.hooks.trigger ("post-undo");
return;
}
@ -1185,7 +1176,6 @@ void TDB::undo ()
// Rewrite files.
File::write (pendingFile, p);
File::write (undoFile, u);
context.hooks.trigger ("post-undo");
return;
}
}
@ -1224,7 +1214,6 @@ void TDB::undo ()
}
std::cout << "Undo complete.\n";
context.hooks.trigger ("post-undo");
return;
}
}

View file

@ -974,47 +974,41 @@ int handleReportBurndownDaily (std::string& outs)
{
int rc = 0;
if (context.hooks.trigger ("pre-burndown-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 ();
// Create a chart, scan the tasks, then render.
Chart chart ('D');
// Use any filter as a title.
if (context.filter.size ())
{
// 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 ();
std::string combined = "(";
// Create a chart, scan the tasks, then render.
Chart chart ('D');
// Use any filter as a title.
if (context.filter.size ())
for (unsigned int i = 0; i < context.filter.size (); ++i)
{
std::string combined = "(";
if (i)
combined += " ";
for (unsigned int i = 0; i < context.filter.size (); ++i)
{
if (i)
combined += " ";
combined += context.filter[i].name ();
combined += context.filter[i].name ();
if (context.filter[i].mod ().length ())
combined += "." + context.filter[i].mod ();
if (context.filter[i].mod ().length ())
combined += "." + context.filter[i].mod ();
combined += ":" + context.filter[i].value ();
}
combined += ")";
chart.description (combined);
combined += ":" + context.filter[i].value ();
}
chart.scan (tasks);
outs = chart.render ();
context.hooks.trigger ("post-burndown-command");
combined += ")";
chart.description (combined);
}
chart.scan (tasks);
outs = chart.render ();
return rc;
}
@ -1023,47 +1017,41 @@ int handleReportBurndownWeekly (std::string& outs)
{
int rc = 0;
if (context.hooks.trigger ("pre-burndown-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 ();
// Create a chart, scan the tasks, then render.
Chart chart ('W');
// Use any filter as a title.
if (context.filter.size ())
{
// 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 ();
std::string combined = "(";
// Create a chart, scan the tasks, then render.
Chart chart ('W');
// Use any filter as a title.
if (context.filter.size ())
for (unsigned int i = 0; i < context.filter.size (); ++i)
{
std::string combined = "(";
if (i)
combined += " ";
for (unsigned int i = 0; i < context.filter.size (); ++i)
{
if (i)
combined += " ";
combined += context.filter[i].name ();
combined += context.filter[i].name ();
if (context.filter[i].mod ().length ())
combined += "." + context.filter[i].mod ();
if (context.filter[i].mod ().length ())
combined += "." + context.filter[i].mod ();
combined += ":" + context.filter[i].value ();
}
combined += ")";
chart.description (combined);
combined += ":" + context.filter[i].value ();
}
chart.scan (tasks);
outs = chart.render ();
context.hooks.trigger ("post-burndown-command");
combined += ")";
chart.description (combined);
}
chart.scan (tasks);
outs = chart.render ();
return rc;
}
@ -1072,47 +1060,41 @@ int handleReportBurndownMonthly (std::string& outs)
{
int rc = 0;
if (context.hooks.trigger ("pre-burndown-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 ();
// Create a chart, scan the tasks, then render.
Chart chart ('M');
// Use any filter as a title.
if (context.filter.size ())
{
// 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 ();
std::string combined = "(";
// Create a chart, scan the tasks, then render.
Chart chart ('M');
// Use any filter as a title.
if (context.filter.size ())
for (unsigned int i = 0; i < context.filter.size (); ++i)
{
std::string combined = "(";
if (i)
combined += " ";
for (unsigned int i = 0; i < context.filter.size (); ++i)
{
if (i)
combined += " ";
combined += context.filter[i].name ();
combined += context.filter[i].name ();
if (context.filter[i].mod ().length ())
combined += "." + context.filter[i].mod ();
if (context.filter[i].mod ().length ())
combined += "." + context.filter[i].mod ();
combined += ":" + context.filter[i].value ();
}
combined += ")";
chart.description (combined);
combined += ":" + context.filter[i].value ();
}
chart.scan (tasks);
outs = chart.render ();
context.hooks.trigger ("post-burndown-command");
combined += ")";
chart.description (combined);
}
chart.scan (tasks);
outs = chart.render ();
return rc;
}

View file

@ -2457,7 +2457,7 @@ void handleShell ()
std::string prompt = context.config.get ("shell.prompt");
if (context.hooks.trigger ("pre-shell-prompt"))
{
context.hooks.trigger ("format-prompt", "prompt", prompt);
//context.hooks.trigger ("format-prompt", "prompt", prompt);
std::cout << prompt << " ";
}
context.hooks.trigger ("post-shell-prompt");

File diff suppressed because it is too large Load diff

View file

@ -652,32 +652,27 @@ int handleEdit (std::string& outs)
{
int rc = 0;
if (context.hooks.trigger ("pre-edit-command"))
{
std::stringstream out;
std::stringstream out;
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
Filter filter;
context.tdb.loadPending (tasks, filter);
// Filter sequence.
std::vector <Task> all = tasks;
context.filter.applySequence (tasks, context.sequence);
// Filter sequence.
std::vector <Task> all = tasks;
context.filter.applySequence (tasks, context.sequence);
std::vector <Task>::iterator task;
for (task = tasks.begin (); task != tasks.end (); ++task)
if (editFile (*task))
context.tdb.update (*task);
std::vector <Task>::iterator task;
for (task = tasks.begin (); task != tasks.end (); ++task)
if (editFile (*task))
context.tdb.update (*task);
context.tdb.commit ();
context.tdb.unlock ();
outs = out.str ();
context.hooks.trigger ("post-edit-command");
}
context.tdb.commit ();
context.tdb.unlock ();
outs = out.str ();
return rc;
}

View file

@ -41,50 +41,40 @@ extern Context context;
int handleExportCSV (std::string& outs)
{
int rc = 0;
std::stringstream out;
if (context.hooks.trigger ("pre-export-command"))
{
std::stringstream out;
// Deliberately no 'id'.
out << "'uuid',"
<< "'status',"
<< "'tags',"
<< "'entry',"
<< "'start',"
<< "'due',"
<< "'recur',"
<< "'end',"
<< "'project',"
<< "'priority',"
<< "'fg',"
<< "'bg',"
<< "'description'"
<< "\n";
// Deliberately no 'id'.
out << "'uuid',"
<< "'status',"
<< "'tags',"
<< "'entry',"
<< "'start',"
<< "'due',"
<< "'recur',"
<< "'end',"
<< "'project',"
<< "'priority',"
<< "'fg',"
<< "'bg',"
<< "'description'"
<< "\n";
// Get all the tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
// Get all the tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
foreach (task, tasks)
if (task->getStatus () != Task::recurring)
out << task->composeCSV ().c_str ();
foreach (task, tasks)
{
context.hooks.trigger ("pre-display", *task);
if (task->getStatus () != Task::recurring)
out << task->composeCSV ().c_str ();
}
outs = out.str ();
context.hooks.trigger ("post-export-command");
// Prevent messages from cluttering the export output.
context.headers.clear ();
}
outs = out.str ();
// Prevent messages from cluttering the export output.
context.headers.clear ();
return rc;
}
@ -95,133 +85,125 @@ int handleExportCSV (std::string& outs)
int handleExportiCal (std::string& outs)
{
int rc = 0;
std::stringstream out;
if (context.hooks.trigger ("pre-export-command"))
out << "BEGIN:VCALENDAR\n"
<< "VERSION:2.0\n"
<< "PRODID:-//GBF//" << PACKAGE_STRING << "//EN\n";
// Get all the tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
foreach (task, tasks)
{
std::stringstream out;
out << "BEGIN:VCALENDAR\n"
<< "VERSION:2.0\n"
<< "PRODID:-//GBF//" << PACKAGE_STRING << "//EN\n";
// Get all the tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
foreach (task, tasks)
if (task->getStatus () != Task::recurring)
{
context.hooks.trigger ("pre-display", *task);
out << "BEGIN:VTODO\n";
if (task->getStatus () != Task::recurring)
// Required UID:20070313T123432Z-456553@example.com
out << "UID:" << task->get ("uuid") << "\n";
// Required DTSTAMP:20070313T123432Z
Date entry (atoi (task->get ("entry").c_str ()));
out << "DTSTAMP:" << entry.toISO () << "\n";
// Optional DTSTART:20070514T110000Z
if (task->has ("start"))
{
out << "BEGIN:VTODO\n";
// Required UID:20070313T123432Z-456553@example.com
out << "UID:" << task->get ("uuid") << "\n";
// Required DTSTAMP:20070313T123432Z
Date entry (atoi (task->get ("entry").c_str ()));
out << "DTSTAMP:" << entry.toISO () << "\n";
// Optional DTSTART:20070514T110000Z
if (task->has ("start"))
{
Date start (atoi (task->get ("start").c_str ()));
out << "DTSTART:" << start.toISO () << "\n";
}
// Optional DUE:20070709T130000Z
if (task->has ("due"))
{
Date due (atoi (task->get ("due").c_str ()));
out << "DUE:" << due.toISO () << "\n";
}
// Optional COMPLETED:20070707T100000Z
if (task->has ("end") && task->getStatus () == Task::completed)
{
Date end (atoi (task->get ("end").c_str ()));
out << "COMPLETED:" << end.toISO () << "\n";
}
out << "SUMMARY:" << task->get ("description") << "\n";
// Optional CLASS:PUBLIC/PRIVATE/CONFIDENTIAL
std::string classification = context.config.get ("export.ical.class");
if (classification == "")
classification = "PRIVATE";
out << "CLASS:" << classification << "\n";
// Optional multiple CATEGORIES:FAMILY,FINANCE
if (task->getTagCount () > 0)
{
std::vector <std::string> tags;
task->getTags (tags);
std::string all;
join (all, ",", tags);
out << "CATEGORIES:" << all << "\n";
}
// Optional PRIORITY:
// 1-4 H
// 5 M
// 6-9 L
if (task->has ("priority"))
{
out << "PRIORITY:";
std::string priority = task->get ("priority");
if (priority == "H") out << "1";
else if (priority == "M") out << "5";
else out << "9";
out << "\n";
}
// Optional STATUS:NEEDS-ACTION/IN-PROCESS/COMPLETED/CANCELLED
out << "STATUS:";
Task::status stat = task->getStatus ();
if (stat == Task::pending || stat == Task::waiting)
{
if (task->has ("start"))
out << "IN-PROCESS";
else
out << "NEEDS-ACTION";
}
else if (stat == Task::completed)
{
out << "COMPLETED";
}
else if (stat == Task::deleted)
{
out << "CANCELLED";
}
out << "\n";
// Optional COMMENT:annotation1
// Optional COMMENT:annotation2
std::vector <Att> annotations;
task->getAnnotations (annotations);
foreach (anno, annotations)
out << "COMMENT:" << anno->value () << "\n";
out << "END:VTODO\n";
Date start (atoi (task->get ("start").c_str ()));
out << "DTSTART:" << start.toISO () << "\n";
}
// Optional DUE:20070709T130000Z
if (task->has ("due"))
{
Date due (atoi (task->get ("due").c_str ()));
out << "DUE:" << due.toISO () << "\n";
}
// Optional COMPLETED:20070707T100000Z
if (task->has ("end") && task->getStatus () == Task::completed)
{
Date end (atoi (task->get ("end").c_str ()));
out << "COMPLETED:" << end.toISO () << "\n";
}
out << "SUMMARY:" << task->get ("description") << "\n";
// Optional CLASS:PUBLIC/PRIVATE/CONFIDENTIAL
std::string classification = context.config.get ("export.ical.class");
if (classification == "")
classification = "PRIVATE";
out << "CLASS:" << classification << "\n";
// Optional multiple CATEGORIES:FAMILY,FINANCE
if (task->getTagCount () > 0)
{
std::vector <std::string> tags;
task->getTags (tags);
std::string all;
join (all, ",", tags);
out << "CATEGORIES:" << all << "\n";
}
// Optional PRIORITY:
// 1-4 H
// 5 M
// 6-9 L
if (task->has ("priority"))
{
out << "PRIORITY:";
std::string priority = task->get ("priority");
if (priority == "H") out << "1";
else if (priority == "M") out << "5";
else out << "9";
out << "\n";
}
// Optional STATUS:NEEDS-ACTION/IN-PROCESS/COMPLETED/CANCELLED
out << "STATUS:";
Task::status stat = task->getStatus ();
if (stat == Task::pending || stat == Task::waiting)
{
if (task->has ("start"))
out << "IN-PROCESS";
else
out << "NEEDS-ACTION";
}
else if (stat == Task::completed)
{
out << "COMPLETED";
}
else if (stat == Task::deleted)
{
out << "CANCELLED";
}
out << "\n";
// Optional COMMENT:annotation1
// Optional COMMENT:annotation2
std::vector <Att> annotations;
task->getAnnotations (annotations);
foreach (anno, annotations)
out << "COMMENT:" << anno->value () << "\n";
out << "END:VTODO\n";
}
out << "END:VCALENDAR\n";
outs = out.str ();
context.hooks.trigger ("post-export-command");
// Prevent messages from cluttering the export output.
context.headers.clear ();
}
out << "END:VCALENDAR\n";
outs = out.str ();
// Prevent messages from cluttering the export output.
context.headers.clear ();
return rc;
}
@ -230,36 +212,27 @@ int handleExportYAML (std::string& outs)
{
int rc = 0;
if (context.hooks.trigger ("pre-export-command"))
{
// YAML header.
std::stringstream out;
out << "%YAML 1.1\n"
<< "---\n";
// YAML header.
std::stringstream out;
out << "%YAML 1.1\n"
<< "---\n";
// Get all the tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
// Get all the tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
foreach (task, tasks)
{
context.hooks.trigger ("pre-display", *task);
out << task->composeYAML ().c_str ();
}
foreach (task, tasks)
out << task->composeYAML ().c_str ();
out << "...\n";
outs = out.str ();
context.hooks.trigger ("post-export-command");
// Prevent messages from cluttering the export output.
context.headers.clear ();
}
out << "...\n";
outs = out.str ();
// Prevent messages from cluttering the export output.
context.headers.clear ();
return rc;
}

File diff suppressed because it is too large Load diff

View file

@ -1264,94 +1264,88 @@ static std::string importYAML (const std::vector <std::string>& lines)
int handleImport (std::string& outs)
{
int rc = 0;
std::stringstream out;
if (context.hooks.trigger ("pre-import-command"))
// Use the description as a file name.
std::string file = trim (context.task.get ("description"));
std::string tmpfile = "";
Uri uri (file);
uri.parse ();
Transport* transport;
if ((transport = Transport::getTransport (uri)) != NULL )
{
std::stringstream out;
std::string location (context.config.get ("data.location"));
tmpfile = location + "/import.data";
transport->recv (tmpfile);
delete transport;
// Use the description as a file name.
std::string file = trim (context.task.get ("description"));
std::string tmpfile = "";
Uri uri (file);
uri.parse ();
Transport* transport;
if ((transport = Transport::getTransport (uri)) != NULL )
{
std::string location (context.config.get ("data.location"));
tmpfile = location + "/import.data";
transport->recv (tmpfile);
delete transport;
file = tmpfile;
}
if (file.length () > 0)
{
// Load the file.
std::vector <std::string> all;
File::read (file, all);
std::vector <std::string> lines;
std::vector <std::string>::iterator it;
for (it = all.begin (); it != all.end (); ++it)
{
std::string line = *it;
trim (line);
// Skip blank lines
if (line.length () > 0)
lines.push_back (line);
}
// Take a guess at the file type.
fileType type = determineFileType (lines);
std::string identifier;
switch (type)
{
case task_1_4_3: identifier = "This looks like an older taskwarrior export file."; break;
case task_1_5_0: identifier = "This looks like a recent taskwarrior export file."; break;
case task_1_6_0: identifier = "This looks like a current taskwarrior export file."; break;
case task_cmd_line: identifier = "This looks like taskwarrior command line arguments."; break;
case todo_sh_2_0: identifier = "This looks like a todo.sh 2.x file."; break;
case csv: identifier = "This looks like a CSV file, but not a taskwarrior export file."; break;
case yaml: identifier = "This looks like a YAML file."; break;
case text: identifier = "This looks like a text file with one task per line."; break;
case not_a_clue:
throw std::string ("Taskwarrior cannot determine which type of file "
"this is, and cannot proceed.");
}
// For tty users, confirm the import, as it is destructive.
if (isatty (fileno (stdout)))
if (! confirm (identifier + " Okay to proceed?"))
throw std::string ("Taskwarrior will not import any data.");
// Determine which type it might be, then attempt an import.
switch (type)
{
case task_1_4_3: out << importTask_1_4_3 (lines); break;
case task_1_5_0: out << importTask_1_5_0 (lines); break;
case task_1_6_0: out << importTask_1_6_0 (lines); break;
case task_cmd_line: out << importTaskCmdLine (lines); break;
case todo_sh_2_0: out << importTodoSh_2_0 (lines); break;
case csv: out << importCSV (lines); break;
case yaml: out << importYAML (lines); break;
case text: out << importText (lines); break;
case not_a_clue: /* to stop the compiler from complaining. */ break;
}
if (tmpfile != "")
remove (tmpfile.c_str ());
}
else
throw std::string ("You must specify a file to import.");
outs = out.str ();
context.hooks.trigger ("post-import-command");
file = tmpfile;
}
if (file.length () > 0)
{
// Load the file.
std::vector <std::string> all;
File::read (file, all);
std::vector <std::string> lines;
std::vector <std::string>::iterator it;
for (it = all.begin (); it != all.end (); ++it)
{
std::string line = *it;
trim (line);
// Skip blank lines
if (line.length () > 0)
lines.push_back (line);
}
// Take a guess at the file type.
fileType type = determineFileType (lines);
std::string identifier;
switch (type)
{
case task_1_4_3: identifier = "This looks like an older taskwarrior export file."; break;
case task_1_5_0: identifier = "This looks like a recent taskwarrior export file."; break;
case task_1_6_0: identifier = "This looks like a current taskwarrior export file."; break;
case task_cmd_line: identifier = "This looks like taskwarrior command line arguments."; break;
case todo_sh_2_0: identifier = "This looks like a todo.sh 2.x file."; break;
case csv: identifier = "This looks like a CSV file, but not a taskwarrior export file."; break;
case yaml: identifier = "This looks like a YAML file."; break;
case text: identifier = "This looks like a text file with one task per line."; break;
case not_a_clue:
throw std::string ("Taskwarrior cannot determine which type of file "
"this is, and cannot proceed.");
}
// For tty users, confirm the import, as it is destructive.
if (isatty (fileno (stdout)))
if (! confirm (identifier + " Okay to proceed?"))
throw std::string ("Taskwarrior will not import any data.");
// Determine which type it might be, then attempt an import.
switch (type)
{
case task_1_4_3: out << importTask_1_4_3 (lines); break;
case task_1_5_0: out << importTask_1_5_0 (lines); break;
case task_1_6_0: out << importTask_1_6_0 (lines); break;
case task_cmd_line: out << importTaskCmdLine (lines); break;
case todo_sh_2_0: out << importTodoSh_2_0 (lines); break;
case csv: out << importCSV (lines); break;
case yaml: out << importYAML (lines); break;
case text: out << importText (lines); break;
case not_a_clue: /* to stop the compiler from complaining. */ break;
}
if (tmpfile != "")
remove (tmpfile.c_str ());
}
else
throw std::string ("You must specify a file to import.");
outs = out.str ();
return rc;
}

File diff suppressed because it is too large Load diff