85 lines
2.9 KiB
Ruby
85 lines
2.9 KiB
Ruby
# CAL.RB - CALENDAR
|
|
REQUIRE 'DATE'.DOWNCASE
|
|
|
|
# FIND CLASSES.
|
|
OBJECT = [].CLASS.SUPERCLASS
|
|
DATE = OBJECT.CONST_GET('DATE'.DOWNCASE.CAPITALIZE)
|
|
|
|
# CREATES A CALENDAR OF _YEAR_. RETURNS THIS CALENDAR AS A MULTI-LINE
|
|
# STRING FIT TO _COLUMNS_.
|
|
OBJECT.SEND(:DEFINE_METHOD, :CAL) {|_YEAR, _COLUMNS|
|
|
|
|
# START AT JANUARY 1.
|
|
#
|
|
# DATE::ENGLAND MARKS THE SWITCH FROM JULIAN CALENDAR TO GREGORIAN
|
|
# CALENDAR AT 1752 SEPTEMBER 14. THIS REMOVES SEPTEMBER 3 TO 13 FROM
|
|
# YEAR 1752. (BY FORTUNE, IT KEEPS JANUARY 1.)
|
|
#
|
|
_DATE = DATE.NEW(_YEAR, 1, 1, DATE::ENGLAND)
|
|
|
|
# COLLECT CALENDARS OF ALL 12 MONTHS.
|
|
_MONTHS = (1..12).COLLECT {|_MONTH|
|
|
_ROWS = [DATE::MONTHNAMES[_MONTH].UPCASE.CENTER(20),
|
|
"SU MO TU WE TH FR SA"]
|
|
|
|
# MAKE ARRAY OF 42 DAYS, STARTING WITH SUNDAY.
|
|
_DAYS = []
|
|
_DATE.WDAY.TIMES { _DAYS.PUSH " " }
|
|
CATCH(:BREAK) {
|
|
LOOP {
|
|
(_DATE.MONTH == _MONTH) || THROW(:BREAK)
|
|
_DAYS.PUSH("%2D".DOWNCASE % _DATE.MDAY)
|
|
_DATE += 1 }}
|
|
(42 - _DAYS.LENGTH).TIMES { _DAYS.PUSH " " }
|
|
|
|
_DAYS.EACH_SLICE(7) {|_WEEK| _ROWS.PUSH(_WEEK.JOIN " ") }
|
|
_ROWS }
|
|
|
|
# CALCULATE MONTHS PER ROW (MPR).
|
|
# 1. DIVIDE COLUMNS BY 22 COLUMNS PER MONTH, ROUNDED DOWN. (PRETEND
|
|
# TO HAVE 2 EXTRA COLUMNS; LAST MONTH USES ONLY 20 COLUMNS.)
|
|
# 2. DECREASE MPR IF 12 MONTHS WOULD FIT IN THE SAME MONTHS PER
|
|
# COLUMN (MPC). FOR EXAMPLE, IF WE CAN FIT 5 MPR AND 3 MPC, THEN
|
|
# WE USE 4 MPR AND 3 MPC.
|
|
_MPR = (_COLUMNS + 2).DIV 22
|
|
_MPR = 12.DIV((12 + _MPR - 1).DIV _MPR)
|
|
|
|
# USE 20 COLUMNS PER MONTH + 2 SPACES BETWEEN MONTHS.
|
|
_WIDTH = _MPR * 22 - 2
|
|
|
|
# JOIN MONTHS INTO CALENDAR.
|
|
_ROWS = ["[SNOOPY]".CENTER(_WIDTH), "#{_YEAR}".CENTER(_WIDTH)]
|
|
_MONTHS.EACH_SLICE(_MPR) {|_SLICE|
|
|
_SLICE[0].EACH_INDEX {|_I|
|
|
_ROWS.PUSH(_SLICE.MAP {|_A| _A[_I]}.JOIN " ") }}
|
|
_ROWS.JOIN("\012") }
|
|
|
|
|
|
(ARGV.LENGTH == 1) || ABORT("USAGE: #{$0} YEAR")
|
|
|
|
# GUESS WIDTH OF TERMINAL.
|
|
# 1. OBEY ENVIRONMENT VARIABLE COLUMNS.
|
|
# 2. TRY TO REQUIRE 'IO/CONSOLE' FROM RUBY 1.9.3.
|
|
# 3. TRY TO RUN `TPUT CO`.
|
|
# 4. ASSUME 80 COLUMNS.
|
|
LOADERROR = OBJECT.CONST_GET('LOAD'.DOWNCASE.CAPITALIZE +
|
|
'ERROR'.DOWNCASE.CAPITALIZE)
|
|
STANDARDERROR = OBJECT.CONST_GET('STANDARD'.DOWNCASE.CAPITALIZE +
|
|
'ERROR'.DOWNCASE.CAPITALIZE)
|
|
_INTEGER = 'INTEGER'.DOWNCASE.CAPITALIZE
|
|
_TPUT_CO = 'TPUT CO'.DOWNCASE
|
|
_COLUMNS = RESCUE(PROC {SEND(_INTEGER, ENV["COLUMNS"] || "")},
|
|
STANDARDERROR,
|
|
PROC {
|
|
RESCUE(PROC {
|
|
REQUIRE 'IO/CONSOLE'.DOWNCASE
|
|
IO.CONSOLE.WINSIZE[1]
|
|
}, LOADERROR,
|
|
PROC {
|
|
RESCUE(PROC {
|
|
SEND(_INTEGER, `#{_TPUT_CO}`)
|
|
}, STANDARDERROR,
|
|
PROC {80}) }) })
|
|
|
|
PUTS CAL(ARGV[0].TO_I, _COLUMNS)
|