calendarium-romanum 0.5.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +5 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +50 -0
  5. data/.travis.yml +23 -0
  6. data/.yardopts +3 -0
  7. data/Appraisals +67 -0
  8. data/CHANGELOG.md +488 -0
  9. data/Gemfile +26 -0
  10. data/Gemfile.lock +95 -0
  11. data/README.md +601 -0
  12. data/Rakefile +27 -0
  13. data/bin/calendariumrom +3 -0
  14. data/calendarium-romanum.gemspec +31 -0
  15. data/config/locales/cs.yml +4 -0
  16. data/config/locales/en.yml +20 -14
  17. data/config/locales/es.yml +94 -0
  18. data/config/locales/fr.yml +6 -0
  19. data/config/locales/it.yml +6 -0
  20. data/config/locales/la.yml +6 -0
  21. data/config/locales/pt.yml +94 -0
  22. data/data/README.md +70 -24
  23. data/data/czech-brno-cs.txt +4 -6
  24. data/data/czech-budejovice-cs.txt +4 -6
  25. data/data/czech-cechy-cs.txt +4 -5
  26. data/data/czech-cs.txt +239 -235
  27. data/data/czech-hradec-cs.txt +3 -5
  28. data/data/czech-litomerice-cs.txt +5 -7
  29. data/data/czech-morava-cs.txt +4 -5
  30. data/data/czech-olomouc-cs.txt +2 -4
  31. data/data/czech-ostrava-cs.txt +3 -5
  32. data/data/czech-plzen-cs.txt +3 -5
  33. data/data/czech-praha-cs.txt +3 -4
  34. data/data/easter_dates.txt +67 -0
  35. data/data/universal-1969-la.txt +234 -0
  36. data/data/universal-en.txt +217 -211
  37. data/data/universal-es.txt +246 -0
  38. data/data/universal-fr.txt +217 -210
  39. data/data/universal-it.txt +217 -211
  40. data/data/universal-la.txt +217 -212
  41. data/data/universal-pt.txt +248 -0
  42. data/doc/data_readme.md +2 -0
  43. data/doc/images/class_diagram.png +0 -0
  44. data/doc/images/class_diagram.puml +44 -0
  45. data/doc/yard_readme.rdoc +76 -0
  46. data/lib/calendarium-romanum.rb +16 -2
  47. data/lib/calendarium-romanum/abstract_date.rb +15 -0
  48. data/lib/calendarium-romanum/calendar.rb +150 -33
  49. data/lib/calendarium-romanum/cli.rb +80 -100
  50. data/lib/calendarium-romanum/cli/comparator.rb +83 -0
  51. data/lib/calendarium-romanum/cli/date_parser.rb +30 -0
  52. data/lib/calendarium-romanum/cli/dumper.rb +68 -0
  53. data/lib/calendarium-romanum/cli/helper.rb +23 -0
  54. data/lib/calendarium-romanum/cli/querier.rb +73 -0
  55. data/lib/calendarium-romanum/cr.rb +16 -0
  56. data/lib/calendarium-romanum/data.rb +40 -8
  57. data/lib/calendarium-romanum/day.rb +187 -32
  58. data/lib/calendarium-romanum/enum.rb +41 -24
  59. data/lib/calendarium-romanum/enums.rb +127 -43
  60. data/lib/calendarium-romanum/errors.rb +1 -1
  61. data/lib/calendarium-romanum/ordinalizer.rb +10 -1
  62. data/lib/calendarium-romanum/perpetual_calendar.rb +58 -7
  63. data/lib/calendarium-romanum/rank.rb +39 -8
  64. data/lib/calendarium-romanum/rank_predicates.rb +43 -0
  65. data/lib/calendarium-romanum/sanctorale.rb +213 -23
  66. data/lib/calendarium-romanum/sanctorale_factory.rb +74 -3
  67. data/lib/calendarium-romanum/sanctorale_loader.rb +180 -0
  68. data/lib/calendarium-romanum/sanctorale_writer.rb +124 -0
  69. data/lib/calendarium-romanum/temporale.rb +222 -42
  70. data/lib/calendarium-romanum/temporale/celebration_factory.rb +68 -9
  71. data/lib/calendarium-romanum/temporale/date_helper.rb +85 -0
  72. data/lib/calendarium-romanum/temporale/dates.rb +52 -59
  73. data/lib/calendarium-romanum/temporale/easter_table.rb +27 -0
  74. data/lib/calendarium-romanum/temporale/extensions.rb +15 -0
  75. data/lib/calendarium-romanum/temporale/extensions/christ_eternal_priest.rb +16 -3
  76. data/lib/calendarium-romanum/temporale/extensions/dedication_before_all_saints.rb +73 -0
  77. data/lib/calendarium-romanum/transfers.rb +84 -24
  78. data/lib/calendarium-romanum/util.rb +21 -23
  79. data/lib/calendarium-romanum/version.rb +3 -2
  80. data/liturgical_law/1969_normae_universales.md +568 -0
  81. data/liturgical_law/1977_decretum_de_celebratione_baptismatis_domini.md +58 -0
  82. data/liturgical_law/1990_decretum_de_variatione_inducenda.md +67 -0
  83. data/liturgical_law/1998_notificatio_de_occurrentia.md +57 -0
  84. data/liturgical_law/2002_normae_universales.md +946 -0
  85. data/liturgical_law/2006_notification.md +37 -0
  86. data/liturgical_law/2012_declarationes.md +38 -0
  87. data/liturgical_law/2020_dubia_de_calendario_2022.md +100 -0
  88. data/liturgical_law/README.md +74 -0
  89. metadata +61 -38
  90. data/lib/calendarium-romanum/sanctoraleloader.rb +0 -122
  91. data/spec/abstract_date_spec.rb +0 -62
  92. data/spec/calendar_spec.rb +0 -559
  93. data/spec/celebration_factory_spec.rb +0 -16
  94. data/spec/celebration_spec.rb +0 -43
  95. data/spec/cli_spec.rb +0 -155
  96. data/spec/colour_spec.rb +0 -17
  97. data/spec/data_spec.rb +0 -23
  98. data/spec/date_parser_spec.rb +0 -68
  99. data/spec/date_spec.rb +0 -61
  100. data/spec/dates_spec.rb +0 -45
  101. data/spec/day_spec.rb +0 -108
  102. data/spec/enum_spec.rb +0 -51
  103. data/spec/i18n_spec.rb +0 -58
  104. data/spec/ordinalizer_spec.rb +0 -36
  105. data/spec/perpetual_calendar_spec.rb +0 -91
  106. data/spec/rank_spec.rb +0 -57
  107. data/spec/readme_spec.rb +0 -56
  108. data/spec/sanctorale_factory_spec.rb +0 -42
  109. data/spec/sanctorale_spec.rb +0 -191
  110. data/spec/sanctoraleloader_spec.rb +0 -176
  111. data/spec/season_spec.rb +0 -17
  112. data/spec/spec_helper.rb +0 -46
  113. data/spec/temporale_spec.rb +0 -572
