119 lines
3.6 KiB
Text
119 lines
3.6 KiB
Text
#!/bin/env pike
|
|
|
|
int main(int argc, array(string) argv)
|
|
{
|
|
object cal = Calendar;
|
|
object year;
|
|
string region = "us";
|
|
|
|
array date = argv[1..];
|
|
if (sizeof(date) && objectp(Calendar[date[0]]) && Calendar[date[0]]->Day)
|
|
{
|
|
cal = Calendar[date[0]];
|
|
date = Array.shift(date)[1];
|
|
}
|
|
|
|
if (sizeof(date) && (int)date[0])
|
|
{
|
|
year = cal.Year((int)date[0]);
|
|
date = Array.shift(date)[1];
|
|
}
|
|
|
|
if (sizeof(date))
|
|
region = date[0];
|
|
|
|
if (!year)
|
|
year = cal.Year();
|
|
|
|
print_year(year, region);
|
|
}
|
|
|
|
array make_month(object month, int field_width, void|string region)
|
|
{
|
|
array out =({});
|
|
mapping holidays = ([]);
|
|
object today = Calendar.Day();
|
|
|
|
if (region)
|
|
holidays = Calendar.Events.find_region(region)->scan_events(month);
|
|
|
|
array weekday_names =
|
|
sprintf("%*.*s", field_width, field_width, month->week()->days()->week_day_shortname()[*]);
|
|
|
|
out += ({ ({ month->month_name(), month->month_no(), month->year_name() }) });
|
|
out += ({ weekday_names });
|
|
out += showday(month->weeks()->days()[*][*], month, today, holidays, field_width);
|
|
|
|
out += ({ ({ " "*field_width })*sizeof(weekday_names) });
|
|
|
|
return out;
|
|
}
|
|
|
|
string print_month(object _month, void|int field_width, void|string region)
|
|
{
|
|
if (!field_width)
|
|
field_width = 2;
|
|
array month = make_month(_month, field_width, region);
|
|
string out = "";
|
|
|
|
out += sprintf("%|*s\n", (field_width+1)*sizeof(month[1])-1, sprintf("%s", month[0][0]));
|
|
out += sprintf((month[1..][*]*" ")*"\n");
|
|
return out;
|
|
}
|
|
|
|
string print_year(object year, void|string region)
|
|
{
|
|
array output = ({});
|
|
int day_width = 2;
|
|
int columns = Stdio.stdout.tcgetattr()->columns;
|
|
int month_width = sizeof(make_month(year->month(), day_width)[1]) * (day_width+1) - 1;
|
|
if (columns < month_width)
|
|
columns = month_width;
|
|
|
|
// try to find an optimal good looking solution to spread the months
|
|
// across the terminal width
|
|
// for the common calendar of 12 months this is easy but we need to
|
|
// account for caledars that have more than 12 months
|
|
float max_width = (float)((columns+2)/(month_width+2));
|
|
float max_height = ceil(year->number_of_months()/max_width);
|
|
float w = max_width;
|
|
|
|
while(ceil(year->number_of_months()/(w-1)) == max_height)
|
|
w--;
|
|
|
|
foreach(print_month(year->months()[*], day_width, region)/w;; array row)
|
|
{
|
|
array rows = row[*]/"\n";
|
|
int l = max(@sizeof(rows[*]));
|
|
foreach(rows; int i;)
|
|
{
|
|
// the last line of each month is an empty line.
|
|
// repeat the line as many times as needed to make the months equally long
|
|
rows[i]+=({ rows[i][-1] })*(l-sizeof(rows[i]));
|
|
}
|
|
rows = Array.transpose(rows);
|
|
output += rows[*]*" ";
|
|
}
|
|
write("%*|s\n", sizeof(output[1]), year->format_nice());
|
|
write(output * "\n");
|
|
write("\n");
|
|
}
|
|
|
|
string showday(object day, object month, object today, mapping holidays, int field_width)
|
|
{
|
|
string dayname;
|
|
if (day->month() == month)
|
|
{
|
|
dayname = (string)day->month_day();
|
|
dayname = " "*(sizeof((string)month->number_of_days())-sizeof(dayname))+dayname;
|
|
if (day == today)
|
|
dayname = sprintf("%|*.*s", field_width, field_width, dayname);
|
|
else
|
|
dayname = sprintf("%|*.*s", field_width, field_width, dayname);
|
|
if (holidays[day])
|
|
dayname = sprintf("%|s", dayname);
|
|
}
|
|
else
|
|
dayname = " "*field_width;
|
|
return dayname;
|
|
}
|