Merge branch '1.9.3' of tasktools.org:task into 1.9.3

Conflicts:
	src/Config.cpp
This commit is contained in:
Johannes Schlatow 2010-09-02 01:53:25 +02:00
commit 2eaba55481
27 changed files with 663 additions and 338 deletions

View file

@ -415,7 +415,7 @@ bool Att::validNameValue (
"\" is not a valid status. Use 'pending', 'completed', 'deleted', 'recurring' or 'waiting'.";
}
else if (! validInternalName (name) &&
else if (! validInternalName (name) &&
! validModifiableName (name))
throw std::string ("'") + name + "' is not a recognized attribute.";
@ -438,11 +438,11 @@ bool Att::validMod (const std::string& mod)
std::string Att::type (const std::string& name) const
{
if (name == "due" ||
name == "wait" ||
name == "until" ||
name == "start" ||
name == "entry" ||
name == "end" ||
name == "wait")
name == "end")
return "date";
else if (name == "recur")
@ -542,16 +542,17 @@ bool Att::match (const Att& other) const
if (mMod == "")
{
// Exact matches on dates should only compare m/d/y, not h:m:s. This allows
// Comapisons like "task list due:today" (bug #405).
// comparisons like "task list due:today" (bug #405).
std::string which = type (mName);
if (which == "date")
{
if (other.mValue == "")
return false;
Date left (mValue);
Date right (other.mValue);
if (left.year () != right.year () ||
left.month () != right.month () ||
left.day () != right.day ())
if (! left.sameDay (right))
return false;
}
else

View file

@ -59,172 +59,175 @@ std::string Config::defaults =
"\n"
"# Files\n"
"data.location=~/.task\n"
"locking=on # Use file-level locking\n"
"locking=on # Use file-level locking\n"
"\n"
"# Terminal\n"
"curses=on # Use ncurses library to determine terminal width\n"
"defaultwidth=80 # Without ncurses, assumed width\n"
"#editor=vi # Preferred text editor\n"
"curses=on # Use ncurses library to determine terminal width\n"
"defaultwidth=80 # Without ncurses, assumed width\n"
"#editor=vi # Preferred text editor\n"
"\n"
"# Miscellaneous\n"
"verbose=yes # Provide extra feedback\n"
"confirmation=yes # Confirmation on delete, big changes\n"
"echo.command=yes # Details on command just run\n"
"annotations=full # Level of verbosity for annotations: full, sparse or none\n"
"next=2 # How many tasks per project in next report\n"
"bulk=2 # > 2 tasks considered 'a lot', for confirmation\n"
"nag=You have higher priority tasks. # Nag message to keep you honest\n" // TODO
"search.case.sensitive=yes # Setting to no allows case insensitive searches\n"
"active.indicator=* # What to show as an active task indicator\n"
"tag.indicator=+ # What to show as a tag indicator\n"
"recurrence.indicator=R # What to show as a task recurrence indicator\n"
"recurrence.limit=1 # Number of future recurring pending tasks\n"
"undo.style=side # Undo style - can be 'side', or 'diff'\n"
"merge.autopush=ask # Push database to remote origin after merge: yes, no, ask\n"
"verbose=yes # Provide extra feedback\n"
"confirmation=yes # Confirmation on delete, big changes\n"
"echo.command=yes # Details on command just run\n"
"annotations=full # Level of verbosity for annotations: full, sparse or none\n"
"next=2 # How many tasks per project in next report\n"
"bulk=2 # > 2 tasks considered 'a lot', for confirmation\n"
"nag=You have higher priority tasks. # Nag message to keep you honest\n" // TODO
"search.case.sensitive=yes # Setting to no allows case insensitive searches\n"
"active.indicator=* # What to show as an active task indicator\n"
"tag.indicator=+ # What to show as a tag indicator\n"
"recurrence.indicator=R # What to show as a task recurrence indicator\n"
"recurrence.limit=1 # Number of future recurring pending tasks\n"
"undo.style=side # Undo style - can be 'side', or 'diff'\n"
"merge.autopush=ask # Push database to remote origin after merge: yes, no, ask\n"
"\n"
"# Dates\n"
"dateformat=m/d/Y # Preferred input and display date format\n"
"dateformat.holiday=YMD # Preferred input date format for holidays\n"
"dateformat.report=m/d/Y # Preferred display date format for reports\n"
"dateformat.annotation=m/d/Y # Preferred display date format for reports\n"
"weekstart=Sunday # Sunday or Monday only\n"
"displayweeknumber=yes # Show week numbers on calendar\n"
"due=7 # Task is considered due in 7 days\n"
"dateformat=m/d/Y # Preferred input and display date format\n"
"dateformat.holiday=YMD # Preferred input date format for holidays\n"
"dateformat.report=m/d/Y # Preferred display date format for reports\n"
"dateformat.annotation=m/d/Y # Preferred display date format for reports\n"
"weekstart=Sunday # Sunday or Monday only\n"
"displayweeknumber=yes # Show week numbers on calendar\n"
"due=7 # Task is considered due in 7 days\n"
"\n"
"# Calendar controls\n"
"calendar.legend=yes # Display the legend on calendar\n"
"calendar.details=sparse # Calendar shows information for tasks w/due dates: full, sparse or none\n"
"calendar.details.report=list # Report to use when showing task information in cal\n"
"calendar.holidays=none # Show public holidays on calendar:full, sparse or none\n"
"#monthsperline=3 # Number of calendar months on a line\n"
"calendar.legend=yes # Display the legend on calendar\n"
"calendar.details=sparse # Calendar shows information for tasks w/due dates: full, sparse or none\n"
"calendar.details.report=list # Report to use when showing task information in cal\n"
"calendar.holidays=none # Show public holidays on calendar:full, sparse or none\n"
"#monthsperline=3 # Number of calendar months on a line\n"
"\n"
"# Journal controls\n"
"journal.time=no # Record start/stop commands as annotation\n"
"journal.time.start.annotation=Started task # Annotation description for the start journal entry\n"
"journal.time.stop.annotation=Stopped task # Annotation description for the stop journal entry\n"
"journal.time=no # Record start/stop commands as annotation\n"
"journal.time.start.annotation=Started task # Annotation description for the start journal entry\n"
"journal.time.stop.annotation=Stopped task # Annotation description for the stop journal entry\n"
"\n"
"# Urgency Coefficients\n"
"urgency.next.coefficient=10.0 # Urgency coefficients for 'next' special tag\n"
"urgency.blocking.coefficient=9.0 # Urgency coefficients for blocking tasks\n"
"urgency.blocked.coefficient=8.0 # Urgency coefficients for blocked tasks\n"
"urgency.due.coefficient=7.0 # Urgency coefficients for due dates\n"
"urgency.priority.coefficient=6.0 # Urgency coefficients for priorities\n"
"urgency.waiting.coefficient=5.0 # Urgency coefficients for waiting status\n"
"urgency.active.coefficient=4.0 # Urgency coefficients for active tasks\n"
"urgency.project.coefficient=3.0 # Urgency coefficients for projects\n"
"urgency.tags.coefficient=2.0 # Urgency coefficients for tags\n"
"urgency.annotations.coefficient=1.0 # Urgency coefficients for annotations\n"
"urgency.next.coefficient=10.0 # Urgency coefficients for 'next' special tag\n"
"urgency.blocking.coefficient=9.0 # Urgency coefficients for blocking tasks\n"
"urgency.blocked.coefficient=8.0 # Urgency coefficients for blocked tasks\n"
"urgency.due.coefficient=7.0 # Urgency coefficients for due dates\n"
"urgency.priority.coefficient=6.0 # Urgency coefficients for priorities\n"
"urgency.waiting.coefficient=5.0 # Urgency coefficients for waiting status\n"
"urgency.active.coefficient=4.0 # Urgency coefficients for active tasks\n"
"urgency.project.coefficient=3.0 # Urgency coefficients for projects\n"
"urgency.tags.coefficient=2.0 # Urgency coefficients for tags\n"
"urgency.annotations.coefficient=1.0 # Urgency coefficients for annotations\n"
"\n"
"#urgency.user.project.foo.coefficient=5.0 # Urgency coefficients for 'foo' project\n"
"#urgency.user.tag.foo.coefficient=5.0 # Urgency coefficients for 'foo' tag\n"
"#urgency.user.project.foo.coefficient=5.0 # Urgency coefficients for 'foo' project\n"
"#urgency.user.tag.foo.coefficient=5.0 # Urgency coefficients for 'foo' tag\n"
"\n"
"# Color controls.\n"
"color=on # Enable color\n"
"color=on # Enable color\n"
#ifdef LINUX
"color.header=color3 # Color of header messages\n"
"color.footnote=color3 # Color of footnote messages\n"
"color.debug=color3 # Color of diagnostic output\n"
"color.header=color3 # Color of header messages\n"
"color.footnote=color3 # Color of footnote messages\n"
"color.debug=color3 # Color of diagnostic output\n"
"color.alternate=on color233 # Alternate color for line coloring\n"
"\n"
"color.summary.bar=on rgb141 # Color of summary report progress bar\n"
"color.summary.background=on color0 # Color of summary report background\n"
"color.summary.bar=on rgb141 # Color of summary report progress bar\n"
"color.summary.background=on color0 # Color of summary report background\n"
"\n"
"color.history.add=color0 on rgb500 # Color of added tasks in ghistory report\n"
"color.history.done=color0 on rgb050 # Color of completed tasks in ghistory report\n"
"color.history.delete=color0 on rgb550 # Color of deleted tasks in ghistory report\n"
"color.history.add=color0 on rgb500 # Color of added tasks in ghistory report\n"
"color.history.done=color0 on rgb050 # Color of completed tasks in ghistory report\n"
"color.history.delete=color0 on rgb550 # Color of deleted tasks in ghistory report\n"
"\n"
"color.undo.before=color1 # Color of values before a change\n"
"color.undo.after=color2 # Color of values after a change\n"
"color.undo.before=color1 # Color of values before a change\n"
"color.undo.after=color2 # Color of values after a change\n"
"\n"
"color.calendar.today=color15 on rgb013 # Color of today in calendar\n"
"color.calendar.due=color0 on color1 # Color of days with due tasks in calendar\n"
"color.calendar.due.today=color15 on color1 # Color of today with due tasks in calendar\n"
"color.calendar.overdue=color0 on color9 # Color of days with overdue tasks in calendar\n"
"color.calendar.weekend=color235 # Color of weekend days in calendar\n"
"color.calendar.holiday=color0 on color11 # Color of public holidays in calendar\n"
"color.calendar.weeknumber=rgb013 # Color of the weeknumbers in calendar\n"
"color.calendar.due=color0 on color1 # Color of days with due tasks in calendar\n"
"color.calendar.due.today=color15 on color1 # Color of today with due tasks in calendar\n"
"color.calendar.overdue=color0 on color9 # Color of days with overdue tasks in calendar\n"
"color.calendar.weekend=color235 # Color of weekend days in calendar\n"
"color.calendar.holiday=color0 on color11 # Color of public holidays in calendar\n"
"color.calendar.weeknumber=rgb013 # Color of the weeknumbers in calendar\n"
"\n"
"# The following rules are presented in their order of precedence.\n"
"# The higher the color rule is up this list, the higher precedence\n"
"# it has in determining the color for the task. Precedence is shown\n"
"# in brackets [1]\n"
"color.recurring=rgb013 # [1] Color of recur.any: tasks\n"
"color.overdue=color9 # [2] Color of overdue tasks\n"
"color.due.today=rgb400 # [3] Color of tasks due today\n"
"color.due=color1 # [4] Color of due tasks\n"
"#color.keyword.car=on blue # [5] Color of description.contains:car tasks\n"
"#color.project.garden=on green # [6] Color of project:garden tasks\n"
"#color.tag.bug=yellow # [7] Color of +bug tasks\n"
"color.active=rgb555 on rgb410 # [8] Color of active tasks\n"
"color.pri.none= # [9] Color of priority: tasks\n"
"color.pri.H=rgb255 # [9] Color of priority:H tasks\n"
"color.pri.M=rgb250 # [9] Color of priority:M tasks\n"
"color.pri.L=rgb245 # [9] Color of priority:L tasks\n"
"color.tagged=rgb031 # [10] Color of tagged tasks\n"
"color.blocked=black on white # [11] Color of blocked tasks\n"
"color.alternate=on color233 # [12] Alternate color for line coloring\n"
"# Here are the color rules.\n"
"color.recurring=rgb013 # Color of recur.any: tasks\n"
"color.overdue=color9 # Color of overdue tasks\n"
"color.due.today=rgb400 # Color of tasks due today\n"
"color.due=color1 # Color of due tasks\n"
"#color.keyword.car=on blue # Color of description.contains:car tasks\n"
"#color.project.garden=on green # Color of project:garden tasks\n"
"#color.project.none= # Color of tasks with no project\n"
"#color.tag.bug=yellow # Color of +bug tasks\n"
"#color.tag.none= # Color of tag-less tasks\n"
"color.active=rgb555 on rgb410 # Color of active tasks\n"
"color.pri.none= # Color of priority: tasks\n"
"color.pri.H=rgb255 # Color of priority:H tasks\n"
"color.pri.M=rgb250 # Color of priority:M tasks\n"
"color.pri.L=rgb245 # Color of priority:L tasks\n"
"color.tagged=rgb031 # Color of tagged tasks\n"
"color.blocked=black on white # Color of blocked tasks\n"
#else
"color.header=yellow # Color of header messages\n"
"color.footnote=yellow # Color of footnote messages\n"
"color.debug=yellow # Color of diagnostic output\n"
"color.header=yellow # Color of header messages\n"
"color.footnote=yellow # Color of footnote messages\n"
"color.debug=yellow # Color of diagnostic output\n"
"color.alternate= # Alternate color for line coloring\n"
"\n"
"color.summary.bar=on green # Color of summary report progress bar\n"
"color.summary.background=on black # Color of summary report background\n"
"color.summary.bar=on green # Color of summary report progress bar\n"
"color.summary.background=on black # Color of summary report background\n"
"\n"
"color.history.add=black on red # Color of added tasks in ghistory report\n"
"color.history.done=black on green # Color of completed tasks in ghistory report\n"
"color.history.delete=black on yellow # Color of deleted tasks in ghistory report\n"
"color.history.add=black on red # Color of added tasks in ghistory report\n"
"color.history.done=black on green # Color of completed tasks in ghistory report\n"
"color.history.delete=black on yellow # Color of deleted tasks in ghistory report\n"
"\n"
"color.undo.before=red # Color of values before a change\n"
"color.undo.after=green # Color of values after a change\n"
"color.undo.before=red # Color of values before a change\n"
"color.undo.after=green # Color of values after a change\n"
"\n"
"color.calendar.today=bold white on bright blue # Color of today in calendar\n"
"color.calendar.due=white on red # Color of days with due tasks in calendar\n"
"color.calendar.due.today=bold white on red # Color of today with due tasks in calendar\n"
"color.calendar.overdue=black on bright red # Color of days with overdue tasks in calendar\n"
"color.calendar.weekend=white on bright black # Color of weekend days in calendar\n"
"color.calendar.holiday=black on bright yellow # Color of public holidays in calendar\n"
"color.calendar.weeknumber=bold blue # Color of the weeknumbers in calendar\n"
"color.calendar.due=white on red # Color of days with due tasks in calendar\n"
"color.calendar.due.today=bold white on red # Color of today with due tasks in calendar\n"
"color.calendar.overdue=black on bright red # Color of days with overdue tasks in calendar\n"
"color.calendar.weekend=white on bright black # Color of weekend days in calendar\n"
"color.calendar.holiday=black on bright yellow # Color of public holidays in calendar\n"
"color.calendar.weeknumber=bold blue # Color of the weeknumbers in calendar\n"
"\n"
"# The following rules are presented in their order of precedence.\n"
"# The higher the color rule is up this list, the higher precedence\n"
"# it has in determining the color for the task. Precedence is shown\n"
"# in brackets [1]\n"
"color.recurring=magenta # [1] Color of recur.any: tasks\n"
"color.overdue=bold red # [2] Color of overdue tasks\n"
"color.due.today=red # [3] Color of tasks due today\n"
"color.due=red # [4] Color of due tasks\n"
"#color.keyword.car=on blue # [5] Color of description.contains:car tasks\n"
"#color.project.garden=on green # [6] Color of project:garden tasks\n"
"#color.tag.bug=yellow # [7] Color of +bug tasks\n"
"color.active=black on bright green # [8] Color of active tasks\n"
"color.pri.none= # [9] Color of priority: tasks\n"
"color.pri.H=bold white # [9] Color of priority:H tasks\n"
"color.pri.M=white # [9] Color of priority:M tasks\n"
"color.pri.L= # [9] Color of priority:L tasks\n"
"color.tagged=green # [10] Color of tagged tasks\n"
"color.blocked=black on white # [11] Color of blocked tasks\n"
"color.alternate= # [12] Alternate color for line coloring\n"
"# Here are the color rules.\n"
"color.recurring=magenta # Color of recur.any: tasks\n"
"color.overdue=bold red # Color of overdue tasks\n"
"color.due.today=red # Color of tasks due today\n"
"color.due=red # Color of due tasks\n"
"#color.keyword.car=on blue # Color of description.contains:car tasks\n"
"#color.project.garden=on green # Color of project:garden tasks\n"
"#color.project.none= # Color of tasks with no project\n"
"#color.tag.bug=yellow # Color of +bug tasks\n"
"#color.tag.none= # Color of tag-less tasks\n"
"color.active=black on bright green # Color of active tasks\n"
"color.pri.none= # Color of priority: tasks\n"
"color.pri.H=bold white # Color of priority:H tasks\n"
"color.pri.M=white # Color of priority:M tasks\n"
"color.pri.L= # Color of priority:L tasks\n"
"color.tagged=green # Color of tagged tasks\n"
"color.blocked=black on white # Color of blocked tasks\n"
#endif
"\n"
"# Here is the rule precedence order, highest to lowest.\n"
"# Note that these are just the color rule names, without the leading 'color.'\n"
"# and any trailing '.value'.\n"
"rule.precedence.color=due.today,active,blocked,overdue,due,keyword,project,tag,recurring,pri,tagged\n"
"\n"
"# Shadow file support\n"
"#shadow.file=/tmp/shadow.txt # Location of shadow file\n"
"#shadow.command=list # Task command for shadow file\n"
"#shadow.notify=on # Footnote when updated\n"
"#shadow.file=/tmp/shadow.txt # Location of shadow file\n"
"#shadow.command=list # Task command for shadow file\n"
"#shadow.notify=on # Footnote when updated\n"
"\n"
"#default.project=foo # Default project for 'add' command\n"
"#default.priority=M # Default priority for 'add' command\n"
"default.command=list # When no arguments are specified\n"
"#default.project=foo # Default project for 'add' command\n"
"#default.priority=M # Default priority for 'add' command\n"
"default.command=list # When no arguments are specified\n"
"\n"
"_forcecolor=no # Forces color to be on, even for non TTY output\n"
"blanklines=true # Use more whitespace in output\n"
"complete.all.projects=no # Include old project names in '_projects' command\n"
"complete.all.tags=no # Include old tag names in '_ags' command\n"
"list.all.projects=no # Include old project names in 'projects' command\n"
"list.all.tags=no # Include old tag names in 'tags' command\n"
"debug=no # Display diagnostics\n"
"hooks=off # Hook system master switch\n"
"fontunderline=yes # Uses underlines rather than -------\n"
"shell.prompt=task> # Prompt used by the shell command\n"
"_forcecolor=no # Forces color to be on, even for non TTY output\n"
"blanklines=true # Use more whitespace in output\n"
"complete.all.projects=no # Include old project names in '_projects' command\n"
"complete.all.tags=no # Include old tag names in '_ags' command\n"
"list.all.projects=no # Include old project names in 'projects' command\n"
"list.all.tags=no # Include old tag names in 'tags' command\n"
"debug=no # Display diagnostics\n"
"hooks=off # Hook system master switch\n"
"fontunderline=yes # Uses underlines rather than -------\n"
"shell.prompt=task> # Prompt used by the shell command\n"
"\n"
"# Import heuristics - alternate names for fields (comma-separated list of names)\n"
"#import.synonym.bg=?\n"
@ -243,14 +246,14 @@ std::string Config::defaults =
"#import.synonym.uuid=?\n"
"\n"
"# Export Controls\n"
"export.ical.class=PRIVATE # Could be PUBLIC, PRIVATE or CONFIDENTIAL\n"
"export.ical.class=PRIVATE # Could be PUBLIC, PRIVATE or CONFIDENTIAL\n"
"\n"
"# Aliases - alternate names for commands\n"
"alias.rm=delete # Alias for the delete command\n"
"alias.history=history.monthly # Prefer monthly over annual history reports\n"
"alias.ghistory=ghistory.monthly # Prefer monthly graphical over annual history reports\n"
"alias.export=export.yaml # Prefer YAML over CSV or iCal export\n"
"alias.export.vcalendar=export.ical # They are the same\n"
"alias.rm=delete # Alias for the delete command\n"
"alias.history=history.monthly # Prefer monthly over annual history reports\n"
"alias.ghistory=ghistory.monthly # Prefer monthly graphical over annual history reports\n"
"alias.export=export.yaml # Prefer YAML over CSV or iCal export\n"
"alias.export.vcalendar=export.ical # They are the same\n"
"\n"
"# Fields: id, uuid, project, priority, priority_long, entry, start, end, due\n"
"# countdown, countdown_compact, age, age_compact, active, tags,\n"
@ -396,6 +399,7 @@ std::string Config::defaults =
//
// In all real use cases, Config::load is called.
Config::Config ()
: original_file ()
{
}

View file

@ -125,8 +125,6 @@ void Context::initialize ()
if (locale != "")
stringtable.load (location.data + "/strings." + locale);
// TODO Handle "--version, -v" right here?
// init TDB.
tdb.clear ();
std::vector <std::string> all;

View file

@ -812,6 +812,7 @@ int handleShow (std::string &outs)
"import.synonym.id import.synonym.uuid complete.all.projects complete.all.tags "
"search.case.sensitive hooks active.indicator tag.indicator recurrence.indicator "
"recurrence.limit list.all.projects list.all.tags undo.style verbose "
"rule.precedence.color "
#ifdef FEATURE_SHELL
"shell.prompt "
#endif
@ -2032,7 +2033,7 @@ int handleColor (std::string &outs)
// actual colors.
if (*item != "_forcecolor" &&
*item != "color" &&
item->find ("color") != std::string::npos)
item->find ("color") == 0)
{
int row = table.addRow ();
table.addCell (row, 0, *item);

View file

@ -154,11 +154,15 @@ bool dependencyChainBroken (Task& task)
std::string dependencyNag (Task& task)
{
std::stringstream out;
out << "# dependencyNag "
<< task.id
<< " "
<< task.get ("uuid")
<< "\n";
if (task.has ("depends"))
{
out << "# dependencyNag "
<< task.id
<< " "
<< task.get ("uuid")
<< "\n";
}
return out.str ();
}

View file

@ -114,6 +114,8 @@ void handleRecurrence ()
sprintf (indexMask, "%u", (unsigned int) i);
rec.set ("imask", indexMask); // Store index into mask.
rec.remove ("mask"); // Remove the mask of the parent.
// Add the new task to the vector, for immediate use.
modified.push_back (rec);

View file

@ -470,49 +470,45 @@ int handleInfo (std::string &outs)
}
}
if (task->getStatus () == Task::recurring ||
task->has ("parent"))
// recur
if (task->has ("recur"))
{
// recur
if (task->has ("recur"))
{
row = table.addRow ();
table.addCell (row, 0, "Recurrence");
value = task->get ("recur");
context.hooks.trigger ("format-recur", "recur", value);
table.addCell (row, 1, value);
}
row = table.addRow ();
table.addCell (row, 0, "Recurrence");
value = task->get ("recur");
context.hooks.trigger ("format-recur", "recur", value);
table.addCell (row, 1, value);
}
// until
if (task->has ("until"))
{
row = table.addRow ();
table.addCell (row, 0, "Recur until");
// until
if (task->has ("until"))
{
row = table.addRow ();
table.addCell (row, 0, "Recur until");
Date dt (atoi (task->get ("until").c_str ()));
std::string format = context.config.get ("reportdateformat");
if (format == "")
format = context.config.get ("dateformat");
Date dt (atoi (task->get ("until").c_str ()));
std::string format = context.config.get ("reportdateformat");
if (format == "")
format = context.config.get ("dateformat");
std::string until = getDueDate (*task, format);
table.addCell (row, 1, until);
}
std::string until = getDueDate (*task, format);
table.addCell (row, 1, until);
}
// mask
if (task->has ("mask"))
{
row = table.addRow ();
table.addCell (row, 0, "Mask");
table.addCell (row, 1, task->get ("mask"));
}
// mask
if (task->getStatus () == Task::recurring)
{
row = table.addRow ();
table.addCell (row, 0, "Mask");
table.addCell (row, 1, task->get ("mask"));
}
if (task->has ("parent"))
{
// parent
if (task->has ("parent"))
{
row = table.addRow ();
table.addCell (row, 0, "Parent task");
table.addCell (row, 1, task->get ("parent"));
}
row = table.addRow ();
table.addCell (row, 0, "Parent task");
table.addCell (row, 1, task->get ("parent"));
// imask
row = table.addRow ();
@ -759,7 +755,7 @@ int handleReportSummary (std::string &outs)
table.addCell (row, 0, (i->first == "" ? "(none)" : i->first));
table.addCell (row, 1, countPending[i->first]);
if (counter[i->first])
table.addCell (row, 2, Duration ((int) sumEntry[i->first] / counter[i->first]).format ());
table.addCell (row, 2, Duration ((int) (sumEntry[i->first] / (double)counter[i->first])).format ());
int c = countCompleted[i->first];
int p = countPending[i->first];

View file

@ -36,137 +36,251 @@
extern Context context;
static std::map <std::string, Color> gsColor;
static std::vector <std::string> gsPrecedence;
////////////////////////////////////////////////////////////////////////////////
void initializeColorRules ()
{
std::vector <std::string> ruleNames;
context.config.all (ruleNames);
foreach (it, ruleNames)
gsColor.clear ();
gsPrecedence.clear ();
// Load all the configuration values, filter to only the ones that begin with
// "color.", then store name/value in gsColor, and name in rules.
std::vector <std::string> rules;
std::vector <std::string> variables;
context.config.all (variables);
foreach (it, variables)
{
if (it->substr (0, 6) == "color.")
{
Color c (context.config.get (*it));
gsColor[*it] = c;
rules.push_back (*it);
}
}
// Load the rule.precedence.color list, split it, then autocomplete against
// the 'rules' vector loaded above.
std::vector <std::string> results;
std::vector <std::string> precedence;
split (precedence, context.config.get ("rule.precedence.color"), ',');
foreach (it, precedence)
{
// Add the leading "color." string.
std::string rule = "color." + *it;
autoComplete (rule, rules, results);
foreach (r, results)
gsPrecedence.push_back (*r);
}
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeBlocked (Task& task, const std::string& rule, Color& c)
{
if (gsColor[rule].nontrivial ())
if (task.get ("depends") != "")
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeTagged (Task& task, const std::string& rule, Color& c)
{
if (gsColor[rule].nontrivial ())
if (task.getTagCount ())
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizePriorityL (Task& task, const std::string& rule, Color& c)
{
if (gsColor[rule].nontrivial ())
if (task.get ("priority") == "L")
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizePriorityM (Task& task, const std::string& rule, Color& c)
{
if (gsColor[rule].nontrivial ())
if (task.get ("priority") == "M")
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizePriorityH (Task& task, const std::string& rule, Color& c)
{
if (gsColor[rule].nontrivial ())
if (task.get ("priority") == "H")
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizePriorityNone (Task& task, const std::string& rule, Color& c)
{
if (gsColor[rule].nontrivial ())
if (task.get ("priority") == "")
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeActive (Task& task, const std::string& rule, Color& c)
{
Task::status status = task.getStatus ();
if (gsColor[rule].nontrivial () &&
status != Task::completed &&
status != Task::deleted &&
task.has ("start"))
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeTag (Task& task, const std::string& rule, Color& c)
{
if (task.hasTag (rule.substr (10)))
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeProject (Task& task, const std::string& rule, Color& c)
{
// Observe the case sensitivity setting.
bool sensitive = context.config.getBoolean ("search.case.sensitive");
if (compare (task.get ("project"), rule.substr (14), sensitive))
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeProjectNone (Task& task, const std::string& rule, Color& c)
{
if (task.get ("project") == "")
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeTagNone (Task& task, const std::string& rule, Color& c)
{
if (task.getTagCount () == 0)
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeKeyword (Task& task, const std::string& rule, Color& c)
{
// Observe the case sensitivity setting.
bool sensitive = context.config.getBoolean ("search.case.sensitive");
// The easiest thing to check is the description, because it is just one
// attribute.
if (find (task.get ("description"), rule.substr (14), sensitive) != std::string::npos)
c.blend (gsColor[rule]);
// Failing the description check, look at all annotations, returning on the
// first match.
else
{
Task::iterator it;
for (it = task.begin (); it != task.end (); ++it)
{
if (it->first.substr (0, 11) == "annotation_" &&
find (it->second.value (), rule.substr (14), sensitive) != std::string::npos)
{
c.blend (gsColor[rule]);
return;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
void autoColorize (Task& task, Color& c)
static void colorizeDue (Task& task, const std::string& rule, Color& c)
{
// The special tag 'nocolor' overrides all auto colorization.
if (task.hasTag ("nocolor"))
return;
// Note: fg, bg already contain colors specifically assigned via command.
// Note: These rules form a hierarchy - the last rule is King.
Task::status status = task.getStatus ();
// Colorization of the blocked.
if (gsColor["color.blocked"].nontrivial ())
if (task.get ("depends") != "")
c.blend (gsColor["color.blocked"]);
// Colorization of the tagged.
if (gsColor["color.tagged"].nontrivial ())
if (task.getTagCount ())
c.blend (gsColor["color.tagged"]);
// Colorization of the low priority.
if (gsColor["color.pri.L"].nontrivial ())
if (task.get ("priority") == "L")
c.blend (gsColor["color.pri.L"]);
// Colorization of the medium priority.
if (gsColor["color.pri.M"].nontrivial ())
if (task.get ("priority") == "M")
c.blend (gsColor["color.pri.M"]);
// Colorization of the high priority.
if (gsColor["color.pri.H"].nontrivial ())
if (task.get ("priority") == "H")
c.blend (gsColor["color.pri.H"]);
// Colorization of the priority-less.
if (gsColor["color.pri.none"].nontrivial ())
if (task.get ("priority") == "")
c.blend (gsColor["color.pri.none"]);
// Colorization of the active, if not completed/deleted.
if (gsColor["color.active"].nontrivial () &&
status != Task::completed &&
status != Task::deleted)
if (task.has ("start"))
c.blend (gsColor["color.active"]);
// Colorization by tag value.
std::map <std::string, Color>::iterator it;
for (it = gsColor.begin (); it != gsColor.end (); ++it)
{
if (it->first.substr (0, 10) == "color.tag.")
{
std::string value = it->first.substr (10);
if (task.hasTag (value))
c.blend (it->second);
}
}
// Colorization by project name.
for (it = gsColor.begin (); it != gsColor.end (); ++it)
{
if (it->first.substr (0, 14) == "color.project.")
{
std::string value = lowerCase (it->first.substr (14));
std::string project = lowerCase (task.get ("project"));
if (project.find (value) == 0)
c.blend (it->second);
}
}
// Colorization by keyword.
for (it = gsColor.begin (); it != gsColor.end (); ++it)
{
if (it->first.substr (0, 14) == "color.keyword.")
{
std::string value = lowerCase (it->first.substr (14));
std::string desc = lowerCase (task.get ("description"));
if (desc.find (value) != std::string::npos)
c.blend (it->second);
}
}
// Colorization of the due and overdue.
if (task.has ("due") &&
status != Task::completed &&
status != Task::deleted)
{
std::string due = task.get ("due");
switch (getDueState (due))
{
case 1: // imminent
c.blend (gsColor["color.due"]);
break;
if (getDueState (task.get ("due")) == 1)
c.blend (gsColor[rule]);
}
}
case 2: // today
c.blend (gsColor["color.due.today"]);
break;
////////////////////////////////////////////////////////////////////////////////
static void colorizeDueToday (Task& task, const std::string& rule, Color& c)
{
Task::status status = task.getStatus ();
case 3: // overdue
c.blend (gsColor["color.overdue"]);
break;
if (task.has ("due") &&
status != Task::completed &&
status != Task::deleted)
{
if (getDueState (task.get ("due")) == 2)
c.blend (gsColor[rule]);
}
}
case 0: // not due at all
default:
break;
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeOverdue (Task& task, const std::string& rule, Color& c)
{
Task::status status = task.getStatus ();
if (task.has ("due") &&
status != Task::completed &&
status != Task::deleted)
{
if (getDueState (task.get ("due")) == 3)
c.blend (gsColor[rule]);
}
}
////////////////////////////////////////////////////////////////////////////////
static void colorizeRecurring (Task& task, const std::string& rule, Color& c)
{
if (gsColor[rule].nontrivial ())
if (task.has ("recur"))
c.blend (gsColor[rule]);
}
////////////////////////////////////////////////////////////////////////////////
void autoColorize (Task& task, Color& c)
{
// The special tag 'nocolor' overrides all auto and specific colorization.
if (task.hasTag ("nocolor"))
{
c = Color ();
return;
}
// Colorization of the recurring.
if (gsColor["color.recurring"].nontrivial ())
if (task.has ("recur"))
c.blend (gsColor["color.recurring"]);
// Note: c already contains colors specifically assigned via command.
// Note: These rules form a hierarchy - the last rule is King, hence the
// reverse iterator.
std::vector <std::string>::reverse_iterator r;
for (r = gsPrecedence.rbegin (); r != gsPrecedence.rend (); ++r)
{
if (*r == "color.blocked") colorizeBlocked (task, *r, c);
else if (*r == "color.tagged") colorizeTagged (task, *r, c);
else if (*r == "color.pri.L") colorizePriorityL (task, *r, c);
else if (*r == "color.pri.M") colorizePriorityM (task, *r, c);
else if (*r == "color.pri.H") colorizePriorityH (task, *r, c);
else if (*r == "color.pri.none") colorizePriorityNone (task, *r, c);
else if (*r == "color.active") colorizeActive (task, *r, c);
else if (*r == "color.project.none") colorizeProjectNone (task, *r, c);
else if (*r == "color.tag.none") colorizeTagNone (task, *r, c);
else if (*r == "color.due") colorizeDue (task, *r, c);
else if (*r == "color.due.today") colorizeDueToday (task, *r, c);
else if (*r == "color.overdue") colorizeOverdue (task, *r, c);
else if (*r == "color.recurring") colorizeRecurring (task, *r, c);
// Wildcards
else if (r->substr (0, 9) == "color.tag") colorizeTag (task, *r, c);
else if (r->substr (0, 13) == "color.project") colorizeProject (task, *r, c);
else if (r->substr (0, 13) == "color.keyword") colorizeKeyword (task, *r, c);
}
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -28,7 +28,7 @@
use strict;
use warnings;
use Test::More tests => 13;
use Test::More tests => 40;
# Create the rc file.
if (open my $fh, '>', 'bug.rc')
@ -59,6 +59,67 @@ $output = qx{../task rc:bug.rc long -\@strange};
like ($output, qr/one/, '+ordinary implicitly included');
unlike ($output, qr/two/, '@strange explicitly excluded');
# Bug #XXX - '-t1 -t2' doesn't seem to work, when @ characters are involved.
unlink 'pending.data';
qx{../task rc:bug.rc add one +t1};
qx{../task rc:bug.rc add two +t2};
qx{../task rc:bug.rc add three +t3};
my $output = qx{../task rc:bug.rc list -t1};
unlike ($output, qr/one/, 'Single: no t1');
like ($output, qr/two/, 'Single: yes t2');
like ($output, qr/three/, 'Single: yes t3');
$output = qx{../task rc:bug.rc list -t1 -t2};
unlike ($output, qr/one/, 'Double: no t1');
unlike ($output, qr/two/, 'Double: no t2');
like ($output, qr/three/, 'Double: yes t3');
$output = qx{../task rc:bug.rc list -t1 -t2 -t3};
unlike ($output, qr/one/, 'Triple: no t1');
unlike ($output, qr/two/, 'Triple: no t2');
unlike ($output, qr/three/, 'Triple: no t3');
# Once again, with @ characters.
qx{../task rc:bug.rc 1 +\@1};
qx{../task rc:bug.rc 2 +\@2};
qx{../task rc:bug.rc 3 +\@3};
$output = qx{../task rc:bug.rc list -\@1};
unlike ($output, qr/one/, 'Single: no @1');
like ($output, qr/two/, 'Single: yes @2');
like ($output, qr/three/, 'Single: yes @3');
$output = qx{../task rc:bug.rc list -\@1 -\@2};
unlike ($output, qr/one/, 'Double: no @1');
unlike ($output, qr/two/, 'Double: no @2');
like ($output, qr/three/, 'Double: yes @3');
$output = qx{../task rc:bug.rc list -\@1 -\@2 -\@3};
unlike ($output, qr/one/, 'Triple: no @1');
unlike ($output, qr/two/, 'Triple: no @2');
unlike ($output, qr/three/, 'Triple: no @3');
# Once again, with @ characters and punctuation.
qx{../task rc:bug.rc 1 +\@foo.1};
qx{../task rc:bug.rc 2 +\@foo.2};
qx{../task rc:bug.rc 3 +\@foo.3};
$output = qx{../task rc:bug.rc list -\@foo.1};
unlike ($output, qr/one/, 'Single: no @foo.1');
like ($output, qr/two/, 'Single: yes @foo.2');
like ($output, qr/three/, 'Single: yes @foo.3');
$output = qx{../task rc:bug.rc list -\@foo.1 -\@foo.2};
unlike ($output, qr/one/, 'Double: no @foo.1');
unlike ($output, qr/two/, 'Double: no @foo.2');
like ($output, qr/three/, 'Double: yes @foo.3');
$output = qx{../task rc:bug.rc list -\@foo.1 -\@foo.2 -\@foo.3};
unlike ($output, qr/one/, 'Triple: no @foo.1');
unlike ($output, qr/two/, 'Triple: no @foo.2');
unlike ($output, qr/three/, 'Triple: no @foo.3');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');

66
src/tests/bug.485.x Executable file
View file

@ -0,0 +1,66 @@
#! /usr/bin/perl
################################################################################
## taskwarrior - a command line task list manager.
##
## Copyright 2006 - 2010, Paul Beckingham.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 2 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, write to the
##
## Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor,
## Boston, MA
## 02110-1301
## USA
##
################################################################################
use strict;
use warnings;
use Test::More tests => 9;
# Create the rc file.
if (open my $fh, '>', 'bug.rc')
{
print $fh "data.location=.\n";
close $fh;
ok (-r 'bug.rc', 'Created bug.rc');
}
# Bug #485 - 'task list recur:month' doesn't list monthly tasks
qx{../task rc:bug.rc add one due:tomorrow recur:monthly};
qx{../task rc:bug.rc add two due:tomorrow recur:month};
my $output = qx{../task rc:bug.rc list recur:monthly};
like ($output, qr/one/, 'monthly -> monthly');
like ($output, qr/two/, 'month -> monthly');
$output = qx{../task rc:bug.rc list recur:month};
like ($output, qr/one/, 'monthly -> month');
like ($output, qr/two/, 'month -> month');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');
unlink 'completed.data';
ok (!-r 'completed.data', 'Removed completed.data');
unlink 'undo.data';
ok (!-r 'undo.data', 'Removed undo.data');
unlink 'bug.rc';
ok (!-r 'bug.rc', 'Removed bug.rc');
exit 0;

View file

@ -2,7 +2,7 @@
################################################################################
## taskwarrior - a command line task list manager.
##
## Copyright 2006 - 2010, Paul Beckingham.
## Copyright 2006 - 2010, Paul Beckingham, Federico Hernandez.
## All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it under
@ -28,15 +28,18 @@
use strict;
use warnings;
use Test::More tests => 8;
use Test::More tests => 9;
# Create the rc file.
if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"search.case.sensitive=yes\n",
"color=on\n",
"color.alternate=\n",
"color.keyword.red=red\n",
"color.keyword.green=green\n",
"color.keyword.yellow=yellow\n",
"_forcecolor=1\n";
close $fh;
ok (-r 'color.rc', 'Created color.rc');
@ -46,11 +49,14 @@ if (open my $fh, '>', 'color.rc')
qx{../task rc:color.rc add nothing};
qx{../task rc:color.rc add red};
qx{../task rc:color.rc add green};
qx{../task rc:color.rc add -- annotation};
qx{../task rc:color.rc 4 annotate yellow};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.keyword.red');
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.keyword.green');
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.keyword.red');
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.keyword.green');
like ($output, qr/ \033\[33m .* annotation .* \033\[0m /x, 'color.keyword.yellow (annotation)');
# Cleanup.
unlink 'pending.data';

View file

@ -35,6 +35,7 @@ if (open my $fh, '>', 'color.rc')
{
print $fh "data.location=.\n",
"color.project.x=red\n",
"color.project.none=green\n",
"color.alternate=\n",
"_forcecolor=1\n";
close $fh;
@ -46,7 +47,7 @@ qx{../task rc:color.rc add nothing};
qx{../task rc:color.rc add project:x red};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[32m .* nothing .* \033\[0m /x, 'color.project.none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.project.red');
# Cleanup.

View file

@ -36,6 +36,7 @@ if (open my $fh, '>', 'color.rc')
print $fh "data.location=.\n",
"color.tagged=\n",
"color.alternate=\n",
"color.tag.none=yellow\n",
"color.tag.red=red\n",
"color.tag.green=green\n",
"_forcecolor=1\n";
@ -49,7 +50,7 @@ qx{../task rc:color.rc add +red red};
qx{../task rc:color.rc add +green green};
my $output = qx{../task rc:color.rc list};
like ($output, qr/ (?!<\033\[\d\dm) .* nothing .* (?!>\033\[0m) /x, 'none');
like ($output, qr/ \033\[33m .* nothing .* \033\[0m /x, 'color.tag.none');
like ($output, qr/ \033\[31m .* red .* \033\[0m /x, 'color.tag.red');
like ($output, qr/ \033\[32m .* green .* \033\[0m /x, 'color.tag.green');

View file

@ -28,7 +28,7 @@
use strict;
use warnings;
use Test::More tests => 7;
use Test::More tests => 9;
# Create the rc file.
if (open my $fh, '>', 'due.rc')
@ -57,6 +57,13 @@ my $output = qx{../task rc:due.rc list};
like ($output, qr/\[31m.+$just.+\[0m/, 'one marked due');
like ($output, qr/\s+$almost\s+/, 'two not marked due');
qx{../task rc:due.rc add three due:today};
$output = qx{../task rc:due.rc list due:today};
like ($output, qr/three/, 'due:today works as a filter');
$output = qx{../task rc:due.rc list due.is:today};
like ($output, qr/three/, 'due.is:today works as a filter');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');

View file

@ -71,8 +71,8 @@ qx{../task rc:wait.rc add wait:tomorrow tomorrow};
$output = qx{../task rc:wait.rc ls};
unlike ($output, qr/tomorrow/ms, 'waiting task invisible');
$output = qx{../task rc:wait.rc ls wait:tomorrow};
like ($output, qr/tomorrow/ms, 'waiting task visible when specifically asked for it');
$output = qx{../task rc:wait.rc all status:waiting wait:tomorrow};
like ($output, qr/tomorrow/ms, 'waiting task visible when specifically queried');
# Cleanup.
unlink 'pending.data';