@@ -1,20 +1,52 @@
1
- require 'date'
2
1
  require 'forwardable'
3
2
 
4
3
  module CalendariumRomanum
5
4
 
6
5
  # Provides complete information concerning a liturgical year,
7
6
  # it's days and celebrations occurring on them.
7
+ #
8
+ # {Calendar}'s business logic is mostly about correctly combining
9
+ # information from {Temporale} and {Sanctorale}.
8
10
  class Calendar
9
11
  extend Forwardable
10
12
 
11
13
  # Day when the implemented calendar system became effective
12
14
  EFFECTIVE_FROM = Date.new(1970, 1, 1).freeze
13
15
 
14
- # year: Integer
15
- # returns a calendar for the liturgical year beginning with
16
+ # Returns a calendar for the liturgical year beginning with
16
17
  # Advent of the specified civil year.
17
- def initialize(year, sanctorale = nil, temporale = nil, vespers: false)
18
+ #
19
+ # @overload initialize(year, sanctorale = nil, temporale = nil, vespers: false, transfers: nil)
20
+ # @param year [Integer]
21
+ # Civil year when the liturgical year begins.
22
+ # @param sanctorale [Sanctorale, nil]
23
+ # If not provided, the +Calendar+ will only know celebrations
24
+ # of the temporale cycle, no feasts of the saints!
25
+ # @param temporale [Temporale, nil]
26
+ # If not provided, +Temporale+ for the given year with default
27
+ # configuration will built.
28
+ # @param vespers [Boolean] Set to true if you want the +Calendar+ to populate {Day#vespers}
29
+ # @param transfers [#call, nil]
30
+ # Object with the same public interface as the +Transfers+ class (really class,
31
+ # not instance!), responsible for handling transfers of conflicting solemnities.
32
+ # Only useful for overriding the default solemnity transfer logic with a custom one.
33
+ #
34
+ # @overload initialize(temporale, sanctorale=nil, vespers: false, transfers: nil)
35
+ # @param temporale [Temporale]
36
+ # @param sanctorale [Sanctorale, nil]
37
+ # @param vespers [Boolean]
38
+ # @param transfers [#call, nil]
39
+ # @since 0.8.0
40
+ #
41
+ # @raise [RangeError]
42
+ # if +year+ is specified for which the implemented calendar
43
+ # system wasn't in force
44
+ def initialize(year, sanctorale = nil, temporale = nil, vespers: false, transfers: nil)
45
+ unless year.is_a? Integer
46
+ temporale = year
47
+ year = temporale.year
48
+ end
49
+
18
50
  if year < (EFFECTIVE_FROM.year - 1)
