mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
Merge branch '1.4.3' into 1.5.0
Conflicts: NEWS TUTORIAL configure.ac html/advanced.html html/task.html html/versions.html src/task.cpp
This commit is contained in:
commit
47c02965e9
22 changed files with 449 additions and 92 deletions
40
src/TDB.cpp
40
src/TDB.cpp
|
@ -204,7 +204,9 @@ bool TDB::deleteT (const T& t)
|
|||
sprintf (endTime, "%u", (unsigned int) time (NULL));
|
||||
it->setAttribute ("end", endTime);
|
||||
|
||||
return overwritePending (all);
|
||||
bool status = overwritePending (all);
|
||||
dbChanged ();
|
||||
return status;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -228,14 +230,16 @@ bool TDB::completeT (const T& t)
|
|||
sprintf (endTime, "%u", (unsigned int) time (NULL));
|
||||
it->setAttribute ("end", endTime);
|
||||
|
||||
return overwritePending (all);
|
||||
bool status = overwritePending (all);
|
||||
dbChanged ();
|
||||
return status;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TDB::addT (const T& t) const
|
||||
bool TDB::addT (const T& t)
|
||||
{
|
||||
T task (t);
|
||||
std::vector <std::string> tags;
|
||||
|
@ -254,9 +258,15 @@ bool TDB::addT (const T& t) const
|
|||
|
||||
if (task.getStatus () == T::pending ||
|
||||
task.getStatus () == T::recurring)
|
||||
return writePending (task);
|
||||
{
|
||||
bool status = writePending (task);
|
||||
dbChanged ();
|
||||
return status;
|
||||
}
|
||||
|
||||
return writeCompleted (task);
|
||||
bool status = writeCompleted (task);
|
||||
dbChanged ();
|
||||
return status;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -281,7 +291,9 @@ bool TDB::modifyT (const T& t)
|
|||
pending.push_back (*it);
|
||||
}
|
||||
|
||||
return overwritePending (pending);
|
||||
bool status = overwritePending (pending);
|
||||
dbChanged ();
|
||||
return status;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -439,4 +451,20 @@ int TDB::nextId ()
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::onChange (void (*callback)())
|
||||
{
|
||||
if (callback)
|
||||
mOnChange.push_back (callback);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Iterate over callbacks.
|
||||
void TDB::dbChanged ()
|
||||
{
|
||||
foreach (i, mOnChange)
|
||||
if (*i)
|
||||
(**i) ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -45,23 +45,27 @@ public:
|
|||
bool allCompletedT (std::vector <T>&) const;
|
||||
bool deleteT (const T&);
|
||||
bool completeT (const T&);
|
||||
bool addT (const T&) const;
|
||||
bool addT (const T&);
|
||||
bool modifyT (const T&);
|
||||
bool logRead (std::vector <std::string>&) const;
|
||||
int gc ();
|
||||
int nextId ();
|
||||
|
||||
void onChange (void (*)());
|
||||
|
||||
private:
|
||||
bool lock (FILE*) const;
|
||||
bool overwritePending (std::vector <T>&);
|
||||
bool writePending (const T&) const;
|
||||
bool writeCompleted (const T&) const;
|
||||
bool readLockedFile (const std::string&, std::vector <std::string>&) const;
|
||||
void dbChanged ();
|
||||
|
||||
private:
|
||||
std::string mPendingFile;
|
||||
std::string mCompletedFile;
|
||||
int mId;
|
||||
std::vector <void (*)()> mOnChange;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void handleAdd (const TDB& tdb, T& task, Config& conf)
|
||||
void handleAdd (TDB& tdb, T& task, Config& conf)
|
||||
{
|
||||
char entryTime[16];
|
||||
sprintf (entryTime, "%u", (unsigned int) time (NULL));
|
||||
|
|
|
@ -659,9 +659,6 @@ void handleInfo (TDB& tdb, T& task, Config& conf)
|
|||
if (table.rowCount ())
|
||||
std::cout << optionalBlankLine (conf)
|
||||
<< table.render ()
|
||||
<< optionalBlankLine (conf)
|
||||
<< table.rowCount ()
|
||||
<< (table.rowCount () == 1 ? " task" : " tasks")
|
||||
<< std::endl;
|
||||
else
|
||||
std::cout << "No matches." << std::endl;
|
||||
|
|
216
src/task.cpp
216
src/task.cpp
|
@ -46,6 +46,11 @@
|
|||
#include <ncurses.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Globals for exclusive use by callback function.
|
||||
static TDB* gTdb = NULL;
|
||||
static Config* gConf = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static void shortUsage (Config& conf)
|
||||
{
|
||||
|
@ -280,6 +285,7 @@ int main (int argc, char** argv)
|
|||
// Load the config file from the home directory. If the file cannot be
|
||||
// found, offer to create a sample one.
|
||||
Config conf;
|
||||
gConf = &conf;
|
||||
loadConfFile (argc, argv, conf);
|
||||
|
||||
// When redirecting output to a file, do not use color, curses.
|
||||
|
@ -290,58 +296,30 @@ int main (int argc, char** argv)
|
|||
}
|
||||
|
||||
TDB tdb;
|
||||
tdb.dataDirectory (expandPath (conf.get ("data.location")));
|
||||
gTdb = &tdb;
|
||||
std::string dataLocation = expandPath (conf.get ("data.location"));
|
||||
tdb.dataDirectory (dataLocation);
|
||||
|
||||
// If argc == 1 and the default.command configuration variable is set,
|
||||
// then use that, otherwise stick with argc/argv.
|
||||
std::vector <std::string> args;
|
||||
std::string defaultCommand = conf.get ("default.command");
|
||||
if (argc == 1 && defaultCommand != "")
|
||||
// Log commands, if desired.
|
||||
if (conf.get ("command.logging") == "on")
|
||||
tdb.logCommand (argc, argv);
|
||||
|
||||
// Set up TDB callback.
|
||||
std::string shadowFile = expandPath (conf.get ("shadow.file"));
|
||||
if (shadowFile != "")
|
||||
{
|
||||
// Stuff the command line.
|
||||
split (args, defaultCommand, ' ');
|
||||
std::cout << "[task " << defaultCommand << "]" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse the command line.
|
||||
for (int i = 1; i < argc; ++i)
|
||||
args.push_back (argv[i]);
|
||||
if (shadowFile == dataLocation + "/pending.data")
|
||||
throw std::string ("Configuration variable 'shadow.file' is set to "
|
||||
"overwrite your pending tasks. Please change it.");
|
||||
|
||||
if (shadowFile == dataLocation + "/completed.data")
|
||||
throw std::string ("Configuration variable 'shadow.file' is set to "
|
||||
"overwrite your completed tasks. Please change it.");
|
||||
|
||||
tdb.onChange (&onChangeCallback);
|
||||
}
|
||||
|
||||
std::string command;
|
||||
T task;
|
||||
parse (args, command, task, conf);
|
||||
|
||||
if (command == "add") handleAdd (tdb, task, conf);
|
||||
else if (command == "projects") handleProjects (tdb, task, conf);
|
||||
else if (command == "tags") handleTags (tdb, task, conf);
|
||||
else if (command == "list") handleList (tdb, task, conf);
|
||||
else if (command == "info") handleInfo (tdb, task, conf);
|
||||
else if (command == "undelete") handleUndelete (tdb, task, conf);
|
||||
else if (command == "long") handleLongList (tdb, task, conf);
|
||||
else if (command == "ls") handleSmallList (tdb, task, conf);
|
||||
else if (command == "colors") handleColor ( conf);
|
||||
else if (command == "completed") handleCompleted (tdb, task, conf);
|
||||
else if (command == "delete") handleDelete (tdb, task, conf);
|
||||
else if (command == "start") handleStart (tdb, task, conf);
|
||||
else if (command == "done") handleDone (tdb, task, conf);
|
||||
else if (command == "undo") handleUndo (tdb, task, conf);
|
||||
else if (command == "export") handleExport (tdb, task, conf);
|
||||
else if (command == "version") handleVersion ( conf);
|
||||
else if (command == "summary") handleReportSummary (tdb, task, conf);
|
||||
else if (command == "next") handleReportNext (tdb, task, conf);
|
||||
else if (command == "history") handleReportHistory (tdb, task, conf);
|
||||
else if (command == "ghistory") handleReportGHistory (tdb, task, conf);
|
||||
else if (command == "calendar") handleReportCalendar (tdb, task, conf);
|
||||
else if (command == "active") handleReportActive (tdb, task, conf);
|
||||
else if (command == "overdue") handleReportOverdue (tdb, task, conf);
|
||||
else if (command == "oldest") handleReportOldest (tdb, task, conf);
|
||||
else if (command == "newest") handleReportNewest (tdb, task, conf);
|
||||
else if (command == "stats") handleReportStats (tdb, task, conf);
|
||||
else if (command == "" && task.getId ()) handleModify (tdb, task, conf);
|
||||
else if (command == "help") longUsage (conf);
|
||||
else shortUsage (conf);
|
||||
runTaskCommand (argc, argv, tdb, conf);
|
||||
}
|
||||
|
||||
catch (std::string& error)
|
||||
|
@ -391,12 +369,18 @@ int getDueState (const std::string& due)
|
|||
if (due.length ())
|
||||
{
|
||||
Date dt (::atoi (due.c_str ()));
|
||||
Date now;
|
||||
|
||||
if (dt < now)
|
||||
// rightNow is the current date + time.
|
||||
Date rightNow;
|
||||
|
||||
// By performing this conversion, today is set up as the same date, but
|
||||
// midnight.
|
||||
Date today (rightNow.month (), rightNow.day (), rightNow.year ());
|
||||
|
||||
if (dt < today)
|
||||
return 2;
|
||||
|
||||
Date nextweek = now + 7 * 86400;
|
||||
Date nextweek = today + 7 * 86400;
|
||||
if (dt < nextweek)
|
||||
return 1;
|
||||
}
|
||||
|
@ -544,7 +528,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
|||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
|
@ -563,7 +546,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
|||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
|
@ -579,7 +561,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
|||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
|
@ -598,7 +579,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
|||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
|
@ -614,7 +594,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
|||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
|
@ -630,7 +609,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
|||
while (! Date::valid (m, d, y))
|
||||
--d;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
|
@ -639,7 +617,6 @@ Date getNextRecurrence (Date& current, std::string& period)
|
|||
{
|
||||
y += 2;
|
||||
|
||||
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
|
||||
return Date (m, d, y);
|
||||
}
|
||||
|
||||
|
@ -657,7 +634,6 @@ void updateRecurrenceMask (
|
|||
T& task)
|
||||
{
|
||||
std::string parent = task.getAttribute ("parent");
|
||||
// std::cout << "# updateRecurrenceMask of " << parent << std::endl;
|
||||
if (parent != "")
|
||||
{
|
||||
std::vector <T>::iterator it;
|
||||
|
@ -665,11 +641,8 @@ void updateRecurrenceMask (
|
|||
{
|
||||
if (it->getUUID () == parent)
|
||||
{
|
||||
// std::cout << "# located parent task" << std::endl;
|
||||
unsigned int index = atoi (task.getAttribute ("imask").c_str ());
|
||||
// std::cout << "# child imask=" << index << std::endl;
|
||||
std::string mask = it->getAttribute ("mask");
|
||||
// std::cout << "# parent mask=" << mask << std::endl;
|
||||
if (mask.length () > index)
|
||||
{
|
||||
mask[index] = (task.getStatus () == T::pending) ? '-'
|
||||
|
@ -677,15 +650,11 @@ void updateRecurrenceMask (
|
|||
: (task.getStatus () == T::deleted) ? 'X'
|
||||
: '?';
|
||||
|
||||
// std::cout << "# setting parent mask to=" << mask << std::endl;
|
||||
it->setAttribute ("mask", mask);
|
||||
// std::cout << "# tdb.modifyT (parent)" << std::endl;
|
||||
tdb.modifyT (*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
// std::cout << "# mask of insufficient length" << std::endl;
|
||||
// std::cout << "# should never occur" << std::endl;
|
||||
std::string mask;
|
||||
for (unsigned int i = 0; i < index; ++i)
|
||||
mask += "?";
|
||||
|
@ -703,3 +672,118 @@ void updateRecurrenceMask (
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Using gTdb and gConf, generate a report.
|
||||
void onChangeCallback ()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (gConf && gTdb)
|
||||
{
|
||||
gConf->set ("curses", "off");
|
||||
gConf->set ("color", "off");
|
||||
|
||||
// Determine if shadow file is enabled.
|
||||
std::string shadowFile = expandPath (gConf->get ("shadow.file"));
|
||||
if (shadowFile != "")
|
||||
{
|
||||
// Capture std::cout for the shadow file.
|
||||
std::ofstream shadow (shadowFile.c_str ());
|
||||
std::streambuf* original = std::cout.rdbuf (shadow.rdbuf ());
|
||||
|
||||
// Run report. Use shadow.command, using default.command as a fallback
|
||||
// with "list" as a default.
|
||||
std::string command = gConf->get ("shadow.command",
|
||||
gConf->get ("default.command", "list"));
|
||||
std::vector <std::string> args;
|
||||
split (args, command, ' ');
|
||||
runTaskCommand (args, *gTdb, *gConf);
|
||||
|
||||
// Restore std::cout.
|
||||
std::cout.rdbuf (original);
|
||||
}
|
||||
else
|
||||
throw std::string ("Could not write to '") + shadowFile + "'.";
|
||||
}
|
||||
else
|
||||
throw std::string ("Internal error (TDB/Config).");
|
||||
}
|
||||
|
||||
catch (std::string& error)
|
||||
{
|
||||
std::cout << error << std::endl;
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "Unknown error." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void runTaskCommand (
|
||||
int argc,
|
||||
char** argv,
|
||||
TDB& tdb,
|
||||
Config& conf)
|
||||
{
|
||||
std::vector <std::string> args;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
args.push_back (argv[i]);
|
||||
|
||||
runTaskCommand (args, tdb, conf);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void runTaskCommand (
|
||||
std::vector <std::string>& args,
|
||||
TDB& tdb,
|
||||
Config& conf)
|
||||
{
|
||||
// If argc == 1 and the default.command configuration variable is set,
|
||||
// then use that, otherwise stick with argc/argv.
|
||||
std::string defaultCommand = conf.get ("default.command");
|
||||
if (args.size () == 0 && defaultCommand != "")
|
||||
{
|
||||
// Stuff the command line.
|
||||
args.clear ();
|
||||
split (args, defaultCommand, ' ');
|
||||
std::cout << "[task " << defaultCommand << "]" << std::endl;
|
||||
}
|
||||
|
||||
std::string command;
|
||||
T task;
|
||||
parse (args, command, task, conf);
|
||||
|
||||
if (command == "add") handleAdd (tdb, task, conf);
|
||||
else if (command == "projects") handleProjects (tdb, task, conf);
|
||||
else if (command == "tags") handleTags (tdb, task, conf);
|
||||
else if (command == "list") handleList (tdb, task, conf);
|
||||
else if (command == "info") handleInfo (tdb, task, conf);
|
||||
else if (command == "undelete") handleUndelete (tdb, task, conf);
|
||||
else if (command == "long") handleLongList (tdb, task, conf);
|
||||
else if (command == "ls") handleSmallList (tdb, task, conf);
|
||||
else if (command == "colors") handleColor ( conf);
|
||||
else if (command == "completed") handleCompleted (tdb, task, conf);
|
||||
else if (command == "delete") handleDelete (tdb, task, conf);
|
||||
else if (command == "start") handleStart (tdb, task, conf);
|
||||
else if (command == "done") handleDone (tdb, task, conf);
|
||||
else if (command == "undo") handleUndo (tdb, task, conf);
|
||||
else if (command == "export") handleExport (tdb, task, conf);
|
||||
else if (command == "version") handleVersion ( conf);
|
||||
else if (command == "summary") handleReportSummary (tdb, task, conf);
|
||||
else if (command == "next") handleReportNext (tdb, task, conf);
|
||||
else if (command == "history") handleReportHistory (tdb, task, conf);
|
||||
else if (command == "ghistory") handleReportGHistory (tdb, task, conf);
|
||||
else if (command == "calendar") handleReportCalendar (tdb, task, conf);
|
||||
else if (command == "active") handleReportActive (tdb, task, conf);
|
||||
else if (command == "overdue") handleReportOverdue (tdb, task, conf);
|
||||
else if (command == "oldest") handleReportOldest (tdb, task, conf);
|
||||
else if (command == "newest") handleReportNewest (tdb, task, conf);
|
||||
else if (command == "stats") handleReportStats (tdb, task, conf);
|
||||
else if (command == "usage") handleReportUsage (tdb, task, conf);
|
||||
else if (command == "" && task.getId ()) handleModify (tdb, task, conf);
|
||||
else if (command == "help") longUsage (conf);
|
||||
else shortUsage (conf);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -66,9 +66,12 @@ void handleRecurrence (TDB&, std::vector <T>&);
|
|||
bool generateDueDates (T&, std::vector <Date>&);
|
||||
Date getNextRecurrence (Date&, std::string&);
|
||||
void updateRecurrenceMask (TDB&, std::vector <T>&, T&);
|
||||
void onChangeCallback ();
|
||||
void runTaskCommand (int, char**, TDB&, Config&);
|
||||
void runTaskCommand (std::vector <std::string>&, TDB&, Config&);
|
||||
|
||||
// command.cpp
|
||||
void handleAdd (const TDB&, T&, Config&);
|
||||
void handleAdd (TDB&, T&, Config&);
|
||||
void handleProjects (TDB&, T&, Config&);
|
||||
void handleTags (TDB&, T&, Config&);
|
||||
void handleUndelete (TDB&, T&, Config&);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue