- added displaying of holidays in 'task cal'
  via calendar.holidays
- the legend in the calendar can now be turned off
- weeknumbers in the calendar can now be color-coded
This commit is contained in:
Federico Hernandez 2010-01-22 01:42:32 +01:00
parent f6f84aaf42
commit a7244a999e
5 changed files with 247 additions and 73 deletions

View file

@ -167,6 +167,7 @@ according to dateformat.
The default value is: m/d/Y. The string should contain the characters
.RS
.RS
m minimal-digit month, for example 1 or 12
.br
@ -190,10 +191,14 @@ B long name of month, for example January or August
.br
V weeknumber, for example 03 or 37
.RE
.RE
.RS
The string may also contain other characters to act as spacers, or formatting. Examples for other
values of dateformat:
.RE
.RS
.RS
.br
d/m/Y would use for input and output 24/7/2009
@ -202,9 +207,13 @@ yMD would use for input and output 090724
.br
M-D-Y would use for input and output 07-24-2009
.RE
.RE
.RS
Examples for other values of reportdateformat:
.RE
.RS
.RS
.br
a D b Y (V) would do an output as "Fri 24 Jul 2009 (30)"
@ -213,6 +222,7 @@ A, B D, Y would do an output as "Friday, July 24, 2009"
.br
vV a Y-M-D would do an output as "v30 Fri 2009-07.24"
.RE
.RE
.TP
.B weekstart=Sunday
@ -228,14 +238,48 @@ The week number is dependent on the day a week starts.
This is the number of days into the future that define when a task is considered due,
and is colored accordingly. Defaults to 7.
.TP calendar.details=no
If set to yes running "task calendar" will display the details of tasks with due dates
that fall into the calendar period.
.TP
.B calendar.details=sparse
If set to full running "task calendar" will display the details of tasks with due dates
that fall into the calendar period. The corresponding days will be color-coded in the
calendar. If set to sparse only the corresponding days will be color coded and no details
will be displayed. The displaying of due dates with details is turned off by setting the
variable to none.
.TP calendar.details.report=list
.TP
.B calendar.details.report=list
The report to run when displaying the details of tasks with due date when running the
"task calendar" command.
.TP
.B calendar.holidays=full
If set to full running "task calendar" will display holidays in the calendar by color-coding
the corresponding days. A detailed list with the dates and names of the holidays is also shown.
If set to sparse only the days are color-coded and no details on the holidays will be
displayed. The displaying of holidays is turned off by setting the variable to none.
.TP
.B Holidays
Holidays are entered either directly in the .taskrc file or via an include file that is specified
in .taskrc. For each holiday the name and the date is required to be given:
.RS
.RS
.br
holiday.towel.name=Day of the towel
.br
holiday.towel.date=20100525
.br
holiday.sysadmin.name=System Administrator Appreciation Day
.br
holiday.sysadmin.date=20100730
.RE
.RE
.RS
Dates are to be entered according to the setting in the dateformat variable.
.RE
.TP
.B monthsperline=2
Determines how many months the "task calendar" command renders across the screen.
@ -351,8 +395,16 @@ Color of days with due tasks in calendar.
Color of days with overdue tasks in calendar.
.TP
.B color.calendar.weekend=black on white
.B color.calendar.weekend=bright white on black
Color of weekend days in calendar.
.TP
.B color.calendar.holiday=black on bright yellow
Color of holidays in calendar.
.TP
.B color.calendar.weeknumber=black on white
Color of weeknumbers in calendar.
.RE
.SS SHADOW FILE

View file

@ -70,8 +70,10 @@ std::string Config::defaults =
"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"
"#calendar.details=yes # Calendar shows information for tasks w/due dates\n"
"calendar.legend=yes # Display the legend on calendar\n"
"#calendar.details=full # Calendar shows information for tasks w/due dates\n"
"#calendar.details.report=list # Report to use when showing task information in cal\n"
"#calendar.holidays=none # Show public holidays on calendar\n"
"#monthsperline=3 # Number of calendar months on a line\n" // TODO
"\n"
"# Color controls.\n"
@ -94,12 +96,10 @@ std::string Config::defaults =
"color.calendar.today=black on cyan # Color of today in calendar\n"
"color.calendar.due=black on green # Color of days with due tasks in calendar\n"
"color.calendar.overdue=black on red # Color of days with overdue tasks in calendar\n"
"color.calendar.weekend=black on white # Color of weekend days in calendar\n"
"color.calendar.weekend=bright white on 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=black on white # Color of the weeknumbers in calendar\n"
"#color.debug=magenta # Color of diagnostic output\n"
"color.pri.H=bold # Color of priority:H tasks\n"
"color.history.add=on red # Color of added tasks in the history reports\n"
"color.history.delete=on yellow # Color of deleted tasks in the history reports\n"
"color.history.done=on green # Color of completed tasks in the history reports\n"
"\n"
"# Shadow file support\n"
"#shadow.file=/tmp/shadow.txt # Location of shadow file\n"

View file

@ -649,15 +649,15 @@ int handleConfig (std::string &outs)
// These are the regular configuration variables.
// Note that there is a leading and trailing space, to make searching easier.
std::string recognized =
" annotations blanklines bulk calendar.details calendar.details.report color "
"color.active color.due color.overdue color.pri.H color.pri.L color.pri.M color.pri.none "
"color.recurring color.tagged color.footnote color.header color.debug color.alternate "
"color.calendar.today color.calendar.due color.calendar.overdue color.calendar.weekend "
"confirmation curses data.location dateformat reportdateformat debug default.command "
"default.priority default.project defaultwidth due locale displayweeknumber "
"echo.command locking monthsperline nag next project shadow.command shadow.file "
"shadow.notify weekstart editor import.synonym.id import.synonym.uuid "
"complete.all.projects complete.all.tags "
" annotations blanklines bulk calendar.details calendar.details.report calendar.holidays "
"calendar.legend color color.active color.due color.overdue color.pri.H color.pri.L "
"color.pri.M color.pri.none color.recurring color.tagged color.footnote color.header "
"color.debug color.alternate color.calendar.today color.calendar.due color.calendar.overdue "
"color.calendar.weekend color.calendar.holiday color.calendar.weeknumber confirmation "
"curses data.location dateformat reportdateformat debug default.command default.priority "
"default.project defaultwidth due locale displayweeknumber echo.command fontunderline "
"locking monthsperline nag next project shadow.command shadow.file shadow.notify weekstart "
"editor import.synonym.id import.synonym.uuid complete.all.projects complete.all.tags "
#ifdef FEATURE_SHELL
"shell.prompt "
#endif
@ -684,6 +684,7 @@ int handleConfig (std::string &outs)
if (i->substr (0, 14) != "color.keyword." &&
i->substr (0, 14) != "color.project." &&
i->substr (0, 10) != "color.tag." &&
i->substr (0, 8) != "holiday." &&
i->substr (0, 7) != "report." &&
i->substr (0, 6) != "alias.")
{

View file

@ -1416,6 +1416,13 @@ std::string renderMonths (
int row = 0;
Color color_today (context.config.get ("color.calendar.today"));
Color color_due (context.config.get ("color.calendar.due"));
Color color_overdue (context.config.get ("color.calendar.overdue"));
Color color_weekend (context.config.get ("color.calendar.weekend"));
Color color_holiday (context.config.get ("color.calendar.holiday"));
Color color_weeknumber (context.config.get ("color.calendar.weeknumber"));
// Loop through months to be added on this line.
for (int mpl = 0; mpl < monthsPerLine ; mpl++)
{
@ -1431,7 +1438,11 @@ std::string renderMonths (
int woy = temp.weekOfYear (weekStart);
if (context.config.getBoolean ("displayweeknumber"))
{
table.addCell (row, (8 * mpl), woy);
if (context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor"))
table.setCellColor (row, (8 * mpl), color_weeknumber);
}
// Calculate column id.
int thisCol = dow + // 0 = Sunday
@ -1443,35 +1454,52 @@ std::string renderMonths (
table.addCell (row, thisCol, d);
Color color_today (context.config.get ("color.calendar.today"));
Color color_due (context.config.get ("color.calendar.due"));
Color color_overdue (context.config.get ("color.calendar.overdue"));
Color color_weekend (context.config.get ("color.calendar.weekend"));
if (context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor"))
{
// colorize weekends
if (dow == 0 || dow == 6)
table.setCellColor (row, thisCol, color_weekend);
// colorize holidays
if (context.config.get ("calendar.holidays") != "none")
{
std::vector <std::string> holidays;
context.config.all (holidays);
foreach (hol, holidays)
if (hol->substr (0, 8) == "holiday.")
if (hol->substr (hol->size () - 4) == "date")
{
std::string value = context.config.get (*hol);
Date holDate (value.c_str (), context.config.get ("dateformat"));
if (holDate.day () == d &&
holDate.month () == months[mpl] &&
holDate.year () == years[mpl])
table.setCellColor (row, thisCol, color_holiday);
}
}
// colorize today
if (today.day () == d &&
today.month () == months.at (mpl) &&
today.year () == years.at (mpl))
table.setCellColor (row, thisCol, color_today);
}
foreach (task, all)
{
if (task->getStatus () == Task::pending &&
task->has ("due"))
{
Date due (atoi (task->get ("due").c_str ()));
// colorize due tasks
if (context.config.get ("calendar.details") != "none")
foreach (task, all)
{
if (task->getStatus () == Task::pending &&
task->has ("due"))
{
Date due (atoi (task->get ("due").c_str ()));
if ((context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor")) &&
due.day () == d &&
due.month () == months[mpl] &&
due.year () == years[mpl])
table.setCellColor (row, thisCol, (due < today ? color_overdue : color_due));
}
if (due.day () == d &&
due.month () == months[mpl] &&
due.year () == years[mpl])
table.setCellColor (row, thisCol, (due < today ? color_overdue : color_due));
}
}
}
// Check for end of week, and...
@ -1652,12 +1680,15 @@ int handleReportCalendar (std::string &outs)
}
}
Color color_today (context.config.get ("color.calendar.today"));
Color color_due (context.config.get ("color.calendar.due"));
Color color_overdue (context.config.get ("color.calendar.overdue"));
Color color_weekend (context.config.get ("color.calendar.weekend"));
Color color_today (context.config.get ("color.calendar.today"));
Color color_due (context.config.get ("color.calendar.due"));
Color color_overdue (context.config.get ("color.calendar.overdue"));
Color color_weekend (context.config.get ("color.calendar.weekend"));
Color color_holiday (context.config.get ("color.calendar.holiday"));
Color color_weeknumber (context.config.get ("color.calendar.weeknumber"));
if (context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor"))
if ((context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor")) &&
context.config.getBoolean ("calendar.legend"))
out << "Legend: "
<< color_today.colorize ("today")
<< ", "
@ -1666,11 +1697,15 @@ int handleReportCalendar (std::string &outs)
<< color_overdue.colorize ("overdue")
<< ", "
<< color_weekend.colorize ("weekend")
<< ", "
<< color_holiday.colorize ("holiday")
<< ", "
<< color_weeknumber.colorize ("weeknumber")
<< "."
<< optionalBlankLine ()
<< std::endl;
if (context.config.getBoolean ("calendar.details"))
if (context.config.get ("calendar.details") == "full" || context.config.get ("calendar.holidays") == "full")
{
--details_mFrom;
if (details_mFrom == 0)
@ -1693,22 +1728,80 @@ int handleReportCalendar (std::string &outs)
Date date_before (mTo, 1, yTo);
std::string before = date_before.toString (context.config.get ("dateformat"));
std::string report = context.config.get ("calendar.details.report");
std::string report_filter = context.config.get ("report." + report + ".filter");
// Table with due date information
if (context.config.get ("calendar.details") == "full")
{
std::string report = context.config.get ("calendar.details.report");
std::string report_filter = context.config.get ("report." + report + ".filter");
report_filter += " due.after:" + after + " due.before:" + before;
context.config.set ("report." + report + ".filter", report_filter);
report_filter += " due.after:" + after + " due.before:" + before;
context.config.set ("report." + report + ".filter", report_filter);
// Display all due task in the report colorized not only the imminet ones
context.config.set ("due", 0);
// Display all due task in the report colorized not only the imminet ones
context.config.set ("due", 0);
context.args.clear ();
context.filter.clear ();
context.sequence.clear ();
context.args.clear ();
context.filter.clear ();
context.sequence.clear ();
std::string output;
handleCustomReport (report, output);
out << output;
std::string output;
handleCustomReport (report, output);
out << output;
}
// Table with holiday information
if (context.config.get ("calendar.holidays") == "full")
{
std::vector <std::string> holidays;
context.config.all (holidays);
Table holTable;
holTable.setTableWidth (context.getWidth ());
holTable.addColumn ("Date");
holTable.addColumn ("Holiday");
if ((context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor")) &&
context.config.getBoolean ("fontunderline"))
{
holTable.setColumnUnderline (0);
holTable.setColumnUnderline (1);
}
else
holTable.setTableDashedUnderline ();
holTable.setColumnWidth (0, Table::minimum);
holTable.setColumnWidth (1, Table::flexible);
holTable.setColumnJustification (0, Table::left);
holTable.setColumnJustification (1, Table::left);
foreach (hol, holidays)
if (hol->substr (0, 8) == "holiday.")
if (hol->substr (hol->size () - 4) == "name")
{
std::string holName = context.config.get ("holiday." + hol->substr (8, hol->size () - 13) + ".name");
std::string holDate = context.config.get ("holiday." + hol->substr (8, hol->size () - 13) + ".date");
Date hDate (holDate.c_str (), context.config.get ("dateformat"));
if (date_after < hDate && hDate < date_before)
{
std::string format = context.config.get ("report." +
context.config.get ("calendar.details.report") +
".dateformat");
if (format == "")
format = context.config.get ("reportdateformat");
if (format == "")
format = context.config.get ("dateformat");
int row = holTable.addRow ();
holTable.addCell (row, 0, hDate.toString (format));
holTable.addCell (row, 1, holName);
}
}
out << optionalBlankLine ()
<< holTable.render ()
<< std::endl;
}
}
outs = out.str ();

View file

@ -30,7 +30,7 @@
use strict;
use warnings;
use Test::More tests => 60;
use Test::More tests => 75;
# Create the rc file.
if (open my $fh, '>', 'cal.rc')
@ -65,9 +65,9 @@ $output = qx{../task rc:cal.rc add zero};
unlike ($output, qr/\[41m\d+/, 'No overdue tasks are present');
unlike ($output, qr/\[43m\d+/, 'No due tasks are present');
$output = qx{../task rc:cal.rc rc.weekstart:Sunday cal};
like ($output, qr/Su Mo Tu/, 'Week starts on Sunday');
like ($output, qr/Su Mo Tu/, 'Week starts on Sunday');
$output = qx{../task rc:cal.rc rc.weekstart:Monday cal};
like ($output, qr/Fr Sa Su/, 'Week starts on Monday');
like ($output, qr/Fr Sa Su/, 'Week starts on Monday');
$output = qx{../task rc:cal.rc cal y};
like ($output, qr/$month\w+?\s+?$year/, 'Current month and year are displayed');
if ( $month eq "Jan")
@ -85,22 +85,23 @@ unlike ($output, qr/$month\w+?\s+?$nextyear/, 'Current month and year ahead
qx{../task rc:cal.rc add due:20190515 one};
qx{../task rc:cal.rc add due:20200123 two};
$output = qx{../task rc:cal.rc rc._forcecolor:on cal due};
unlike ($output, qr/April 2019/, 'April 2019 is not displayed');
like ($output, qr/May 2019/, 'May 2019 is displayed');
unlike ($output, qr/January 2020/, 'January 2020 is not displayed');
unlike ($output, qr/April 2019/, 'April 2019 is not displayed');
like ($output, qr/May 2019/, 'May 2019 is displayed');
unlike ($output, qr/January 2020/, 'January 2020 is not displayed');
like ($output, qr/30;42m15/, 'Task 1 is color-coded due');
$output = qx{../task rc:cal.rc rc._forcecolor:on cal due y};
like ($output, qr/30;42m23/, 'Task 2 is color-coded due');
like ($output, qr/April 2020/, 'April 2020 is displayed');
unlike ($output, qr/May 2020/, 'May 2020 is not displayed');
like ($output, qr/April 2020/, 'April 2020 is displayed');
unlike ($output, qr/May 2020/, 'May 2020 is not displayed');
qx{../task rc:cal.rc ls};
qx{../task rc:cal.rc del 1-3};
qx{../task rc:cal.rc add due:20080408 three};
$output = qx{../task rc:cal.rc rc._forcecolor:on cal due};
like ($output, qr/April 2008/, 'April 2008 is displayed');
like ($output, qr/41m 8/, 'Task 3 is color-coded overdue');
like ($output, qr/30;47m19/, 'Saturday April 19, 2008 is color-coded');
like ($output, qr/30;47m20/, 'Sunday April 20, 2008 is color-coded');
like ($output, qr/April 2008/, 'April 2008 is displayed');
like ($output, qr/41m 8/, 'Task 3 is color-coded overdue');
like ($output, qr/37;100m19/, 'Saturday April 19, 2008 is color-coded');
like ($output, qr/37;100m20/, 'Sunday April 20, 2008 is color-coded');
like ($output, qr/30;47m 1/, 'Weeknumbers are color-coded');
# task cal 2016
$output = qx{../task rc:cal.rc rc.weekstart:Monday cal 2016};
@ -120,9 +121,9 @@ unlike ($output, qr/53/, 'Weeknumbers are not displayed');
# task cal 4 2010
$output = qx{../task rc:cal.rc rc.monthsperline:1 cal 4 2010};
unlike ($output, qr/March 2010/, 'March 2010 is not displayed');
like ($output, qr/April 2010/, 'April 2010 is displayed');
unlike ($output, qr/May 2010/, 'May 2010 is not displayed');
unlike ($output, qr/March 2010/, 'March 2010 is not displayed');
like ($output, qr/April 2010/, 'April 2010 is displayed');
unlike ($output, qr/May 2010/, 'May 2010 is not displayed');
# Cleanup.
unlink 'pending.data';
@ -137,10 +138,17 @@ if (open my $fh, '>', 'details.rc')
{
print $fh "data.location=.\n",
"dateformat=YMD\n",
"calendar.details=yes\n",
"calendar.details=full\n",
"calendar.details.report=list\n",
"calendar.holidays=full\n",
"color=on\n",
"confirmation=no\n";
"confirmation=no\n",
"holiday.AAAA.name=AAAA\n",
"holiday.AAAA.date=20150101\n",
"holiday.BBBBBB.name=BBBBBB\n",
"holiday.BBBBBB.date=20150115\n",
"holiday.åäö.name=åäö\n",
"holiday.åäö.date=20150125\n";
close $fh;
ok (-r 'details.rc', 'Created details.rc');
}
@ -155,6 +163,9 @@ qx{../task rc:details.rc add due:20141231 six};
qx{../task rc:details.rc add due:20160101 seven};
qx{../task rc:details.rc add due:20081231 eight};
$output = qx{../task rc:details.rc rc.calendar.legend:no cal};
unlike ($output, qr/Legend:/, 'Legend is not displayed');
$output = qx{../task rc:details.rc cal rc.monthsperline:3 1 2015};
like ($output, qr/January 2015/, 'January 2015 is displayed');
like ($output, qr/20150105/, 'Due date 20150105 is displayed');
@ -194,6 +205,23 @@ like ($output, qr/$month\w+?\s+?$year/, 'Current month and year are displayed'
like ($output, qr/$duedate/, 'Due date on current day is displayed');
like ($output, qr/1 task/, '1 due task is displayed');
$output = qx{../task rc:details.rc cal rc.monthsperline:1 1 2015};
like ($output, qr/Date/, 'Word Date is displayed');
like ($output, qr/Holiday/, 'Word Holiday is displayed');
like ($output, qr/20150101/, 'Holiday 20150101 is displayed');
like ($output, qr/20150115/, 'Holiday 20150115 is displayed');
like ($output, qr/20150125/, 'Holiday 20150125 is displayed');
like ($output, qr/AAAA/, 'Holiday name AAAA is displayed');
like ($output, qr/BBBBBB/, 'Holiday name BBBBBB is displayed');
like ($output, qr/åäö/, 'Holiday name åäö is displayed');
$output = qx{../task rc:details.rc cal rc._forcecolor:on rc.monthsperline:1 rc.calendar.details:sparse rc.calendar.holidays:sparse 1 2015};
unlike ($output, qr/Date/, 'Word Date is not displayed');
unlike ($output, qr/Holiday/, 'Word Holiday is not displayed');
like ($output, qr/30;103m 1/, 'Holiday AAAA is color-coded');
like ($output, qr/30;103m15/, 'Holiday BBBBBB is color-coded');
like ($output, qr/30;103m25/, 'Holiday åäö is color-coded');
# Cleanup.
unlink 'pending.data';
ok (!-r 'pending.data', 'Removed pending.data');