19
51
  raise system_not_effective
20
52
  end
@@ -28,26 +60,23 @@ module CalendariumRomanum
28
60
  @temporale = temporale || Temporale.new(year)
29
61
  @populate_vespers = vespers
30
62
 
31
- @transferred = Transfers.new(@temporale, @sanctorale)
63
+ @transferred = (transfers || Transfers).call(@temporale, @sanctorale).freeze
32
64
  end
33
65
 
34
66
  class << self
67
+ # @api private
35
68
  def mk_date(*args)
36
69
  ex = TypeError.new('Date, DateTime or three Integers expected')
37
70
 
38
71
  if args.size == 3
39
72
  args.each do |a|
40
- unless a.is_a? Integer
41
- raise ex
42
- end
73
+ raise ex unless a.is_a? Integer
43
74
  end
44
75
  return Date.new(*args)
45
76
 
46
77
  elsif args.size == 1
47
78
  a = args.first
48
- unless a.is_a? Date
49
- raise ex
50
- end
79
+ raise ex unless a.is_a? Date
51
80
  return a
52
81
 
53
82
  else
@@ -55,38 +84,95 @@ module CalendariumRomanum
55
84
  end
56
85
  end
57
86
 
58
- # creates a Calendar for the liturgical year including given
59
- # date
87
+ # Creates a new instance for the liturgical year which includes
88
+ # given date
89
+ #
90
+ # @param date [Date]
91
+ # @param constructor_args
92
+ # arguments that will be passed to {initialize}
93
+ # @return [Calendar]
60
94
  def for_day(date, *constructor_args)
61
95
  new(Temporale.liturgical_year(date), *constructor_args)
62
96
  end
63
97
  end # class << self
64
98
 
99
+ # @!method range_check(date)
100
+ # @see Temporale#range_check
101
+ # @param date
102
+ # @return [void]
103
+ # @!method season(date)
104
+ # @see Temporale#season
105
+ # @param date
106
+ # @return [Season]
65
107
  def_delegators :@temporale, :range_check, :season
108
+
109
+ # @return [Integer]
66
110
  attr_reader :year
111
+
112
+ # @return [Temporale]
67
113
  attr_reader :temporale
114
+
115
+ # @return [Sanctorale]
68
116
  attr_reader :sanctorale
69
117
 
70
- def ==(obj)
71
- unless obj.is_a? Calendar
72
- return false
73
- end
118
+ # Solemnities transferred to a date different from the usual one
119
+ # due to occurrence with a higher-ranking celebration.
120
+ #
121
+ # @return [Hash<Date=>Celebration>]
122
+ # @since 0.8.0
123
+ attr_reader :transferred
124
+
125
+ # Do {Day} instances returned by this +Calendar+
126
+ # have {Day#vespers} populated?
127
+ # @return [Boolean]
128
+ # @since 0.6.0
129
+ def populates_vespers?
130
+ @populate_vespers
131
+ end
74
132
 
75
- year == obj.year
133
+ # Two +Calendar+s are equal if they have equal settings
134
+ # (which means that to equal input they return equal data)
135
+ def ==(b)
136
+ b.class == self.class &&
137
+ year == b.year &&
138
+ populates_vespers? == b.populates_vespers? &&
139
+ temporale == b.temporale &&
140
+ sanctorale == b.sanctorale
76
141
  end
77
142
 
143
+ # Retrieve liturgical calendar information for the specified day
144
+ # or range of days.
145
+ #
146
+ # @overload [](date)
147
+ # @param date [Date]
148
+ # @return [Day]
149
+ # @overload [](range)
150
+ # @param range [Range<Date>]
151
+ # @return [Array<Day>]
78
152
  def [](args)
