mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Hooks
- 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:
parent
2f4efb28d6
commit
48eb4757f8
15 changed files with 2816 additions and 3246 deletions
|
@ -124,7 +124,7 @@ void Context::initialize (int argc, char** argv)
|
||||||
// Hook system init, plus post-start event occurring at the first possible
|
// Hook system init, plus post-start event occurring at the first possible
|
||||||
// moment after hook initialization.
|
// moment after hook initialization.
|
||||||
hooks.initialize ();
|
hooks.initialize ();
|
||||||
hooks.trigger ("post-start");
|
hooks.trigger ("on-launch");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -189,41 +189,33 @@ int Context::run ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dump all debug messages.
|
// Dump all debug messages.
|
||||||
hooks.trigger ("pre-debug");
|
|
||||||
if (config.getBoolean ("debug"))
|
if (config.getBoolean ("debug"))
|
||||||
foreach (d, debugMessages)
|
foreach (d, debugMessages)
|
||||||
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
||||||
std::cout << colorizeDebug (*d) << "\n";
|
std::cout << colorizeDebug (*d) << "\n";
|
||||||
else
|
else
|
||||||
std::cout << *d << "\n";
|
std::cout << *d << "\n";
|
||||||
hooks.trigger ("post-debug");
|
|
||||||
|
|
||||||
// Dump all headers.
|
// Dump all headers.
|
||||||
hooks.trigger ("pre-header");
|
|
||||||
if (config.getBoolean ("verbose"))
|
if (config.getBoolean ("verbose"))
|
||||||
foreach (h, headers)
|
foreach (h, headers)
|
||||||
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
||||||
std::cout << colorizeHeader (*h) << "\n";
|
std::cout << colorizeHeader (*h) << "\n";
|
||||||
else
|
else
|
||||||
std::cout << *h << "\n";
|
std::cout << *h << "\n";
|
||||||
hooks.trigger ("post-header");
|
|
||||||
|
|
||||||
// Dump the report output.
|
// Dump the report output.
|
||||||
hooks.trigger ("pre-output");
|
|
||||||
std::cout << output;
|
std::cout << output;
|
||||||
hooks.trigger ("post-output");
|
|
||||||
|
|
||||||
// Dump all footnotes.
|
// Dump all footnotes.
|
||||||
hooks.trigger ("pre-footnote");
|
|
||||||
if (config.getBoolean ("verbose"))
|
if (config.getBoolean ("verbose"))
|
||||||
foreach (f, footnotes)
|
foreach (f, footnotes)
|
||||||
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
if (config.getBoolean ("color") || config.getBoolean ("_forcecolor"))
|
||||||
std::cout << colorizeFootnote (*f) << "\n";
|
std::cout << colorizeFootnote (*f) << "\n";
|
||||||
else
|
else
|
||||||
std::cout << *f << "\n";
|
std::cout << *f << "\n";
|
||||||
hooks.trigger ("post-footnote");
|
|
||||||
|
|
||||||
hooks.trigger ("pre-exit");
|
hooks.trigger ("on-exit");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,8 +226,6 @@ int Context::dispatch (std::string &out)
|
||||||
|
|
||||||
Timer t ("Context::dispatch");
|
Timer t ("Context::dispatch");
|
||||||
|
|
||||||
hooks.trigger ("pre-dispatch");
|
|
||||||
|
|
||||||
// For read-only commands, optionally update the xterm window title.
|
// For read-only commands, optionally update the xterm window title.
|
||||||
// Why just the read-only commands? Because this capability is to answer the
|
// Why just the read-only commands? Because this capability is to answer the
|
||||||
// question of 'what did I just do to generate this outout?'.
|
// 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); }
|
rc = handleCustomReport (cmd.command, out); }
|
||||||
|
|
||||||
// If the command is not recognized, display usage.
|
// If the command is not recognized, display usage.
|
||||||
else { hooks.trigger ("pre-usage-command");
|
else { rc = shortUsage (out); }
|
||||||
rc = shortUsage (out);
|
|
||||||
hooks.trigger ("post-usage-command"); }
|
|
||||||
|
|
||||||
// Only update the shadow file if such an update was not suppressed (shadow),
|
// Only update the shadow file if such an update was not suppressed (shadow),
|
||||||
if (cmd.isWriteCommand () && !inShadow)
|
if (cmd.isWriteCommand () && !inShadow)
|
||||||
shadow ();
|
shadow ();
|
||||||
|
|
||||||
hooks.trigger ("post-dispatch");
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
245
src/Hooks.cpp
245
src/Hooks.cpp
|
@ -73,208 +73,19 @@ Hook& Hook::operator= (const Hook& other)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Hooks::Hooks ()
|
Hooks::Hooks ()
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
// New 2.x hooks.
|
// New 2.x hooks.
|
||||||
validTaskEvents.push_back ("on-task-add");
|
validTaskEvents.push_back ("on-task-add"); // Unimplemented
|
||||||
validTaskEvents.push_back ("on-task-modify");
|
validTaskEvents.push_back ("on-task-modify"); // Unimplemented
|
||||||
validTaskEvents.push_back ("on-task-complete");
|
validTaskEvents.push_back ("on-task-complete"); // Unimplemented
|
||||||
validTaskEvents.push_back ("on-task-delete");
|
validTaskEvents.push_back ("on-task-delete"); // Unimplemented
|
||||||
|
|
||||||
validProgramEvents.push_back ("on-launch");
|
validProgramEvents.push_back ("on-launch");
|
||||||
validProgramEvents.push_back ("on-exit");
|
validProgramEvents.push_back ("on-exit");
|
||||||
validProgramEvents.push_back ("on-file-read");
|
validProgramEvents.push_back ("on-file-read"); // Unimplemented
|
||||||
validProgramEvents.push_back ("on-file-write");
|
validProgramEvents.push_back ("on-file-write"); // Unimplemented
|
||||||
validProgramEvents.push_back ("on-synch");
|
validProgramEvents.push_back ("on-synch"); // Unimplemented
|
||||||
validProgramEvents.push_back ("on-gc");
|
validProgramEvents.push_back ("on-merge"); // Unimplemented
|
||||||
*/
|
validProgramEvents.push_back ("on-gc"); // Unimplemented
|
||||||
|
|
||||||
// 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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -395,36 +206,6 @@ bool Hooks::trigger (const std::string& event, Task& task)
|
||||||
return true;
|
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)
|
bool Hooks::validProgramEvent (const std::string& event)
|
||||||
{
|
{
|
||||||
|
@ -442,12 +223,4 @@ bool Hooks::validTaskEvent (const std::string& event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hooks::validFieldEvent (const std::string& event)
|
|
||||||
{
|
|
||||||
if (std::find (validFieldEvents.begin (), validFieldEvents.end (), event) != validFieldEvents.end ())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -60,12 +60,10 @@ public:
|
||||||
|
|
||||||
bool trigger (const std::string&); // Program
|
bool trigger (const std::string&); // Program
|
||||||
bool trigger (const std::string&, Task&); // Task
|
bool trigger (const std::string&, Task&); // Task
|
||||||
bool trigger (const std::string&, const std::string&, std::string&); // Field
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool validProgramEvent (const std::string&);
|
bool validProgramEvent (const std::string&);
|
||||||
bool validTaskEvent (const std::string&);
|
bool validTaskEvent (const std::string&);
|
||||||
bool validFieldEvent (const std::string&);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef HAVE_LIBLUA
|
#ifdef HAVE_LIBLUA
|
||||||
|
@ -75,7 +73,6 @@ private:
|
||||||
|
|
||||||
std::vector <std::string> validProgramEvents;
|
std::vector <std::string> validProgramEvents;
|
||||||
std::vector <std::string> validTaskEvents;
|
std::vector <std::string> validTaskEvents;
|
||||||
std::vector <std::string> validFieldEvents;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
37
src/TDB.cpp
37
src/TDB.cpp
|
@ -191,25 +191,21 @@ void TDB::location (const std::string& path)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void TDB::lock (bool lockFile /* = true */)
|
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;
|
location->pending = openAndLock (location->path + "/pending.data");
|
||||||
|
location->completed = openAndLock (location->path + "/completed.data");
|
||||||
mPending.clear ();
|
location->undo = openAndLock (location->path + "/undo.data");
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mAllOpenAndLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -492,7 +488,6 @@ void TDB::update (const Task& task)
|
||||||
int TDB::commit ()
|
int TDB::commit ()
|
||||||
{
|
{
|
||||||
Timer t ("TDB::commit");
|
Timer t ("TDB::commit");
|
||||||
context.hooks.trigger ("pre-commit");
|
|
||||||
|
|
||||||
int quantity = mNew.size () + mModified.size ();
|
int quantity = mNew.size () + mModified.size ();
|
||||||
|
|
||||||
|
@ -512,7 +507,6 @@ int TDB::commit ()
|
||||||
writeUndo (*task, mLocations[0].undo);
|
writeUndo (*task, mLocations[0].undo);
|
||||||
|
|
||||||
mNew.clear ();
|
mNew.clear ();
|
||||||
context.hooks.trigger ("post-commit");
|
|
||||||
return quantity;
|
return quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,7 +573,6 @@ int TDB::commit ()
|
||||||
mNew.clear ();
|
mNew.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
context.hooks.trigger ("post-commit");
|
|
||||||
return quantity;
|
return quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,7 +706,6 @@ int TDB::nextId ()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void TDB::undo ()
|
void TDB::undo ()
|
||||||
{
|
{
|
||||||
context.hooks.trigger ("pre-undo");
|
|
||||||
Directory location (context.config.get ("data.location"));
|
Directory location (context.config.get ("data.location"));
|
||||||
|
|
||||||
std::string undoFile = location.data + "/undo.data";
|
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?"))
|
!confirm ("The undo command is not reversible. Are you sure you want to revert to the previous state?"))
|
||||||
{
|
{
|
||||||
std::cout << "No changes made.\n";
|
std::cout << "No changes made.\n";
|
||||||
context.hooks.trigger ("post-undo");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1035,7 +1026,6 @@ void TDB::undo ()
|
||||||
// Rewrite files.
|
// Rewrite files.
|
||||||
File::write (pendingFile, p);
|
File::write (pendingFile, p);
|
||||||
File::write (undoFile, u);
|
File::write (undoFile, u);
|
||||||
context.hooks.trigger ("post-undo");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1064,6 @@ void TDB::undo ()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Undo complete.\n";
|
std::cout << "Undo complete.\n";
|
||||||
context.hooks.trigger ("post-undo");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
37
src/TDB2.cpp
37
src/TDB2.cpp
|
@ -341,25 +341,21 @@ void TDB::location (const std::string& path)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void TDB::lock (bool lockFile /* = true */)
|
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;
|
location->pending = openAndLock (location->path + "/pending.data");
|
||||||
|
location->completed = openAndLock (location->path + "/completed.data");
|
||||||
mPending.clear ();
|
location->undo = openAndLock (location->path + "/undo.data");
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mAllOpenAndLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -642,7 +638,6 @@ void TDB::update (const Task& task)
|
||||||
int TDB::commit ()
|
int TDB::commit ()
|
||||||
{
|
{
|
||||||
Timer t ("TDB::commit");
|
Timer t ("TDB::commit");
|
||||||
context.hooks.trigger ("pre-commit");
|
|
||||||
|
|
||||||
int quantity = mNew.size () + mModified.size ();
|
int quantity = mNew.size () + mModified.size ();
|
||||||
|
|
||||||
|
@ -662,7 +657,6 @@ int TDB::commit ()
|
||||||
writeUndo (*task, mLocations[0].undo);
|
writeUndo (*task, mLocations[0].undo);
|
||||||
|
|
||||||
mNew.clear ();
|
mNew.clear ();
|
||||||
context.hooks.trigger ("post-commit");
|
|
||||||
return quantity;
|
return quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -729,7 +723,6 @@ int TDB::commit ()
|
||||||
mNew.clear ();
|
mNew.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
context.hooks.trigger ("post-commit");
|
|
||||||
return quantity;
|
return quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,7 +856,6 @@ int TDB::nextId ()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void TDB::undo ()
|
void TDB::undo ()
|
||||||
{
|
{
|
||||||
context.hooks.trigger ("pre-undo");
|
|
||||||
Directory location (context.config.get ("data.location"));
|
Directory location (context.config.get ("data.location"));
|
||||||
|
|
||||||
std::string undoFile = location.data + "/undo.data";
|
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?"))
|
!confirm ("The undo command is not reversible. Are you sure you want to revert to the previous state?"))
|
||||||
{
|
{
|
||||||
std::cout << "No changes made.\n";
|
std::cout << "No changes made.\n";
|
||||||
context.hooks.trigger ("post-undo");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1185,7 +1176,6 @@ void TDB::undo ()
|
||||||
// Rewrite files.
|
// Rewrite files.
|
||||||
File::write (pendingFile, p);
|
File::write (pendingFile, p);
|
||||||
File::write (undoFile, u);
|
File::write (undoFile, u);
|
||||||
context.hooks.trigger ("post-undo");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1224,7 +1214,6 @@ void TDB::undo ()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Undo complete.\n";
|
std::cout << "Undo complete.\n";
|
||||||
context.hooks.trigger ("post-undo");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
168
src/burndown.cpp
168
src/burndown.cpp
|
@ -974,47 +974,41 @@ int handleReportBurndownDaily (std::string& outs)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
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::string combined = "(";
|
||||||
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.
|
for (unsigned int i = 0; i < context.filter.size (); ++i)
|
||||||
Chart chart ('D');
|
|
||||||
|
|
||||||
// Use any filter as a title.
|
|
||||||
if (context.filter.size ())
|
|
||||||
{
|
{
|
||||||
std::string combined = "(";
|
if (i)
|
||||||
|
combined += " ";
|
||||||
|
|
||||||
for (unsigned int i = 0; i < context.filter.size (); ++i)
|
combined += context.filter[i].name ();
|
||||||
{
|
|
||||||
if (i)
|
|
||||||
combined += " ";
|
|
||||||
|
|
||||||
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].value ();
|
||||||
combined += "." + context.filter[i].mod ();
|
|
||||||
|
|
||||||
combined += ":" + context.filter[i].value ();
|
|
||||||
}
|
|
||||||
|
|
||||||
combined += ")";
|
|
||||||
chart.description (combined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chart.scan (tasks);
|
combined += ")";
|
||||||
outs = chart.render ();
|
chart.description (combined);
|
||||||
|
|
||||||
context.hooks.trigger ("post-burndown-command");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chart.scan (tasks);
|
||||||
|
outs = chart.render ();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,47 +1017,41 @@ int handleReportBurndownWeekly (std::string& outs)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
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::string combined = "(";
|
||||||
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.
|
for (unsigned int i = 0; i < context.filter.size (); ++i)
|
||||||
Chart chart ('W');
|
|
||||||
|
|
||||||
// Use any filter as a title.
|
|
||||||
if (context.filter.size ())
|
|
||||||
{
|
{
|
||||||
std::string combined = "(";
|
if (i)
|
||||||
|
combined += " ";
|
||||||
|
|
||||||
for (unsigned int i = 0; i < context.filter.size (); ++i)
|
combined += context.filter[i].name ();
|
||||||
{
|
|
||||||
if (i)
|
|
||||||
combined += " ";
|
|
||||||
|
|
||||||
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].value ();
|
||||||
combined += "." + context.filter[i].mod ();
|
|
||||||
|
|
||||||
combined += ":" + context.filter[i].value ();
|
|
||||||
}
|
|
||||||
|
|
||||||
combined += ")";
|
|
||||||
chart.description (combined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chart.scan (tasks);
|
combined += ")";
|
||||||
outs = chart.render ();
|
chart.description (combined);
|
||||||
|
|
||||||
context.hooks.trigger ("post-burndown-command");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chart.scan (tasks);
|
||||||
|
outs = chart.render ();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1072,47 +1060,41 @@ int handleReportBurndownMonthly (std::string& outs)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
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::string combined = "(";
|
||||||
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.
|
for (unsigned int i = 0; i < context.filter.size (); ++i)
|
||||||
Chart chart ('M');
|
|
||||||
|
|
||||||
// Use any filter as a title.
|
|
||||||
if (context.filter.size ())
|
|
||||||
{
|
{
|
||||||
std::string combined = "(";
|
if (i)
|
||||||
|
combined += " ";
|
||||||
|
|
||||||
for (unsigned int i = 0; i < context.filter.size (); ++i)
|
combined += context.filter[i].name ();
|
||||||
{
|
|
||||||
if (i)
|
|
||||||
combined += " ";
|
|
||||||
|
|
||||||
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].value ();
|
||||||
combined += "." + context.filter[i].mod ();
|
|
||||||
|
|
||||||
combined += ":" + context.filter[i].value ();
|
|
||||||
}
|
|
||||||
|
|
||||||
combined += ")";
|
|
||||||
chart.description (combined);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chart.scan (tasks);
|
combined += ")";
|
||||||
outs = chart.render ();
|
chart.description (combined);
|
||||||
|
|
||||||
context.hooks.trigger ("post-burndown-command");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chart.scan (tasks);
|
||||||
|
outs = chart.render ();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2457,7 +2457,7 @@ void handleShell ()
|
||||||
std::string prompt = context.config.get ("shell.prompt");
|
std::string prompt = context.config.get ("shell.prompt");
|
||||||
if (context.hooks.trigger ("pre-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 << " ";
|
std::cout << prompt << " ";
|
||||||
}
|
}
|
||||||
context.hooks.trigger ("post-shell-prompt");
|
context.hooks.trigger ("post-shell-prompt");
|
||||||
|
|
1238
src/custom.cpp
1238
src/custom.cpp
File diff suppressed because it is too large
Load diff
37
src/edit.cpp
37
src/edit.cpp
|
@ -652,32 +652,27 @@ int handleEdit (std::string& outs)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (context.hooks.trigger ("pre-edit-command"))
|
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"));
|
||||||
handleRecurrence ();
|
handleRecurrence ();
|
||||||
Filter filter;
|
Filter filter;
|
||||||
context.tdb.loadPending (tasks, filter);
|
context.tdb.loadPending (tasks, filter);
|
||||||
|
|
||||||
// Filter sequence.
|
// Filter sequence.
|
||||||
std::vector <Task> all = tasks;
|
std::vector <Task> all = tasks;
|
||||||
context.filter.applySequence (tasks, context.sequence);
|
context.filter.applySequence (tasks, context.sequence);
|
||||||
|
|
||||||
std::vector <Task>::iterator task;
|
std::vector <Task>::iterator task;
|
||||||
for (task = tasks.begin (); task != tasks.end (); ++task)
|
for (task = tasks.begin (); task != tasks.end (); ++task)
|
||||||
if (editFile (*task))
|
if (editFile (*task))
|
||||||
context.tdb.update (*task);
|
context.tdb.update (*task);
|
||||||
|
|
||||||
context.tdb.commit ();
|
context.tdb.commit ();
|
||||||
context.tdb.unlock ();
|
context.tdb.unlock ();
|
||||||
|
|
||||||
outs = out.str ();
|
|
||||||
context.hooks.trigger ("post-edit-command");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
outs = out.str ();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
339
src/export.cpp
339
src/export.cpp
|
@ -41,50 +41,40 @@ extern Context context;
|
||||||
int handleExportCSV (std::string& outs)
|
int handleExportCSV (std::string& outs)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
std::stringstream out;
|
||||||
|
|
||||||
if (context.hooks.trigger ("pre-export-command"))
|
// Deliberately no 'id'.
|
||||||
{
|
out << "'uuid',"
|
||||||
std::stringstream out;
|
<< "'status',"
|
||||||
|
<< "'tags',"
|
||||||
|
<< "'entry',"
|
||||||
|
<< "'start',"
|
||||||
|
<< "'due',"
|
||||||
|
<< "'recur',"
|
||||||
|
<< "'end',"
|
||||||
|
<< "'project',"
|
||||||
|
<< "'priority',"
|
||||||
|
<< "'fg',"
|
||||||
|
<< "'bg',"
|
||||||
|
<< "'description'"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
// Deliberately no 'id'.
|
// Get all the tasks.
|
||||||
out << "'uuid',"
|
std::vector <Task> tasks;
|
||||||
<< "'status',"
|
context.tdb.lock (context.config.getBoolean ("locking"));
|
||||||
<< "'tags',"
|
handleRecurrence ();
|
||||||
<< "'entry',"
|
context.tdb.load (tasks, context.filter);
|
||||||
<< "'start',"
|
context.tdb.commit ();
|
||||||
<< "'due',"
|
context.tdb.unlock ();
|
||||||
<< "'recur',"
|
|
||||||
<< "'end',"
|
|
||||||
<< "'project',"
|
|
||||||
<< "'priority',"
|
|
||||||
<< "'fg',"
|
|
||||||
<< "'bg',"
|
|
||||||
<< "'description'"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
// Get all the tasks.
|
foreach (task, tasks)
|
||||||
std::vector <Task> tasks;
|
if (task->getStatus () != Task::recurring)
|
||||||
context.tdb.lock (context.config.getBoolean ("locking"));
|
out << task->composeCSV ().c_str ();
|
||||||
handleRecurrence ();
|
|
||||||
context.tdb.load (tasks, context.filter);
|
|
||||||
context.tdb.commit ();
|
|
||||||
context.tdb.unlock ();
|
|
||||||
|
|
||||||
foreach (task, tasks)
|
outs = out.str ();
|
||||||
{
|
|
||||||
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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Prevent messages from cluttering the export output.
|
||||||
|
context.headers.clear ();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,133 +85,125 @@ int handleExportCSV (std::string& outs)
|
||||||
int handleExportiCal (std::string& outs)
|
int handleExportiCal (std::string& outs)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
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;
|
if (task->getStatus () != Task::recurring)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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";
|
Date start (atoi (task->get ("start").c_str ()));
|
||||||
|
out << "DTSTART:" << start.toISO () << "\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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,36 +212,27 @@ int handleExportYAML (std::string& outs)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (context.hooks.trigger ("pre-export-command"))
|
// YAML header.
|
||||||
{
|
std::stringstream out;
|
||||||
// YAML header.
|
out << "%YAML 1.1\n"
|
||||||
std::stringstream out;
|
<< "---\n";
|
||||||
out << "%YAML 1.1\n"
|
|
||||||
<< "---\n";
|
|
||||||
|
|
||||||
// Get all the tasks.
|
// Get all the tasks.
|
||||||
std::vector <Task> tasks;
|
std::vector <Task> tasks;
|
||||||
context.tdb.lock (context.config.getBoolean ("locking"));
|
context.tdb.lock (context.config.getBoolean ("locking"));
|
||||||
handleRecurrence ();
|
handleRecurrence ();
|
||||||
context.tdb.load (tasks, context.filter);
|
context.tdb.load (tasks, context.filter);
|
||||||
context.tdb.commit ();
|
context.tdb.commit ();
|
||||||
context.tdb.unlock ();
|
context.tdb.unlock ();
|
||||||
|
|
||||||
foreach (task, tasks)
|
foreach (task, tasks)
|
||||||
{
|
out << task->composeYAML ().c_str ();
|
||||||
context.hooks.trigger ("pre-display", *task);
|
|
||||||
out << task->composeYAML ().c_str ();
|
|
||||||
}
|
|
||||||
|
|
||||||
out << "...\n";
|
out << "...\n";
|
||||||
|
outs = out.str ();
|
||||||
outs = out.str ();
|
|
||||||
context.hooks.trigger ("post-export-command");
|
|
||||||
|
|
||||||
// Prevent messages from cluttering the export output.
|
|
||||||
context.headers.clear ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Prevent messages from cluttering the export output.
|
||||||
|
context.headers.clear ();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1196
src/history.cpp
1196
src/history.cpp
File diff suppressed because it is too large
Load diff
160
src/import.cpp
160
src/import.cpp
|
@ -1264,94 +1264,88 @@ static std::string importYAML (const std::vector <std::string>& lines)
|
||||||
int handleImport (std::string& outs)
|
int handleImport (std::string& outs)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
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.
|
file = tmpfile;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2577
src/report.cpp
2577
src/report.cpp
File diff suppressed because it is too large
Load diff
|
@ -35,7 +35,7 @@ if (open my $fh, '>', 'hook.rc')
|
||||||
{
|
{
|
||||||
print $fh "data.location=.\n",
|
print $fh "data.location=.\n",
|
||||||
"hooks=on\n",
|
"hooks=on\n",
|
||||||
"hook.pre-exit=" . $ENV{'PWD'} . "/hook:test\n";
|
"hook.on-exit=" . $ENV{'PWD'} . "/hook:test\n";
|
||||||
close $fh;
|
close $fh;
|
||||||
ok (-r 'hook.rc', 'Created hook.rc');
|
ok (-r 'hook.rc', 'Created hook.rc');
|
||||||
}
|
}
|
|
@ -35,7 +35,7 @@ if (open my $fh, '>', 'hook.rc')
|
||||||
{
|
{
|
||||||
print $fh "data.location=.\n",
|
print $fh "data.location=.\n",
|
||||||
"hooks=on\n",
|
"hooks=on\n",
|
||||||
"hook.post-start=" . $ENV{'PWD'} . "/hook:test\n";
|
"hook.on-launch=" . $ENV{'PWD'} . "/hook:test\n";
|
||||||
close $fh;
|
close $fh;
|
||||||
ok (-r 'hook.rc', 'Created hook.rc');
|
ok (-r 'hook.rc', 'Created hook.rc');
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue