calrom 0.1.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,51 +1,301 @@
1
1
  require 'optparse'
2
+ require 'pattern-match'
2
3
 
3
4
  module Calrom
4
5
  # Parses command line options, produces Config.
5
6
  class OptionParser
6
- def self.call(argv)
7
- config = Config.new
7
+ using PatternMatch
8
+
9
+ # Raised when the options being parsed are invalid.
10
+ #
11
+ # Exceptions raised by the option parsing library are translated to this exception,
12
+ # thus hiding implementation details (the option parsing library's exception types)
13
+ # from the outer world.
14
+ class Error < RuntimeError; end
15
+
16
+ class CustomizedOptionParser < ::OptionParser
17
+ def separator(string)
18
+ super "\n" + string
19
+ end
20
+ end
21
+
22
+ def self.call(*args)
23
+ self.new.call(*args)
24
+ end
25
+
26
+ def call(argv, config = nil)
27
+ config ||= Config.new
8
28
 
9
29
  today = config.today
30
+
10
31
  year = today.year
11
32
  month = today.month
12
33
  day = nil
34
+ another_day = nil
13
35
 
14
36
  range_type = nil
15
37
 
16
- opt_parser = ::OptionParser.new do |opts|
17
- # for now does nothing, is default
18
- opts.on('-l', '--list', 'list mode')
38
+ opt_parser = CustomizedOptionParser.new do |opts|
39
+ opts.banner = <<~EOS
40
+ Usage: calrom [options] [arg1 [arg2]]
41
+
42
+ Specifying date range (cal/ncal-compatible):
43
+
44
+ calrom - current month
45
+ calrom -m 5 - May of the current year
46
+ calrom -m 5p - May of the previous year
47
+ calrom -m 5f - May of the following year
48
+ calrom -m 5 2000 - May 2000
49
+ calrom 5 2000 - also May 2000
50
+ calrom 2000 - whole year 2000
51
+ calrom -y 2000 - also whole year 2000
52
+ calrom -y - whole current year
53
+ calrom -3 - display the previous, current and next month surrounding today
54
+
55
+ Specifying date range (not cal-compatible):
56
+
57
+ calrom 2000-05-31 - specified day (only)
58
+ calrom 2000-05-31 2000-07-01 - arbitrary date range
59
+ calrom (--yesterday|--today|--tomorrow)
60
+
61
+ EOS
19
62
 
20
- opts.on('-mMONTH', '--month=MONTH', 'which month to list') do |value|
63
+ opts.separator 'Configuration files'
64
+
65
+ opts.on('--config=CONFIG', 'load configuration from file (may be used multiple times, all specified files will be loaded)') do |value|
66
+ config.configs << value
67
+ end
68
+
69
+ opts.separator 'Options selecting date range'
70
+
71
+ # cal
72
+ opts.on('-m MONTH', '--month=MONTH', 'display the specified month. \'f\' or \'p\' can be appended to display the same month of the following or previous year respectively') do |value|
21
73
  range_type = :month