79
- if(args.is_a?(Range))
80
- args.map{|date| day(date)}
153
+ if args.is_a?(Range)
154
+ args.map {|date| day(date) }
81
155
  else
82
- day(*args)
156
+ day(args)
83
157
  end
84
158
  end
85
159
 
86
- # accepts date information represented as
87
- # Date, DateTime, or two to three integers
88
- # (month - day or year - month - day);
89
- # returns filled Day for the specified day
160
+ # Retrieve liturgical calendar information for the specified day
161
+ #
162
+ # @overload day(date, vespers: false)
163
+ # @param date [Date]
164
+ # @overload day(year, month, day, vespers: false)
165
+ # @param year [Integer]
166
+ # @param month [Integer]
167
+ # @param day [Integer]
168
+ # @param vespers [Boolean]
169
+ # Set to +true+ in order to get {Day} with {Day#vespers}
170
+ # populated (overrides instance-wide setting {#populates_vespers?}).
171
+ # @return [Day]
172
+ # @raise [RangeError]
173
+ # If a date is specified on which the implemented calendar
174
+ # system was not yet in force (it became effective during
175
+ # the liturgical year 1969/1970)
90
176
  def day(*args, vespers: false)
91
177
  if args.size == 2
92
178
  date = Date.new(@year, *args)
@@ -124,16 +210,41 @@ module CalendariumRomanum
124
210
  )
125
211
  end
126
212
 
213
+ # Iterate over the whole liturgical year, day by day,
214
+ # for each day yield calendar data.
215
+ # If called without a block, returns +Enumerator+.
216
+ #
217
+ # @yield [Day]
218
+ # @return [void, Enumerator]
219
+ # @since 0.6.0
220
+ def each
221
+ return to_enum(__method__) unless block_given?
222
+
223
+ temporale.date_range
224
+ .each {|date| yield(day(date)) }
225
+ end
226
+
127
227
  # Sunday lectionary cycle
228
+ #
229
+ # @return [Symbol]
230
+ # For possible values see {LECTIONARY_CYCLES}
128
231
  def lectionary
129
232
  LECTIONARY_CYCLES[@year % 3]
130
233
  end
131
234
 
132
235
  # Ferial lectionary cycle
236
+ #
237
+ # @return [1, 2]
133
238
  def ferial_lectionary
134
239
  @year % 2 + 1
135
240
  end
136
241
 
242
+ # Freezes the instance.
243
+ #
244
+ # *WARNING*: {Temporale} and {Sanctorale} instances passed
245
+ # to the +Calendar+ on initialization will be frozen, too!
246
+ # This is necessary, because a +Calendar+ would not really be
247
+ # frozen were it possible to mutate it's key components.
137
248
  def freeze
138
249
  @temporale.freeze
139
250
  @sanctorale.freeze
@@ -143,25 +254,31 @@ module CalendariumRomanum
143
254
  private
144
255
 
145
256
  def celebrations_for(date)
146
- tr = @transferred.get(date)
257
+ tr = @transferred[date]
147
258
  return [tr] if tr
148
259
 
149
- t = @temporale.get date
150
- st = @sanctorale.get date
260
+ t = @temporale[date]
261
+ st = @sanctorale[date]
262
+
263
+ if date.saturday? &&
264
+ @temporale.season(date) == Seasons::ORDINARY &&
265
+ (st.empty? || st.first.rank == Ranks::MEMORIAL_OPTIONAL) &&
266
+ t.rank <= Ranks::MEMORIAL_OPTIONAL
267
+ st += [Temporale::CelebrationFactory.saturday_memorial_bvm]
268
+ end
151
269
 
152
270
  unless st.empty?
153
271
  if st.first.rank > t.rank
154
272
  if st.first.rank == Ranks::MEMORIAL_OPTIONAL
155
- return st.dup.unshift t
273
+ return [t] + st
156
274
  else
157
275
  return st
158
276
  end
159
277
  elsif t.rank == Ranks::FERIAL_PRIVILEGED && st.first.rank.memorial?
160
- st = st.collect do |c|
161
- Celebration.new(c.title, Ranks::COMMEMORATION, t.colour)
278
+ commemorations = st.collect do |c|
279
+ c.change(rank: Ranks::COMMEMORATION, colour: t.colour)
162
280
  end
