September Morn Update
This commit is contained in:
parent
4e2d22a71d
commit
aac6731f2c
6856 changed files with 141342 additions and 21127 deletions
|
|
@ -0,0 +1,166 @@
|
|||
/* UPPER CASE ONLY VERSION OF THE ORIGINAL CALENDAR.C, CHANGES MOSTLY TO AVOID NEEDING #INCLUDES */
|
||||
/* ERROR MESSAGES GO TO STDOUT TO SLIGHTLY SIMPLIFY THE I/O HANDLING */
|
||||
/* WHEN COMPILING THIS, THE COMMAND LINE SHOULD SPECIFY -D OPTIONS FOR THE FOLLOWING WORDS: */
|
||||
/* STRUCT, VOID, INT, CHAR, CONST, MAIN, IF, ELSE, WHILE, FOR, DO, BREAK, RETURN, PUTCHAR */
|
||||
/* THE VALUE OF EACH MACRO SHOULD BE THE WORD IN LOWER-CASE */
|
||||
|
||||
INT PUTCHAR(INT);
|
||||
|
||||
INT WIDTH = 80, YEAR = 1969;
|
||||
INT COLS, LEAD, GAP;
|
||||
|
||||
CONST CHAR *WDAYS[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA" };
|
||||
STRUCT MONTHS {
|
||||
CONST CHAR *NAME;
|
||||
INT DAYS, START_WDAY, AT;
|
||||
} MONTHS[12] = {
|
||||
{ "JANUARY", 31, 0, 0 },
|
||||
{ "FEBRUARY", 28, 0, 0 },
|
||||
{ "MARCH", 31, 0, 0 },
|
||||
{ "APRIL", 30, 0, 0 },
|
||||
{ "MAY", 31, 0, 0 },
|
||||
{ "JUNE", 30, 0, 0 },
|
||||
{ "JULY", 31, 0, 0 },
|
||||
{ "AUGUST", 31, 0, 0 },
|
||||
{ "SEPTEMBER", 30, 0, 0 },
|
||||
{ "OCTOBER", 31, 0, 0 },
|
||||
{ "NOVEMBER", 30, 0, 0 },
|
||||
{ "DECEMBER", 31, 0, 0 }
|
||||
};
|
||||
|
||||
VOID SPACE(INT N) { WHILE (N-- > 0) PUTCHAR(' '); }
|
||||
VOID PRINT(CONST CHAR * S){ WHILE (*S != '\0') { PUTCHAR(*S++); } }
|
||||
INT STRLEN(CONST CHAR * S)
|
||||
{
|
||||
INT L = 0;
|
||||
WHILE (*S++ != '\0') { L ++; };
|
||||
RETURN L;
|
||||
}
|
||||
INT ATOI(CONST CHAR * S)
|
||||
{
|
||||
INT I = 0;
|
||||
INT SIGN = 1;
|
||||
CHAR C;
|
||||
WHILE ((C = *S++) != '\0') {
|
||||
IF (C == '-')
|
||||
SIGN *= -1;
|
||||
ELSE {
|
||||
I *= 10;
|
||||
I += (C - '0');
|
||||
}
|
||||
}
|
||||
RETURN I * SIGN;
|
||||
}
|
||||
|
||||
VOID INIT_MONTHS(VOID)
|
||||
{
|
||||
INT I;
|
||||
|
||||
IF ((!(YEAR % 4) && (YEAR % 100)) || !(YEAR % 400))
|
||||
MONTHS[1].DAYS = 29;
|
||||
|
||||
YEAR--;
|
||||
MONTHS[0].START_WDAY
|
||||
= (YEAR * 365 + YEAR/4 - YEAR/100 + YEAR/400 + 1) % 7;
|
||||
|
||||
FOR (I = 1; I < 12; I++)
|
||||
MONTHS[I].START_WDAY =
|
||||
(MONTHS[I-1].START_WDAY + MONTHS[I-1].DAYS) % 7;
|
||||
|
||||
COLS = (WIDTH + 2) / 22;
|
||||
WHILE (12 % COLS) COLS--;
|
||||
GAP = COLS - 1 ? (WIDTH - 20 * COLS) / (COLS - 1) : 0;
|
||||
IF (GAP > 4) GAP = 4;
|
||||
LEAD = (WIDTH - (20 + GAP) * COLS + GAP + 1) / 2;
|
||||
YEAR++;
|
||||
}
|
||||
|
||||
VOID PRINT_ROW(INT ROW)
|
||||
{
|
||||
INT C, I, FROM = ROW * COLS, TO = FROM + COLS;
|
||||
SPACE(LEAD);
|
||||
FOR (C = FROM; C < TO; C++) {
|
||||
I = STRLEN(MONTHS[C].NAME);
|
||||
SPACE((20 - I)/2);
|
||||
PRINT(MONTHS[C].NAME);
|
||||
SPACE(20 - I - (20 - I)/2 + ((C == TO - 1) ? 0 : GAP));
|
||||
}
|
||||
PUTCHAR('\012');
|
||||
|
||||
SPACE(LEAD);
|
||||
FOR (C = FROM; C < TO; C++) {
|
||||
FOR (I = 0; I < 7; I++) {
|
||||
PRINT(WDAYS[I]);
|
||||
PRINT(I == 6 ? "" : " ");
|
||||
}
|
||||
IF (C < TO - 1) SPACE(GAP);
|
||||
ELSE PUTCHAR('\012');
|
||||
}
|
||||
|
||||
WHILE (1) {
|
||||
FOR (C = FROM; C < TO; C++)
|
||||
IF (MONTHS[C].AT < MONTHS[C].DAYS) BREAK;
|
||||
IF (C == TO) BREAK;
|
||||
|
||||
SPACE(LEAD);
|
||||
FOR (C = FROM; C < TO; C++) {
|
||||
FOR (I = 0; I < MONTHS[C].START_WDAY; I++) SPACE(3);
|
||||
WHILE(I++ < 7 && MONTHS[C].AT < MONTHS[C].DAYS) {
|
||||
INT MM = ++MONTHS[C].AT;
|
||||
PUTCHAR((MM < 10) ? ' ' : '0' + (MM /10));
|
||||
PUTCHAR('0' + (MM %10));
|
||||
IF (I < 7 || C < TO - 1) PUTCHAR(' ');
|
||||
}
|
||||
WHILE (I++ <= 7 && C < TO - 1) SPACE(3);
|
||||
IF (C < TO - 1) SPACE(GAP - 1);
|
||||
MONTHS[C].START_WDAY = 0;
|
||||
}
|
||||
PUTCHAR('\012');
|
||||
}
|
||||
PUTCHAR('\012');
|
||||
}
|
||||
|
||||
VOID PRINT_YEAR(VOID)
|
||||
{
|
||||
INT Y = YEAR;
|
||||
INT ROW;
|
||||
CHAR BUF[32];
|
||||
CHAR * B = &(BUF[31]);
|
||||
*B-- = '\0';
|
||||
DO {
|
||||
*B-- = '0' + (Y % 10);
|
||||
Y /= 10;
|
||||
} WHILE (Y > 0);
|
||||
B++;
|
||||
SPACE((WIDTH - STRLEN(B)) / 2);
|
||||
PRINT(B);PUTCHAR('\012');PUTCHAR('\012');
|
||||
FOR (ROW = 0; ROW * COLS < 12; ROW++)
|
||||
PRINT_ROW(ROW);
|
||||
}
|
||||
|
||||
INT MAIN(INT C, CHAR **V)
|
||||
{
|
||||
INT I, YEAR_SET = 0, RESULT = 0;
|
||||
FOR (I = 1; I < C && RESULT == 0; I++) {
|
||||
IF (V[I][0] == '-' && V[I][1] == 'W' && V[I][2] == '\0') {
|
||||
IF (++I == C || (WIDTH = ATOI(V[I])) < 20)
|
||||
RESULT = 1;
|
||||
} ELSE IF (!YEAR_SET) {
|
||||
YEAR = ATOI(V[I]);
|
||||
IF (YEAR <= 0)
|
||||
YEAR = 1969;
|
||||
YEAR_SET = 1;
|
||||
} ELSE
|
||||
RESULT = 1;
|
||||
}
|
||||
|
||||
IF (RESULT == 0) {
|
||||
INIT_MONTHS();
|
||||
PRINT_YEAR();
|
||||
} ELSE {
|
||||
PRINT("BAD ARGS\012USAGE: ");
|
||||
PRINT(V[0]);
|
||||
PRINT(" YEAR [-W WIDTH (>= 20)]\012");
|
||||
}
|
||||
RETURN RESULT;
|
||||
}
|
||||
|
|
@ -1,147 +1,152 @@
|
|||
import system'text.
|
||||
import system'routines.
|
||||
import system'calendar.
|
||||
import extensions.
|
||||
import extensions'routines.
|
||||
import system'text;
|
||||
import system'routines;
|
||||
import system'calendar;
|
||||
import extensions;
|
||||
import extensions'routines;
|
||||
|
||||
const MonthNames = ("JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER").
|
||||
const DayNames = ("MO", "TU", "WE", "TH", "FR", "SA", "SU").
|
||||
const MonthNames = new string[] {"JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"};
|
||||
const DayNames = new string[] {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
|
||||
|
||||
class CalendarMonthPrinter
|
||||
{
|
||||
object theDate.
|
||||
object theLine.
|
||||
object theMonth.
|
||||
object theYear.
|
||||
object theRow.
|
||||
Date theDate;
|
||||
TextBuilder theLine;
|
||||
int theMonth;
|
||||
int theYear;
|
||||
ref<int> theRow;
|
||||
|
||||
constructor year:aYear month:aMonth
|
||||
[
|
||||
theMonth := aMonth.
|
||||
theYear := aYear.
|
||||
theLine := TextBuilder new.
|
||||
theRow := Integer new(0).
|
||||
]
|
||||
|
||||
writeTitle
|
||||
[
|
||||
theRow value := 0.
|
||||
theDate := Date new(theYear, theMonth, 1).
|
||||
DayNames forEach(:aName)
|
||||
[ theLine print(" ",aName) ]
|
||||
]
|
||||
|
||||
writeLine
|
||||
[
|
||||
theLine clear.
|
||||
|
||||
if (theDate month == theMonth)
|
||||
[
|
||||
theLine write:" " length((theDate dayOfWeek == 0)iif(7,theDate dayOfWeek) - 1).
|
||||
|
||||
[
|
||||
theLine write:(theDate day; literal) paddingLeft:3 with:$32.
|
||||
theDate := theDate addDays:1.
|
||||
]
|
||||
repeatUntil:$((theDate month != theMonth)||(theDate dayOfWeek == 1)).
|
||||
].
|
||||
|
||||
int aLength := theLine length.
|
||||
if (aLength < 21)
|
||||
[ theLine write:" " length(21 - aLength). ].
|
||||
|
||||
theRow append(1).
|
||||
]
|
||||
|
||||
indexer = BaseIndexer::
|
||||
constructor(year, month)
|
||||
{
|
||||
bool available = theRow < 7.
|
||||
theMonth := month;
|
||||
theYear := year;
|
||||
theLine := new TextBuilder();
|
||||
theRow := 0;
|
||||
}
|
||||
|
||||
readIndexTo(ref<int> anIndex) [ theRow readValueTo(anIndex) ]
|
||||
writeTitle()
|
||||
{
|
||||
theRow.Value := 0;
|
||||
theDate := Date.new(theYear, theMonth, 1);
|
||||
DayNames.forEach:(name)
|
||||
{ theLine.print(" ",name) }
|
||||
}
|
||||
|
||||
writeIndex(int anIndex)
|
||||
[
|
||||
if (anIndex <= theRow)
|
||||
[ self writeTitle ].
|
||||
writeLine()
|
||||
{
|
||||
theLine.clear();
|
||||
|
||||
while (anIndex > theRow)
|
||||
[ self writeLine ]
|
||||
]
|
||||
if (theDate.Month == theMonth)
|
||||
{
|
||||
theLine.writeCopies(" ",theDate.DayOfWeek == 0 ? 7 : (theDate.DayOfWeek - 1));
|
||||
|
||||
appendIndex(int anIndex)
|
||||
<= writeIndex(theRow value + anIndex).
|
||||
doUntil(theDate.Month != theMonth || theDate.DayOfWeek == 1)
|
||||
{
|
||||
theLine.writePaddingLeft(theDate.Day.Printable, $32, 3);
|
||||
|
||||
readLengthTo(ref<int> retVal) [ retVal value := 7 ]
|
||||
theDate := theDate.addDays:1
|
||||
}
|
||||
};
|
||||
|
||||
get = self.
|
||||
int length := theLine.Length;
|
||||
if (length < 21)
|
||||
{ theLine.writeCopies(" ", 21 - length) };
|
||||
|
||||
set : o [ NotSupportedException new; raise ]
|
||||
}.
|
||||
theRow.append(1)
|
||||
}
|
||||
|
||||
printTitleTo : anOutput
|
||||
[
|
||||
anOutput write(MonthNames[theMonth - 1]) padding:21 with:$32.
|
||||
]
|
||||
indexer() = new Indexer:
|
||||
{
|
||||
bool Available = theRow < 7;
|
||||
|
||||
printTo : anOutput
|
||||
[
|
||||
anOutput write(theLine literal).
|
||||
]
|
||||
readIndexTo(ref int retVal) { theRow.readValueTo(ref retVal) }
|
||||
|
||||
writeIndex(int index)
|
||||
{
|
||||
if (index <= theRow)
|
||||
{ self.writeTitle() };
|
||||
|
||||
while (index > theRow)
|
||||
{ self.writeLine() }
|
||||
}
|
||||
|
||||
appendIndex(int index)
|
||||
<= writeIndex(theRow.Value + index);
|
||||
|
||||
readLengthTo(ref int retVal) { retVal := 7 }
|
||||
|
||||
get() = self;
|
||||
|
||||
set(o) { NotSupportedException.raise() }
|
||||
};
|
||||
|
||||
printTitleTo(output)
|
||||
{
|
||||
output.writePadding(MonthNames[theMonth - 1], $32, 21)
|
||||
}
|
||||
|
||||
printTo(output)
|
||||
{
|
||||
output.write(theLine.Value)
|
||||
}
|
||||
}
|
||||
|
||||
class Calendar
|
||||
{
|
||||
int theYear.
|
||||
int theRowLength.
|
||||
int theYear;
|
||||
int theRowLength;
|
||||
|
||||
constructor new : aYear
|
||||
[
|
||||
theYear := aYear.
|
||||
theRowLength := 3.
|
||||
]
|
||||
constructor new(int year)
|
||||
{
|
||||
theYear := year;
|
||||
theRowLength := 3
|
||||
}
|
||||
|
||||
printTo:anOutput
|
||||
[
|
||||
anOutput write:"[SNOOPY]" padding:(theRowLength * 25) with:$32.
|
||||
anOutput writeLine.
|
||||
anOutput write:(theYear literal) padding:(theRowLength * 25) with:$32.
|
||||
anOutput writeLine; writeLine.
|
||||
printTo(output)
|
||||
{
|
||||
output.writePadding("[SNOOPY]", $32, theRowLength * 25);
|
||||
output.writeLine();
|
||||
output.writePadding(theYear.Printable, $32, theRowLength * 25);
|
||||
output.writeLine().writeLine();
|
||||
|
||||
var aRowCount := 12 / theRowLength.
|
||||
var Months := Array new(aRowCount); populate(:i)
|
||||
(Array new:theRowLength;
|
||||
populate(:j)
|
||||
( CalendarMonthPrinter year:theYear month(i * theRowLength + j + 1))).
|
||||
var rowCount := 12 / theRowLength;
|
||||
var months := Array.allocate(rowCount).populate:(i =>
|
||||
Array.allocate(theRowLength)
|
||||
.populate:(j =>
|
||||
new CalendarMonthPrinter(theYear, i * theRowLength + j + 1)));
|
||||
|
||||
Months forEach(:aRow)
|
||||
[
|
||||
aRow forEach(:aMonth)
|
||||
[
|
||||
aMonth printTitleTo:anOutput.
|
||||
anOutput write:" ".
|
||||
].
|
||||
months.forEach:(row)
|
||||
{
|
||||
var r := row;
|
||||
|
||||
anOutput writeLine.
|
||||
row.forEach:(month)
|
||||
{
|
||||
month.printTitleTo:output;
|
||||
|
||||
ParallelEnumerator new:aRow; forEach(:aLine)
|
||||
[
|
||||
aLine forEach(:aPrinter)
|
||||
[
|
||||
aPrinter printTo:anOutput.
|
||||
anOutput write:" "
|
||||
].
|
||||
output.write:" "
|
||||
};
|
||||
|
||||
anOutput writeLine
|
||||
].
|
||||
].
|
||||
]
|
||||
output.writeLine();
|
||||
|
||||
ParallelEnumerator.new(row).forEach:(line)
|
||||
{
|
||||
line.forEach:(printer)
|
||||
{
|
||||
printer.printTo:output;
|
||||
|
||||
output.write:" "
|
||||
};
|
||||
|
||||
output.writeLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public program =
|
||||
[
|
||||
var aCalender := Calendar new(console write:"ENTER THE YEAR:"; readLineTo(Integer new)).
|
||||
public program()
|
||||
{
|
||||
var calender := Calendar.new(console.write:"ENTER THE YEAR:".readLine().toInt());
|
||||
|
||||
aCalender printTo:console.
|
||||
calender.printTo:console;
|
||||
|
||||
console readChar.
|
||||
].
|
||||
console.readChar()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
PACKAGE MAIN
|
||||
|
||||
IMPORT (
|
||||
"FMT"
|
||||
"TIME"
|
||||
)
|
||||
|
||||
CONST PAGEWIDTH = 80
|
||||
|
||||
FUNC MAIN() {
|
||||
PRINTCAL(1969)
|
||||
}
|
||||
|
||||
FUNC PRINTCAL(YEAR INT) {
|
||||
THISDATE := TIME.DATE(YEAR, 1, 1, 1, 1, 1, 1, TIME.UTC)
|
||||
VAR (
|
||||
DAYARR [12][7][6]INT // MONTH, WEEKDAY, WEEK
|
||||
MONTH, LASTMONTH TIME.MONTH
|
||||
WEEKINMONTH, DAYINMONTH INT
|
||||
)
|
||||
FOR THISDATE.YEAR() == YEAR {
|
||||
IF MONTH = THISDATE.MONTH(); MONTH != LASTMONTH {
|
||||
WEEKINMONTH = 0
|
||||
DAYINMONTH = 1
|
||||
}
|
||||
WEEKDAY := THISDATE.WEEKDAY()
|
||||
IF WEEKDAY == 0 && DAYINMONTH > 1 {
|
||||
WEEKINMONTH++
|
||||
}
|
||||
DAYARR[INT(MONTH)-1][WEEKDAY][WEEKINMONTH] = THISDATE.DAY()
|
||||
LASTMONTH = MONTH
|
||||
DAYINMONTH++
|
||||
THISDATE = THISDATE.ADD(TIME.HOUR * 24)
|
||||
}
|
||||
CENTRE := FMT.SPRINTF("%D", PAGEWIDTH/2)
|
||||
FMT.PRINTF("%"+CENTRE+"S\N\N", "[SNOOPY]")
|
||||
CENTRE = FMT.SPRINTF("%D", PAGEWIDTH/2-2)
|
||||
FMT.PRINTF("%"+CENTRE+"D\N\N", YEAR)
|
||||
MONTHS := [12]STRING{
|
||||
" JANUARY ", " FEBRUARY", " MARCH ", " APRIL ",
|
||||
" MAY ", " JUNE ", " JULY ", " AUGUST ",
|
||||
"SEPTEMBER", " OCTOBER ", " NOVEMBER", " DECEMBER"}
|
||||
DAYS := [7]STRING{"SU", "MO", "TU", "WE", "TH", "FR", "SA"}
|
||||
FOR QTR := 0; QTR < 4; QTR++ {
|
||||
FOR MONTHINQTR := 0; MONTHINQTR < 3; MONTHINQTR++ { // MONTH NAMES
|
||||
FMT.PRINTF(" %S ", MONTHS[QTR*3+MONTHINQTR])
|
||||
}
|
||||
FMT.PRINTLN()
|
||||
FOR MONTHINQTR := 0; MONTHINQTR < 3; MONTHINQTR++ { // DAY NAMES
|
||||
FOR DAY := 0; DAY < 7; DAY++ {
|
||||
FMT.PRINTF(" %S", DAYS[DAY])
|
||||
}
|
||||
FMT.PRINTF(" ")
|
||||
}
|
||||
FMT.PRINTLN()
|
||||
FOR WEEKINMONTH = 0; WEEKINMONTH < 6; WEEKINMONTH++ {
|
||||
FOR MONTHINQTR := 0; MONTHINQTR < 3; MONTHINQTR++ {
|
||||
FOR DAY := 0; DAY < 7; DAY++ {
|
||||
IF DAYARR[QTR*3+MONTHINQTR][DAY][WEEKINMONTH] == 0 {
|
||||
FMT.PRINTF(" ")
|
||||
} ELSE {
|
||||
FMT.PRINTF("%3D", DAYARR[QTR*3+MONTHINQTR][DAY][WEEKINMONTH])
|
||||
}
|
||||
}
|
||||
FMT.PRINTF(" ")
|
||||
}
|
||||
FMT.PRINTLN()
|
||||
}
|
||||
FMT.PRINTLN()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
lower := []string{
|
||||
"const ", "else ", "for ", "func ", "if ", "import ", "int ", "package ", "string ", "var ",
|
||||
" int", "int(", "string{", " main", "main(", "fmt", "time", "%d", "%s", "%3d", `d\n\n`, `s\n\n`,
|
||||
}
|
||||
title := []string{
|
||||
".add", ".date", ".day", ".hour", ".month", ".printf", ".println", ".sprintf", ".weekday", ".year",
|
||||
}
|
||||
code, err := ioutil.ReadFile("realcal_UC.txt")
|
||||
check(err)
|
||||
text := string(code)
|
||||
for _, lwr := range lower {
|
||||
text = strings.Replace(text, strings.ToUpper(lwr), lwr, -1)
|
||||
}
|
||||
for _, ttl := range title {
|
||||
text = strings.Replace(text, strings.ToUpper(ttl), "."+strings.Title(ttl[1:]), -1)
|
||||
}
|
||||
err = ioutil.WriteFile("realcal_NC.go", []byte(text), 0666)
|
||||
check(err)
|
||||
cmd := exec.Command("go", "run", "realcal_NC.go")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
check(cmd.Run())
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
# IF THIS SMALL FUNCTION IS PLACED IN THE STARTUP.JL
|
||||
# FILE, IT WILL BE LOADED ON STARTUP. THE REST OF
|
||||
# THIS EXAMPLE IS IN ALL UPPERCASE.
|
||||
function RUNUPPERCASECODE(CO)
|
||||
COD = replace(lowercase(CO), "date" => "Date")
|
||||
for E in Meta.parse(COD, 1) eval(E) end
|
||||
end
|
||||
|
||||
|
||||
CODE = """BEGIN
|
||||
|
||||
USING DATES;
|
||||
CENTEROBJECT(X, N) = BEGIN S = UPPERCASE(STRING(X)); RPAD(LPAD(S, DIV(N + LENGTH(S), 2)), N) END;
|
||||
FUNCTION FORMATMONTH(YR, MO)
|
||||
DT = DATE(\"\$YR-\$MO-01\");
|
||||
DAYOFWEEKFIRST = DAYOFWEEK(DT);
|
||||
NUMWEEKLINES = 1;
|
||||
STR = UPPERCASE(CENTEROBJECT(MONTHNAME(DT), 20) * \"\\NMO TU WE TH FR SA SU\\N\");
|
||||
STR *= \" \" ^ (3 * (DAYOFWEEKFIRST - 1)) * LPAD(STRING(1), 2);
|
||||
FOR I = 2:DAYSINMONTH(DT)
|
||||
IF (I + DAYOFWEEKFIRST + 5) % 7 == 0
|
||||
STR *= \"\\N\" * LPAD(I, 2);
|
||||
NUMWEEKLINES += 1;
|
||||
ELSE
|
||||
STR *= LPAD(STRING(I), 3);
|
||||
END;
|
||||
END;
|
||||
STR *= NUMWEEKLINES < 6 ? \"\\N\\N\\N\" : \"\\N\\N\";
|
||||
ARR = [];
|
||||
FOR S IN SPLIT(STR, \"\\N\")
|
||||
PUSH!(ARR, RPAD(S, 20)[1:20])
|
||||
END;
|
||||
JOIN(ARR, \"\\N\");
|
||||
END;
|
||||
|
||||
FUNCTION FORMATYEAR(DISPLAYYEAR)
|
||||
CALMONTHS = [FORMATMONTH(DISPLAYYEAR, MO) FOR MO IN 1:12];
|
||||
MONTHSPERLINE = 6;
|
||||
JOINSPACES = 2;
|
||||
STR = \"\\N\" * CENTEROBJECT(DISPLAYYEAR, 132) * \"\\N\";
|
||||
MONTHCAL = [SPLIT(FORMATMONTH(DISPLAYYEAR, I), \"\\N\") FOR I IN 1:12];
|
||||
FOR I IN 1:MONTHSPERLINE:LENGTH(CALMONTHS) - 1
|
||||
FOR J IN 1:LENGTH(MONTHCAL[1])
|
||||
MONTHLINES = MAP(X->MONTHCAL[X][J], I:I + MONTHSPERLINE - 1);
|
||||
STR *= RPAD(JOIN(MONTHLINES, \" \" ^ JOINSPACES), 132) * \"\\N\";
|
||||
END;
|
||||
STR *= \"\\N\";
|
||||
END;
|
||||
STR;
|
||||
END;
|
||||
|
||||
PRINTLN(FORMATYEAR(1969));
|
||||
|
||||
END;
|
||||
"""
|
||||
|
||||
RUNUPPERCASECODE(CODE)
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
OPTION COMPARE BINARY
|
||||
OPTION EXPLICIT ON
|
||||
OPTION INFER ON
|
||||
OPTION STRICT ON
|
||||
|
||||
IMPORTS SYSTEM.GLOBALIZATION
|
||||
IMPORTS SYSTEM.TEXT
|
||||
IMPORTS SYSTEM.RUNTIME.INTEROPSERVICES
|
||||
IMPORTS SYSTEM.RUNTIME.COMPILERSERVICES
|
||||
|
||||
MODULE ARGHELPER
|
||||
READONLY _ARGDICT AS NEW DICTIONARY(OF STRING, STRING)()
|
||||
|
||||
DELEGATE FUNCTION TRYPARSE(OF T, TRESULT)(VALUE AS T, <OUT> BYREF RESULT AS TRESULT) AS BOOLEAN
|
||||
|
||||
SUB INITIALIZEARGUMENTS(ARGS AS STRING())
|
||||
FOR EACH ITEM IN ARGS
|
||||
ITEM = ITEM.TOUPPERINVARIANT()
|
||||
|
||||
IF ITEM.LENGTH > 0 ANDALSO ITEM(0) <> """"C THEN
|
||||
DIM COLONPOS = ITEM.INDEXOF(":"C, STRINGCOMPARISON.ORDINAL)
|
||||
|
||||
IF COLONPOS <> -1 THEN
|
||||
' SPLIT ARGUMENTS WITH COLUMNS INTO KEY(PART BEFORE COLON) / VALUE(PART AFTER COLON) PAIRS.
|
||||
_ARGDICT.ADD(ITEM.SUBSTRING(0, COLONPOS), ITEM.SUBSTRING(COLONPOS + 1, ITEM.LENGTH - COLONPOS - 1))
|
||||
END IF
|
||||
END IF
|
||||
NEXT
|
||||
END SUB
|
||||
|
||||
SUB FROMARGUMENT(OF T)(
|
||||
KEY AS STRING,
|
||||
<OUT> BYREF VAR AS T,
|
||||
GETDEFAULT AS FUNC(OF T),
|
||||
TRYPARSE AS TRYPARSE(OF STRING, T),
|
||||
OPTIONAL VALIDATE AS PREDICATE(OF T) = NOTHING)
|
||||
|
||||
DIM VALUE AS STRING = NOTHING
|
||||
IF _ARGDICT.TRYGETVALUE(KEY.TOUPPERINVARIANT(), VALUE) THEN
|
||||
IF NOT (TRYPARSE(VALUE, VAR) ANDALSO (VALIDATE IS NOTHING ORELSE VALIDATE(VAR))) THEN
|
||||
CONSOLE.WRITELINE($"INVALID VALUE FOR {KEY}: {VALUE}")
|
||||
ENVIRONMENT.EXIT(-1)
|
||||
END IF
|
||||
ELSE
|
||||
VAR = GETDEFAULT()
|
||||
END IF
|
||||
END SUB
|
||||
END MODULE
|
||||
|
||||
MODULE PROGRAM
|
||||
SUB MAIN(ARGS AS STRING())
|
||||
DIM DT AS DATE
|
||||
DIM COLUMNS, ROWS, MONTHSPERROW AS INTEGER
|
||||
DIM VERTSTRETCH, HORIZSTRETCH, RESIZEWINDOW AS BOOLEAN
|
||||
|
||||
INITIALIZEARGUMENTS(ARGS)
|
||||
FROMARGUMENT("DATE", DT, FUNCTION() NEW DATE(1969, 1, 1), ADDRESSOF DATE.TRYPARSE)
|
||||
FROMARGUMENT("COLS", COLUMNS, FUNCTION() 80, ADDRESSOF INTEGER.TRYPARSE, FUNCTION(V) V >= 20)
|
||||
FROMARGUMENT("ROWS", ROWS, FUNCTION() 43, ADDRESSOF INTEGER.TRYPARSE, FUNCTION(V) V >= 0)
|
||||
FROMARGUMENT("MS/ROW", MONTHSPERROW, FUNCTION() 0, ADDRESSOF INTEGER.TRYPARSE, FUNCTION(V) V <= 12 ANDALSO V <= COLUMNS \ 20)
|
||||
FROMARGUMENT("VSTRETCH", VERTSTRETCH, FUNCTION() TRUE, ADDRESSOF BOOLEAN.TRYPARSE)
|
||||
FROMARGUMENT("HSTRETCH", HORIZSTRETCH, FUNCTION() TRUE, ADDRESSOF BOOLEAN.TRYPARSE)
|
||||
FROMARGUMENT("WSIZE", RESIZEWINDOW, FUNCTION() TRUE, ADDRESSOF BOOLEAN.TRYPARSE)
|
||||
|
||||
' THE SCROLL BAR IN COMMAND PROMPT SEEMS TO TAKE UP PART OF THE LAST COLUMN.
|
||||
IF RESIZEWINDOW THEN
|
||||
CONSOLE.WINDOWWIDTH = COLUMNS + 1
|
||||
CONSOLE.WINDOWHEIGHT = ROWS
|
||||
END IF
|
||||
|
||||
IF MONTHSPERROW < 1 THEN MONTHSPERROW = MATH.MAX(COLUMNS \ 22, 1)
|
||||
|
||||
FOR EACH ROW IN GETCALENDARROWS(DT:=DT, WIDTH:=COLUMNS, HEIGHT:=ROWS, MONTHSPERROW:=MONTHSPERROW, VERTSTRETCH:=VERTSTRETCH, HORIZSTRETCH:=HORIZSTRETCH)
|
||||
CONSOLE.WRITE(ROW)
|
||||
NEXT
|
||||
END SUB
|
||||
|
||||
ITERATOR FUNCTION GETCALENDARROWS(
|
||||
DT AS DATE,
|
||||
WIDTH AS INTEGER,
|
||||
HEIGHT AS INTEGER,
|
||||
MONTHSPERROW AS INTEGER,
|
||||
VERTSTRETCH AS BOOLEAN,
|
||||
HORIZSTRETCH AS BOOLEAN) AS IENUMERABLE(OF STRING)
|
||||
|
||||
DIM YEAR = DT.YEAR
|
||||
DIM CALENDARROWCOUNT AS INTEGER = CINT(MATH.CEILING(12 / MONTHSPERROW))
|
||||
' MAKE ROOM FOR THE THREE EMPTY LINES ON TOP.
|
||||
DIM MONTHGRIDHEIGHT AS INTEGER = HEIGHT - 3
|
||||
|
||||
YIELD "[SNOOPY]".PADCENTER(WIDTH) & ENVIRONMENT.NEWLINE
|
||||
YIELD YEAR.TOSTRING(CULTUREINFO.INVARIANTCULTURE).PADCENTER(WIDTH) & ENVIRONMENT.NEWLINE
|
||||
YIELD ENVIRONMENT.NEWLINE
|
||||
|
||||
DIM MONTH = 0
|
||||
DO WHILE MONTH < 12
|
||||
DIM ROWHIGHESTMONTH = MATH.MIN(MONTH + MONTHSPERROW, 12)
|
||||
|
||||
DIM CELLWIDTH = WIDTH \ MONTHSPERROW
|
||||
DIM CELLCONTENTWIDTH = IF(MONTHSPERROW = 1, CELLWIDTH, (CELLWIDTH * 19) \ 20)
|
||||
|
||||
DIM CELLHEIGHT = MONTHGRIDHEIGHT \ CALENDARROWCOUNT
|
||||
DIM CELLCONTENTHEIGHT = (CELLHEIGHT * 19) \ 20
|
||||
|
||||
' CREATES A MONTH CELL FOR THE SPECIFIED MONTH (1-12).
|
||||
DIM GETMONTHFROM =
|
||||
FUNCTION(M AS INTEGER) BUILDMONTH(
|
||||
DT:=NEW DATE(DT.YEAR, M, 1),
|
||||
WIDTH:=CELLCONTENTWIDTH,
|
||||
HEIGHT:=CELLCONTENTHEIGHT,
|
||||
VERTSTRETCH:=VERTSTRETCH,
|
||||
HORIZSTRETCH:=HORIZSTRETCH).SELECT(FUNCTION(X) X.PADCENTER(CELLWIDTH))
|
||||
|
||||
' THE MONTHS IN THIS ROW OF THE CALENDAR.
|
||||
DIM MONTHSTHISROW AS IENUMERABLE(OF IENUMERABLE(OF STRING)) =
|
||||
ENUMERABLE.SELECT(ENUMERABLE.RANGE(MONTH + 1, ROWHIGHESTMONTH - MONTH), GETMONTHFROM)
|
||||
|
||||
DIM CALENDARROW AS IENUMERABLE(OF STRING) =
|
||||
INTERLEAVED(
|
||||
MONTHSTHISROW,
|
||||
USEINNERSEPARATOR:=FALSE,
|
||||
USEOUTERSEPARATOR:=TRUE,
|
||||
OUTERSEPARATOR:=ENVIRONMENT.NEWLINE)
|
||||
|
||||
DIM EN = CALENDARROW.GETENUMERATOR()
|
||||
DIM HASNEXT = EN.MOVENEXT()
|
||||
DO WHILE HASNEXT
|
||||
|
||||
DIM CURRENT AS STRING = EN.CURRENT
|
||||
|
||||
' TO MAINTAIN THE (NOT STRICTLY NEEDED) CONTRACT OF YIELDING COMPLETE ROWS, KEEP THE NEWLINE AFTER
|
||||
' THE CALENDAR ROW WITH THE LAST TERMINAL ROW OF THE ROW.
|
||||
HASNEXT = EN.MOVENEXT()
|
||||
YIELD IF(HASNEXT, CURRENT, CURRENT & ENVIRONMENT.NEWLINE)
|
||||
LOOP
|
||||
|
||||
MONTH += MONTHSPERROW
|
||||
LOOP
|
||||
END FUNCTION
|
||||
|
||||
''' <SUMMARY>
|
||||
''' INTERLEAVES THE ELEMENTS OF THE SPECIFIED SUB-SOURCES BY MAKING SUCCESSIVE PASSES THROUGH THE SOURCE
|
||||
''' ENUMERABLE, YIELDING A SINGLE ELEMENT FROM EACH SUB-SOURCE IN SEQUENCE IN EACH PASS, OPTIONALLY INSERTING A
|
||||
''' SEPARATOR BETWEEN ELEMENTS OF ADJACENT SUB-SOURCES AND OPTIONALLY A DIFFERENT SEPARATOR AT THE END OF EACH
|
||||
''' PASS THROUGH ALL THE SOURCES. (I.E., BETWEEN ELEMENTS OF THE LAST AND FIRST SOURCE)
|
||||
''' </SUMMARY>
|
||||
''' <TYPEPARAM NAME="T">THE TYPE OF THE ELEMENTS OF THE SUB-SOURCES.</TYPEPARAM>
|
||||
''' <PARAM NAME="SOURCES">A SEQUENCE OF THE SEQUENCES WHOSE ELEMENTS ARE TO BE INTERLEAVED.</PARAM>
|
||||
''' <PARAM NAME="USEINNERSEPARATOR">WHETHER TO INSERT <PARAMREF NAME="USEINNERSEPARATOR"/> BETWEEN THE ELEMENTS OFADJACENT SUB-SOURCES.</PARAM>
|
||||
''' <PARAM NAME="INNERSEPARATOR">THE SEPARATOR BETWEEN ELEMENTS OF ADJACENT SUB-SOURCES.</PARAM>
|
||||
''' <PARAM NAME="USEOUTERSEPARATOR">WHETHER TO INSERT <PARAMREF NAME="OUTERSEPARATOR"/> BETWEEN THE ELEMENTS OF THE LAST AND FIRST SUB-SOURCES.</PARAM>
|
||||
''' <PARAM NAME="OUTERSEPARATOR">THE SEPARATOR BETWEEN ELEMENTS OF THE LAST AND FIRST SUB-SOURCE.</PARAM>
|
||||
''' <PARAM NAME="WHILEANY">IF <SEE LANGWORD="TRUE"/>, THE ENUMERATION CONTINUES UNTIL EVERY GIVEN SUBSOURCE IS EMPTY;
|
||||
''' IF <SEE LANGWORD="FALSE"/>, THE ENUMERATION STOPS AS SOON AS ANY ENUMERABLE NO LONGER HAS AN ELEMENT TO SUPPLY FOR THE NEXT PASS.</PARAM>
|
||||
ITERATOR FUNCTION INTERLEAVED(OF T)(
|
||||
SOURCES AS IENUMERABLE(OF IENUMERABLE(OF T)),
|
||||
OPTIONAL USEINNERSEPARATOR AS BOOLEAN = FALSE,
|
||||
OPTIONAL INNERSEPARATOR AS T = NOTHING,
|
||||
OPTIONAL USEOUTERSEPARATOR AS BOOLEAN = FALSE,
|
||||
OPTIONAL OUTERSEPARATOR AS T = NOTHING,
|
||||
OPTIONAL WHILEANY AS BOOLEAN = TRUE) AS IENUMERABLE(OF T)
|
||||
DIM SOURCEENUMERATORS AS IENUMERATOR(OF T)() = NOTHING
|
||||
|
||||
TRY
|
||||
SOURCEENUMERATORS = SOURCES.SELECT(FUNCTION(X) X.GETENUMERATOR()).TOARRAY()
|
||||
DIM NUMSOURCES = SOURCEENUMERATORS.LENGTH
|
||||
DIM ENUMERATORSTATES(NUMSOURCES - 1) AS BOOLEAN
|
||||
|
||||
DIM ANYPREVITERS AS BOOLEAN = FALSE
|
||||
DO
|
||||
' INDICES OF FIRST AND LAST SUB-SOURCES THAT HAVE ELEMENTS.
|
||||
DIM FIRSTACTIVE = -1, LASTACTIVE = -1
|
||||
|
||||
' DETERMINE WHETHER EACH SUB-SOURCE THAT STILL HAVE ELEMENTS.
|
||||
FOR I = 0 TO NUMSOURCES - 1
|
||||
ENUMERATORSTATES(I) = SOURCEENUMERATORS(I).MOVENEXT()
|
||||
IF ENUMERATORSTATES(I) THEN
|
||||
IF FIRSTACTIVE = -1 THEN FIRSTACTIVE = I
|
||||
LASTACTIVE = I
|
||||
END IF
|
||||
NEXT
|
||||
|
||||
' DETERMINE WHETHER TO YIELD ANYTHING IN THIS ITERATION BASED ON WHETHER WHILEANY IS TRUE.
|
||||
' NOT YIELDING ANYTHING THIS ITERATION IMPLIES THAT THE ENUMERATION HAS ENDED.
|
||||
DIM THISITERHASRESULTS AS BOOLEAN = IF(WHILEANY, FIRSTACTIVE <> -1, FIRSTACTIVE = 0 ANDALSO LASTACTIVE = NUMSOURCES - 1)
|
||||
IF NOT THISITERHASRESULTS THEN EXIT DO
|
||||
|
||||
' DON'T INSERT A SEPARATOR ON THE FIRST PASS.
|
||||
IF ANYPREVITERS THEN
|
||||
IF USEOUTERSEPARATOR THEN YIELD OUTERSEPARATOR
|
||||
ELSE
|
||||
ANYPREVITERS = TRUE
|
||||
END IF
|
||||
|
||||
' GO THROUGH AND YIELD FROM THE SUB-SOURCES THAT STILL HAVE ELEMENTS.
|
||||
FOR I = 0 TO NUMSOURCES - 1
|
||||
IF ENUMERATORSTATES(I) THEN
|
||||
' DON'T INSERT A SEPARATOR BEFORE THE FIRST ELEMENT.
|
||||
IF I > FIRSTACTIVE ANDALSO USEINNERSEPARATOR THEN YIELD INNERSEPARATOR
|
||||
YIELD SOURCEENUMERATORS(I).CURRENT
|
||||
END IF
|
||||
NEXT
|
||||
LOOP
|
||||
|
||||
FINALLY
|
||||
IF SOURCEENUMERATORS ISNOT NOTHING THEN
|
||||
FOR EACH EN IN SOURCEENUMERATORS
|
||||
EN.DISPOSE()
|
||||
NEXT
|
||||
END IF
|
||||
END TRY
|
||||
END FUNCTION
|
||||
|
||||
''' <SUMMARY>
|
||||
''' RETURNS THE ROWS REPRESENTING ONE MONTH CELL WITHOUT TRAILING NEWLINES. APPROPRIATE LEADING AND TRAILING
|
||||
''' WHITESPACE IS ADDED SO THAT EVERY ROW HAS THE LENGTH OF WIDTH.
|
||||
''' </SUMMARY>
|
||||
''' <PARAM NAME="DT">A DATE WITHIN THE MONTH TO REPRESENT.</PARAM>
|
||||
''' <PARAM NAME="WIDTH">THE WIDTH OF THE CELL.</PARAM>
|
||||
''' <PARAM NAME="HEIGHT">THE HEIGHT.</PARAM>
|
||||
''' <PARAM NAME="VERTSTRETCH">IF <SEE LANGWORD="TRUE" />, BLANK ROWS ARE INSERTED TO FIT THE AVAILABLE HEIGHT.
|
||||
''' OTHERWISE, THE CELL HAS A CONSTANT HEIGHT OF </PARAM>
|
||||
''' <PARAM NAME="HORIZSTRETCH">IF <SEE LANGWORD="TRUE" />, THE SPACING BETWEEN INDIVIDUAL DAYS IS INCREASED TO
|
||||
''' FIT THE AVAILABLE WIDTH. OTHERWISE, THE CELL HAS A CONSTANT WIDTH OF 20 CHARACTERS AND IS PADDED TO BE IN
|
||||
''' THE CENTER OF THE EXPECTED WIDTH.</PARAM>
|
||||
ITERATOR FUNCTION BUILDMONTH(DT AS DATE, WIDTH AS INTEGER, HEIGHT AS INTEGER, VERTSTRETCH AS BOOLEAN, HORIZSTRETCH AS BOOLEAN) AS IENUMERABLE(OF STRING)
|
||||
CONST DAY_WDT = 2 ' WIDTH OF A DAY.
|
||||
CONST ALLDAYS_WDT = DAY_WDT * 7 ' WIDTH OF AL LDAYS COMBINED.
|
||||
|
||||
' NORMALIZE THE DATE TO JANUARY 1.
|
||||
DT = NEW DATE(DT.YEAR, DT.MONTH, 1)
|
||||
|
||||
' HORIZONTAL WHITESPACE BETWEEN DAYS OF THE WEEK. CONSTANT OF 6 REPRESENTS 6 SEPARATORS PER LINE.
|
||||
DIM DAYSEP AS NEW STRING(" "C, MATH.MIN((WIDTH - ALLDAYS_WDT) \ 6, IF(HORIZSTRETCH, INTEGER.MAXVALUE, 1)))
|
||||
' NUMBER OF BLANK LINES BETWEEN ROWS.
|
||||
DIM VERTBLANKCOUNT = IF(NOT VERTSTRETCH, 0, (HEIGHT - 8) \ 7)
|
||||
|
||||
' WIDTH OF EACH DAY * 7 DAYS IN ONE ROW + DAY SEPARATOR LENGTH * 6 SEPARATORS PER LINE.
|
||||
DIM BLOCKWIDTH = ALLDAYS_WDT + DAYSEP.LENGTH * 6
|
||||
|
||||
' THE WHITESPACE AT THE BEGINNING OF EACH LINE.
|
||||
DIM LEFTPAD AS NEW STRING(" "C, (WIDTH - BLOCKWIDTH) \ 2)
|
||||
' THE WHITESPACE FOR BLANK LINES.
|
||||
DIM FULLPAD AS NEW STRING(" "C, WIDTH)
|
||||
|
||||
' LINES ARE "STAGED" IN THE STRINGBUILDER.
|
||||
DIM SB AS NEW STRINGBUILDER(LEFTPAD)
|
||||
DIM NUMLINES = 0
|
||||
|
||||
' GET THE CURRENT LINE SO FAR FORM THE STRINGBUILDER AND BEGIN A NEW LINE.
|
||||
' RETURNS THE CURRENT LINE AND TRAILING BLANK LINES USED FOR VERTICAL PADDING (IF ANY).
|
||||
' RETURNS EMPTY ENUMERABLE IF THE HEIGHT REQUIREMENT HAS BEEN REACHED.
|
||||
DIM ENDLINE =
|
||||
FUNCTION() AS IENUMERABLE(OF STRING)
|
||||
DIM FINISHEDLINE AS STRING = SB.TOSTRING().PADRIGHT(WIDTH)
|
||||
SB.CLEAR()
|
||||
SB.APPEND(LEFTPAD)
|
||||
|
||||
' USE AN INNER ITERATOR TO PREVENT LAZY EXECUTION OF SIDE EFFECTS OF OUTER FUNCTION.
|
||||
RETURN IF(NUMLINES >= HEIGHT,
|
||||
ENUMERABLE.EMPTY(OF STRING)(),
|
||||
ITERATOR FUNCTION() AS IENUMERABLE(OF STRING)
|
||||
YIELD FINISHEDLINE
|
||||
NUMLINES += 1
|
||||
|
||||
FOR I = 1 TO VERTBLANKCOUNT
|
||||
IF NUMLINES >= HEIGHT THEN RETURN
|
||||
YIELD FULLPAD
|
||||
NUMLINES += 1
|
||||
NEXT
|
||||
END FUNCTION())
|
||||
END FUNCTION
|
||||
|
||||
' YIELD THE MONTH NAME.
|
||||
SB.APPEND(PADCENTER(DT.TOSTRING("MMMM", CULTUREINFO.INVARIANTCULTURE), BLOCKWIDTH).TOUPPER())
|
||||
FOR EACH L IN ENDLINE()
|
||||
YIELD L
|
||||
NEXT
|
||||
|
||||
' YIELD THE HEADER OF WEEKDAY NAMES.
|
||||
DIM WEEKNMABBREVS = [ENUM].GETNAMES(GETTYPE(DAYOFWEEK)).SELECT(FUNCTION(X) X.SUBSTRING(0, 2).TOUPPER())
|
||||
SB.APPEND(STRING.JOIN(DAYSEP, WEEKNMABBREVS))
|
||||
FOR EACH L IN ENDLINE()
|
||||
YIELD L
|
||||
NEXT
|
||||
|
||||
' DAY OF WEEK OF FIRST DAY OF MONTH.
|
||||
DIM STARTWKDY = CINT(DT.DAYOFWEEK)
|
||||
|
||||
' INITIALIZE WITH EMPTY SPACE FOR THE FIRST LINE.
|
||||
DIM FIRSTPAD AS NEW STRING(" "C, (DAY_WDT + DAYSEP.LENGTH) * STARTWKDY)
|
||||
SB.APPEND(FIRSTPAD)
|
||||
|
||||
DIM D = DT
|
||||
DO WHILE D.MONTH = DT.MONTH
|
||||
SB.APPENDFORMAT(CULTUREINFO.INVARIANTCULTURE, $"{{0,{DAY_WDT}}}", D.DAY)
|
||||
|
||||
' EACH ROW ENDS ON SATURDAY.
|
||||
IF D.DAYOFWEEK = DAYOFWEEK.SATURDAY THEN
|
||||
FOR EACH L IN ENDLINE()
|
||||
YIELD L
|
||||
NEXT
|
||||
ELSE
|
||||
SB.APPEND(DAYSEP)
|
||||
END IF
|
||||
|
||||
D = D.ADDDAYS(1)
|
||||
LOOP
|
||||
|
||||
' KEEP ADDING EMPTY LINES UNTIL THE HEIGHT QUOTA IS MET.
|
||||
DIM NEXTLINES AS IENUMERABLE(OF STRING)
|
||||
DO
|
||||
NEXTLINES = ENDLINE()
|
||||
FOR EACH L IN NEXTLINES
|
||||
YIELD L
|
||||
NEXT
|
||||
LOOP WHILE NEXTLINES.ANY()
|
||||
END FUNCTION
|
||||
|
||||
''' <SUMMARY>
|
||||
''' RETURNS A NEW STRING THAT CENTER-ALIGNS THE CHARACTERS IN THIS STRING BY PADDING TO THE LEFT AND RIGHT WITH
|
||||
''' THE SPECIFIED CHARACTER TO A SPECIFIED TOTAL LENGTH.
|
||||
''' </SUMMARY>
|
||||
''' <PARAM NAME="S">THE STRING TO CENTER-ALIGN.</PARAM>
|
||||
''' <PARAM NAME="TOTALWIDTH">THE NUMBER OF CHARACTERS IN THE RESULTING STRING.</PARAM>
|
||||
''' <PARAM NAME="PADDINGCHAR">THE PADDING CHARACTER.</PARAM>
|
||||
<EXTENSION()>
|
||||
PRIVATE FUNCTION PADCENTER(S AS STRING, TOTALWIDTH AS INTEGER, OPTIONAL PADDINGCHAR AS CHAR = " "C) AS STRING
|
||||
RETURN S.PADLEFT(((TOTALWIDTH - S.LENGTH) \ 2) + S.LENGTH, PADDINGCHAR).PADRIGHT(TOTALWIDTH, PADDINGCHAR)
|
||||
END FUNCTION
|
||||
END MODULE
|
||||
Loading…
Add table
Add a link
Reference in a new issue