22
- month = value.to_i
74
+ if value =~ /^(\d+)([pf])$/
75
+ month = $1
76
+ year = validate_year(year) + ($2 == 'f' ? 1 : -1)
77
+ else
78
+ month = value
79
+ end
80
+ end
81
+
82
+ # cal
83
+ opts.on('-3', 'display the previous, current and next month surrounding today') do |value|
84
+ range_type = :three_months
85
+ end
86
+
87
+ # cal
88
+ opts.on('-y', '--year', 'display specified (or current) year') do |value|
89
+ range_type = :year
90
+ end
91
+
92
+ opts.on('--yesterday', 'display previous day') do |value|
93
+ day = today - 1
94
+ range_type = :day
95
+ end
96
+
97
+ opts.on('--today', 'display current day') do |value|
98
+ day = today
99
+ range_type = :day
100
+ end
101
+
102
+ opts.on('--tomorrow', 'display following day') do |value|
103
+ day = today + 1
104
+ range_type = :day
105
+ end
106
+
107
+ opts.separator "Options configuring liturgical calendar"
108
+
109
+ opts.on('-c CAL', '--calendar=CAL', 'specify (sanctorale) calendar to use. If repeated, layers all specified calendars one over another') do |value|
110
+ config.sanctorale << value
111
+ end
112
+
113
+ opts.on('--[no-]load-parents', 'explicitly enable/disable parent calendar loading') do |value|
114
+ config.load_parents = value
115
+ end
116
+
117
+ transferable = CR::Temporale::SUNDAY_TRANSFERABLE_SOLEMNITIES
118
+ opts.on('--to-sunday=SOLEMNITY', transferable, 'transfer solemnity to Sunday' + supported_values(transferable)) do |value|
119
+ config.transfer_to_sunday << value.to_sym
120
+ end
121
+
122
+ extensions = CR::Temporale::Extensions.all.collect {|cls| cls.name.split('::').last.to_sym }
123
+ opts.on('--temporale-extension=EXTENSION', extensions, 'use temporale extension' + supported_values(extensions)) do |value|
124
+ config.temporale_extensions << CR::Temporale::Extensions.const_get(value)
125
+ end
126
+
127
+ opts.on('--locale=LOCALE', 'override language in which temporale celebration titles are rendered' + supported_values(I18n.available_locales)) do |value|
128
+ config.locale = value.to_sym
129
+ end
130
+
131
+ opts.separator 'Options affecting presentation'
132
+
133
+ opts.on('-l', '--list', 'display detailed listing of days and celebrations (synonym to --format=list)') do
134
+ config.formatter = :list
135
+ end
136
+
137
+ supported_formats =
138
+ Calrom::Formatter.constants
139
+ .collect(&:downcase)
140
+ .delete_if {|i| i == :formatter }
141
+ formats_help = supported_formats.join(', ')
142
+ opts.on('--format=FORMAT', supported_formats, "specify output format (supported: #{formats_help})") do |value|
143
+ config.formatter = value
144
+ end
145
+
146
+ opts.on('--day-filter=EXPR', 'display only days for which the expression (Ruby snippet executed in context of each CalendariumRomanum::Day instance) evaluates as truthy') do |expr|
147
+ config.filter_days << expr
148
+ end
149
+
150
+ opts.on('--celebration-filter=EXPR', 'display only celebrations for which the expression (Ruby snippet executed in context of each CalendariumRomanum::Celebration instance) evaluates as truthy') do |expr|
151
+ config.filter_celebrations << expr
152
+ end
153
+
154
+ # cal
155
+ opts.on('-e', '--easter', 'display date of Easter (only)') do
156
+ config.formatter = :easter
157
+ end
158
+
159
+ opts.on('--calendars', 'list bundled calendars') do |value|
160
+ config.formatter = :calendars
161
+ end
162
+
163
+ opts.on('--[no-]color', 'enable/disable colours (enabled by default)') do |value|
164
+ config.colours = value
165
+ end
166
+
167
+ opts.on('-v', '--verbose', 'enable verbose output') do
168
+ config.verbose = true
169
+ end
170
+
171
+ opts.separator 'Debugging options'
172
+
173
+ # cal
174
+ opts.on('-d YM', '--current-month=YM', 'use given month (YYYY-MM) as the current month (for debugging of date range selection)') do |value|
175
+ year, month = value.split '-'
176
+ end
177
+
178
+ # cal
179
+ opts.on('-H DATE', '--highlight-date=DATE', 'use given date as the current date (for debugging of highlighting)') do |value|
180
+ config.today = validate_day value
181
+ end
182
+
183
+ opts.separator 'Information regarding calrom'
184
+
185
+ opts.on('-V', '--version', 'display calrom version') do
186
+ puts 'calrom v' + Calrom::VERSION
187
+ puts 'using calendarium-romanum v' + CR::VERSION
188
+ exit
189
+ end
190
+
191
+ # Normally optparse defines this option by default, but once -H option is added,
192
+ # for some reason -h (if not defined explicitly) is treated as -H.
193
+ opts.on('-h', '--help', 'display this help') do
194
+ puts opts
195
+ exit
23
196
  end
24
197
  end
25
198
 
26
- arguments = opt_parser.parse argv
199
+ begin
200
+ arguments = opt_parser.parse argv
201
+ rescue ::OptionParser::ParseError => e
202
+ raise Error.new(e.message)
203
+ end
27
204
 
28
- if arguments.size > 0
29
- arg = arguments[0]
30
- if arg =~ /^\d{4}-\d{2}-\d{2}$/
205
+ iso_date_regexp = /^(\d{4,}-\d{2}-\d{2})$/
206
+ match(arguments) do
207
+ with(_[iso_date_regexp.(date)]) do
31
208
  range_type = :day
32
- day = arg
33
- else
209
+ day = date
210
+ end
211
+
212
+ with(_[iso_date_regexp.(date), iso_date_regexp.(another_date)]) do
213
+ range_type = :free
214
+ day = date
215
+ another_day = another_date
216
+ end
217
+
218
+ with(_[y]) do
34
219
  range_type ||= :year
35
- year = arg.to_i
220
+ year = y
221
+ end
222
+
223
+ with(_[m, y]) do
224
+ range_type = :month
225
+ month, year = m, y
226
+ end
227
+
228
+ with([]) {}
229
+
230
+ with(_) do
231
+ raise InputError.new('too many arguments')
36
232
  end
37
233
  end
38
234
 
39
235
  config.date_range =
40
- if range_type == :year
236
+ build_date_range(
237
+ range_type,
238
+ validate_year(year),
239
+ validate_month(month),
240
+ day && validate_day(day),
241
+ another_day && validate_day(another_day)
242
+ )
243
+
244
+ config.freeze
245
+ end
246
+
247
+ protected
248
+
249
+ def validate_year(year)
250
+ unless year.is_a?(Integer) || year =~ /^\d+$/
251
+ raise InputError.new("not a valid year #{year}")
252
+ end
253
+
254
+ year.to_i
255
+ end
256
+
257
+ def validate_month(month)
258
+ unless month.is_a?(Integer) ||
259
+ (month =~ /^\d+$/ && (1..12).include?(month.to_i))
260
+ raise InputError.new("not a valid month #{month}")
261
+ end
262
+
263
+ month.to_i
264
+ end
265
+
266
+ def validate_day(day)
267
+ return day if day.is_a? Date
268
+
269
+ Date.parse(day)
270
+ rescue ArgumentError
271
+ raise InputError.new("not a valid date #{day}")
272
+ end
273
+
274
+ def build_date_range(range_type, year, month, day, another_day=nil)
275
+ range =
276
+ case range_type
277
+ when :year
41
278
  Year.new(year)
42
- elsif range_type == :day
43
- Day.new(Date.parse(day))
279
+ when :day
280
+ Day.new(day)
281
+ when :free
282
+ DateRange.new(day, another_day)
283
+ when :three_months
284
+ ThreeMonths.new(year, month)
44
285
  else
45
286
  Month.new(year, month)
46
287
  end
47
288
 
48
- config.freeze
289
+ beginning = CR::Calendar::EFFECTIVE_FROM
290
+ if range.first < beginning
291
+ raise InputError.new("implemented calendar system in use only since #{beginning}")
292
+ end
293
+
294
+ range
295
+ end
296
+
297
+ def supported_values(values)
298
+ " (supported: #{values.join(', ')})"
49
299
  end
50
300
  end
51
301
  end
@@ -0,0 +1,10 @@
1
+ require 'shellwords'
2
+
3
+ module Calrom
4
+ # Parses configuration file contents to an ARGV-like Array
5
+ class RcParser
6
+ def self.call(content)
7
+ Shellwords.split(content.gsub(/#.+?$/, ''))
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,34 @@
1
+ module Calrom
2
+ module Refinement
3
+ module CalendariumRomanum
4
+ # Refinement used when evaluating the Day/Celebration filter expressions.
5
+ # Allows the user (at least in simple cases) to write just `TRIDUUM` both
6
+ # as a season and as a rank.
7
+ module TriduumNameClashWorkaround
8
+ refine CR::Season do
9
+ alias_method :old_equal, :==
10
+
11
+ def ==(other)
12
+ if other.is_a?(CR::Rank) && self == CR::Seasons::TRIDUUM
13
+ return CR::Ranks::TRIDUUM == other
14
+ end
15
+
16
+ old_equal other
17
+ end
18
+ end
19
+
20
+ refine CR::Rank do
21
+ alias_method :old_equal, :==
22
+
23
+ def ==(other)
24
+ if other.is_a?(CR::Season) && self == CR::Ranks::TRIDUUM
25
+ return CR::Seasons::TRIDUUM == other
26
+ end
27
+
28
+ old_equal other
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ module Calrom
2
+ # Wraps arbitrary sanctorale files and allows handling and loading them exactly
3
+ # the same way as bundled sanctorale files.
4
+ #
5
+ # Erm, yes, according to calendarium-romanum documentation the parent class is actually
6
+ # not intended for use like this. But we take the risk of breakage by future
7
+ # calendarium-romanum releases ;)
8
+ class SanctoraleFile < CR::Data::SanctoraleFile
9
+ def initialize(path)
10
+ @siglum = nil
11
+ @path = path
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Calrom
2
- VERSION = '0.1.0'
2
+ VERSION = '0.4.0'
3
3
  end
data/lib/calrom.rb CHANGED
@@ -1,15 +1,34 @@
1
1
  require 'calendarium-romanum'
2
+ require 'calendarium-romanum/remote'
2
3
  require 'colorized_string'
3
4
 
5
+ # make useful calendarium-romanum constants available as top-level constants
6
+ include CalendariumRomanum::Constants
7
+
4
8
  module Calrom
5
9
  CR = CalendariumRomanum
6
10
  end
7
11
 
8
12
  require 'calrom/version'
13
+ require 'calrom/refinement/calendarium-romanum/triduum_nameclash_workaround'
9
14
  require 'calrom/cli'
10
15
  require 'calrom/option_parser'
16
+ require 'calrom/environment_reader'
11
17
  require 'calrom/config'
12
18
  require 'calrom/date_range'
19
+ require 'calrom/rc_parser'
20
+ require 'calrom/exceptions'
21
+ require 'calrom/sanctorale_file'
22
+ require 'calrom/filtering_calendar'
13
23
  require 'calrom/formatter/formatter'
14
24
  require 'calrom/formatter/list'
25
+ require 'calrom/formatter/overview'
26
+ require 'calrom/formatter/condensed'
27
+ require 'calrom/formatter/csv'
28
+ require 'calrom/formatter/json'
29
+ require 'calrom/formatter/easter'
30
+ require 'calrom/formatter/calendars'
31
+ require 'calrom/highlighter/no'
15
32
  require 'calrom/highlighter/list'
33
+ require 'calrom/highlighter/overview'
34
+ require 'calrom/highlighter/selective'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calrom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Pavlík
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-05 00:00:00.000000000 Z
11
+ date: 2022-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: calendarium-romanum
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.6.0
19
+ version: 0.9.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.6.0
26
+ version: 0.9.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: calendarium-romanum-remote
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: colorize
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -39,19 +53,19 @@ dependencies:
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0.8'
41
55
  - !ruby/object:Gem::Dependency
42
- name: bundler
56
+ name: pattern-match
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '1.13'
48
- type: :development
61
+ version: '1.0'
62
+ type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '1.13'
68
+ version: '1.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +130,7 @@ executables:
116
130
  extensions: []
117
131
  extra_rdoc_files: []
118
132
  files:
133
+ - ".github/workflows/ci.yml"
119
134
  - ".gitignore"
120
135
  - ".rspec"
121
136
  - ".travis.yml"
@@ -132,10 +147,25 @@ files:
132
147
  - lib/calrom/cli.rb
133
148
  - lib/calrom/config.rb
134
149
  - lib/calrom/date_range.rb
150
+ - lib/calrom/environment_reader.rb
151
+ - lib/calrom/exceptions.rb
152
+ - lib/calrom/filtering_calendar.rb
153
+ - lib/calrom/formatter/calendars.rb
154
+ - lib/calrom/formatter/condensed.rb
155
+ - lib/calrom/formatter/csv.rb
156
+ - lib/calrom/formatter/easter.rb
135
157
  - lib/calrom/formatter/formatter.rb
158
+ - lib/calrom/formatter/json.rb
136
159
  - lib/calrom/formatter/list.rb
160
+ - lib/calrom/formatter/overview.rb
137
161
  - lib/calrom/highlighter/list.rb
162
+ - lib/calrom/highlighter/no.rb
163
+ - lib/calrom/highlighter/overview.rb
164
+ - lib/calrom/highlighter/selective.rb
138
165
  - lib/calrom/option_parser.rb
166
+ - lib/calrom/rc_parser.rb
167
+ - lib/calrom/refinement/calendarium-romanum/triduum_nameclash_workaround.rb
168
+ - lib/calrom/sanctorale_file.rb
139
169
  - lib/calrom/version.rb
140
170
  homepage: https://github.com/calendarium-romanum/calrom
141
171
  licenses:
@@ -157,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
187
  version: '0'
158
188
  requirements: []
159
189
  rubyforge_project:
160
- rubygems_version: 2.5.1
190
+ rubygems_version: 2.7.6
161
191
  signing_key:
162
192
  specification_version: 4
163
193
  summary: Command line utility providing access to the Roman Catholic liturgical calendar