163
- st.unshift t
164
- return st
281
+ return [t] + commemorations
165
282
  elsif t.symbol == :immaculate_heart &&
166
283
  [Ranks::MEMORIAL_GENERAL, Ranks::MEMORIAL_PROPER].include?(st.first.rank)
167
284
  optional_memorials = ([t] + st).collect do |celebration|
@@ -1,136 +1,116 @@
1
1
  require 'thor'
2
2
 
3
+ # monkey patch preventing Thor from screwing formatting in our commands' long_desc
4
+ # credits: https://github.com/erikhuda/thor/issues/398#issuecomment-237400762
5
+ class Thor
6
+ module Shell
7
+ class Basic
8
+ def print_wrapped(message, options = {})
9
+ stdout.puts message
10
+ end
11
+ end
12
+ end
13
+ end
14
+
3
15
  module CalendariumRomanum
4
16
 
17
+ # Implementation of the +calendariumrom+ executable.
18
+ # _Not_ loaded by default when you +require+ the gem.
19
+ #
20
+ # @api private
5
21
  class CLI < Thor
6
- include CalendariumRomanum::Util
7
-
8
- desc 'query 2007-06-05', 'show calendar information for a specified date'
9
- option :calendar, default: 'universal-en', aliases: :c
10
- option :locale, default: 'en', aliases: :l
22
+ desc 'query [DATE]', 'show calendar information for a specified date/month/year'
23
+ long_desc <<-EOS
24
+ show calendar information for a specified date/month/year
25
+
26
+ DATE formats:
27
+ not specified - today
28
+ 2000-01-02 - single date
29
+ 2000-01 - month
30
+ 2000 - year
31
+ EOS
32
+ option :calendar, default: Data::GENERAL_ROMAN_ENGLISH.siglum, aliases: :c, desc: 'sanctorale data file to use (filesystem path or identifier of a bundled one)'
33
+ option :locale, default: 'en', aliases: :l, desc: 'locale to use for localized strings'
11
34
  def query(date_str = nil)
12
- I18n.locale = options[:locale]
13
- calendar = options[:calendar]
14
- if File.exist?(calendar)
15
- begin
16
- sanctorale = SanctoraleLoader.new.load_from_file(calendar)
17
- rescue CalendariumRomanum::InvalidDataError
18
- die! 'Invalid file format.'
19
- end
20
- else
21
- data_file = Data[calendar]
22
-
23
- if data_file.nil?
24
- die! "Invalid calendar. Either loading a calendar from filesystem did not succeed, \n or a preinstalled calendar was specified which doesn't exist. See subcommand `calendars` for valid options."
25
- end
26
- sanctorale = data_file.load
27
- end
28
-
29
- pcal = PerpetualCalendar.new sanctorale: sanctorale
30
-
31
- if date_str
32
- begin
33
- parsed_date = DateParser.new(date_str)
34
- parsed_date.date_range.each do |day|
35
- print_single_date(pcal, day)
36
- end
37
- rescue ArgumentError
38
- die! 'Invalid date.'
39
- end
40
- else
41
- print_single_date(pcal, Date.today)
42
- end
35
+ Querier
36
+ .new(locale: options[:locale], calendar: options[:calendar])
37
+ .call(date_str)
43
38
  end
44
39
 
45
- desc 'calendars', 'lists calendars available for querying'
40
+ desc 'calendars', 'list calendars available for querying'
46
41
  def calendars
47
42
  Data.each {|c| puts c.siglum }
48
43
  end
49
44
 
50
- desc 'errors FILE1, ...', 'finds errors in sanctorale data files'
45
+ desc 'errors FILE1 ...', 'find errors in sanctorale data files'
51
46
  def errors(*files)
52
- loader = SanctoraleLoader.new
53
47
  files.each do |path|
54
- s = Sanctorale.new
55
48
  begin
56
- loader.load_from_file path, s
49
+ sanctorale_from_path path
57
50
  rescue Errno::ENOENT, InvalidDataError => err
58
51
  die! err.message
59
52
  end
60
53
  end
61
54
  end
62
55
 
63
- desc 'cmp FILE1, FILE2', 'detect differences in rank and colour of corresponding celebrations'
56
+ desc 'cmp FILE1 FILE2', 'detect differences between two sanctorale data files'
57
+ option :no_rank, type: :boolean, desc: 'ignore differences of rank'
58
+ option :no_colour, type: :boolean, desc: 'ignore differences of colour'
59
+ option :no_symbol, type: :boolean, desc: 'ignore differences of symbol'
60
+ option :title, type: :boolean, desc: 'report differences of title'
64
61
  def cmp(a, b)
65
- loader = SanctoraleLoader.new
66
- paths = [a, b]
67
- sanctoralia = paths.collect {|source| loader.load_from_file source }
68
- names = paths.collect {|source| File.basename source }
69
-
70
- # a leap year must be chosen in order to iterate over
71
- # all possible days of a Sanctorale
72
- Year.new(1990).each_day do |d|
73
- a, b = sanctoralia.collect {|s| s.get(d) }
74
-
75
- 0.upto([a.size, b.size].max - 1) do |i|
76
- ca = a[i]
77
- cb = b[i]
78
- compared = [ca, cb]
79
- differences = []
80
-
81
- if compared.index(&:nil?)
82
- notnili = compared.index {|c| !c.nil? }
83
-
84
- print date(d)
85
- puts " only in #{names[notnili]}:"
86
- puts celebration(compared[notnili])
87
- puts
88
- next
89
- end
90
-
91
- differences << 'rank' if ca.rank != cb.rank
92
- differences << 'colour' if ca.colour != cb.colour
93
-
94
- next if differences.empty?
95
- print date(d)
96
- puts " differs in #{differences.join(', ')}"
97
- puts celebration(ca)
98
- puts celebration(cb)
99
- puts
62
+ properties = Comparator::DEFAULT_PROPERTIES
63
+ options.each_key do |k|
64
+ if k.start_with? 'no_'
65
+ properties.delete k.sub('no_', '').to_sym
66
+ else
67
+ properties << k.to_sym
100
68
  end
101
69
  end
70
+ Comparator.new(properties).call(a, b) || exit(1)
102
71
  end
103
72
 
104
- private
105
-
106
- def date(d)
107
- "#{d.month}/#{d.day}"
73
+ desc 'merge FILE1 ...', 'loads sanctorale data files on top of each other, prints the resulting sanctorale'
74
+ option :front_matter, type: :boolean, desc: 'output YAML front matter'
75
+ def merge(*files)
76
+ sanctoralia = files.collect {|path| sanctorale_from_path path }
77
+ merged = SanctoraleFactory.create_layered *sanctoralia
78
+ SanctoraleWriter.new(front_matter: options[:front_matter]).write merged, STDOUT
108
79
  end
109
80
 
110
- def celebration(c)
111
- "#{c.rank.priority} #{c.colour.symbol} | #{c.title}"
81
+ desc 'id FILE', 'print celebration identifiers found in a sanctorale data file'
82
+ def id(file)
83
+ sanctorale_from_path(file).each_day do |_, celebrations|
84
+ celebrations.each do |c|
85
+ puts c.symbol if c.symbol
86
+ end
87
+ end
112
88
  end
113
89
 
114
- def die!(message, code = 1)
115
- STDERR.puts message
116
- exit code
90
+ desc 'dump YEAR', 'print calendar of the specified year for use in regression tests'
91
+ def dump(year)
92
+ Dumper.new.regression_tests_dump year.to_i
117
93
  end
118
94
 
119
- def print_single_date(calendar, date)
120
- day = calendar.day date
121
-
122
- puts date
123
- puts "season: #{day.season.name}"
124
- puts
125
-
126
- rank_length = day.celebrations.collect {|c| c.rank.short_desc.nil? ? 0 : c.rank.short_desc.size }.max
127
- day.celebrations.each do |c|
128
- next if c.rank.short_desc.nil?
129
- print c.rank.short_desc.rjust(rank_length)
130
- print ' : '
131
- puts c.title
132
- end
95
+ desc 'version', 'print version information'
96
+ def version
97
+ puts 'calendarium-romanum CLI'
98
+ puts "calendarium-romanum: version #{CalendariumRomanum::VERSION}, released #{CalendariumRomanum::RELEASE_DATE}"
133
99
  end
100
+ end
101
+ end
102
+
103
+ # required files reopen the CLI class - require after the class'es main definition
104
+ # in order to prevent superclass mismatch errors
105
+ require_relative 'cli/helper'
134
106
 
107
+ module CalendariumRomanum
108
+ class CLI
109
+ include Helper
135
110
  end
136
111
  end
112
+
113
+ require_relative 'cli/comparator'
114
+ require_relative 'cli/date_parser'
115
+ require_relative 'cli/dumper'
116
+ require_relative 'cli/querier'