calrom 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d42310796615e6626842e77d06cf282159c50ce621910d7c44f61cfdc0de91ae
4
- data.tar.gz: eb40b6b35e68543447d12ebb1ca91be7212a07c92e392ce50cc994b48e9103c7
3
+ metadata.gz: c2e561032a6b91d68a87839856d8ce94b794187a539ac544fc907cfd2568add7
4
+ data.tar.gz: 8c9ab4bbdc83cc0c9884dbb4fb9f658c578e83956ce63da45b8698f59c55124f
5
5
  SHA512:
6
- metadata.gz: 66a58f4609c50cd65f581bf9cbc8e8c52c2d7330b475d0d45fd0cec9cf6c63d16259c2bbaf83bfde1726486bf8916edc399dd0b9e70287882e34b461fa0f010f
7
- data.tar.gz: 7dd18b19ba33a6caa6da2ebb08eedcd0ca12ebcb56f8500e75c35acd61509bfcfe53541608937c205677bd3ad36c951aff197ef02915f020721051a652b8a304
6
+ metadata.gz: e49e7f177d74b28c08ad6bd6ea25c4579857a6ca16ec68483b8fa4e1ad62807754f7010aad598ee156f728e94fd203042ae31f669f187b6ca52f3abcc0a2eec3
7
+ data.tar.gz: 2d416f813d7e688b1e855dcb28f27ba47002118c7de8d526ef8b86cd9571edd1bde6fdd9c0eb4c40a23bae75ab17fa66df43a7628b8f3d5ac5d29fd0be7b8bf7
@@ -0,0 +1,24 @@
1
+ name: CI
2
+ on: [push, pull_request]
3
+ jobs:
4
+ specs:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ matrix:
8
+ # oldest supported and newest MRI
9
+ # TODO: versions known to have worked back in Travis days; update needed
10
+ ruby-version:
11
+ - 2.5.0
12
+ - 3.0.0
13
+
14
+ steps:
15
+ - name: Check out code
16
+ uses: actions/checkout@v3
17
+ - name: Set up Ruby ${{ matrix.ruby-version }}
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby-version }}
21
+ - name: Install dependencies
22
+ run: bundle install --jobs=3
23
+ - name: Run tests
24
+ run: bundle exec rake
data/.travis.yml CHANGED
@@ -1,11 +1,11 @@
1
1
  language: ruby
2
2
 
3
- dist: trusty
3
+ dist: focal
4
4
 
5
5
  # oldest supported and newest MRI
6
6
  rvm:
7
7
  - 2.5.0
8
- - 2.7.1
8
+ - 3.0.0
9
9
 
10
10
  install: bundle install --jobs=3
11
11
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,57 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0] 2022-06-27
4
+
5
+ ### Added
6
+
7
+ - date range selection: cal-like option `-3` to select the current month together
8
+ with the preceding and following one (contributed by Fabio Soares @fabiosoaresv)
9
+ - if exactly one sanctorale data file is specified and its YAML front matter
10
+ references a parent calendar (key `extends`), the file is loaded with its complete
11
+ graph of parents
12
+ - option `--[no-]load-parents` to explicitly enable/disable loading of parent calendars
13
+ - basic support for remote calendars: the `--calendar=` option now accepts
14
+ also a calendar API URL like
15
+ `--calendar=http://calapi.inadiutorium.cz/api/v0/en/calendars/general-la`,
16
+ the referenced API is expected to be compatible with
17
+ [Liturgical Calendar API](http://calapi.inadiutorium.cz/) v0
18
+ - calendar listing (`--calendars`) marks default calendar as such
19
+ - calendar listing lists each calendar's parents
20
+ - option `--verbose`
21
+ - condensed view (`--format=condensed`), intended for use cases like printing current day
22
+ in a window manager toolbar and the like
23
+ - option `--to-sunday=` to configure which temporale solemnities should be transferred to Sunday
24
+ (e.g. `--to-sunday=epiphany`)
25
+ - option `--temporale-extension=` to activate temporale extension
26
+ (supported values are [temporale extension](https://github.com/igneus/calendarium-romanum/tree/master/lib/calendarium-romanum/temporale/extensions)
27
+ class names, e.g. `--temporale-extension=ChristEternalPriest`)
28
+ - any class in the `Calrom::Formatter` module is considered formatter and its
29
+ lowercased name can be used as value for the `--format=` option - custom formatters
30
+ can be added by defining new classes in the namespace
31
+ - options `--day-filter=` and `--celebration-filter=` for filtering days and celebrations
32
+ by a Ruby expression
33
+ - environment variable `CALROM_CURRENT_DATE` can be used to override current date
34
+ (intended mainly for testing)
35
+
36
+ ### Changed
37
+
38
+ - automated locale selection based on sanctorale data file relies solely on the `locale` key
39
+ of the file's YAML front matter (previously it relied on a file naming convention)
40
+ - option `--calendar=` expands tilde in path (if it isn't expanded by shell,
41
+ as is the case e.g. in configuration files)
42
+ - when displaying just a single day, highlighting of the current day is disabled by default
43
+ (i.e. if the day being displayed is current day, it won't be highlighted as such)
44
+ - list view (`--list`): rank is not printed for ferials and Sundays
45
+ - overview view always arranges the displayed months in multiple columns, just like `cal`
46
+ (previously date ranges spanning less than three months were printed in a single column)
47
+ - date range specification: support for dates with year higher than 9999 (e.g. `10000-01-01`)
48
+
49
+ ### Fixed
50
+
51
+ - crash on invalid value of `--locale`
52
+ - list view: when printing a date range between the same months of different years
53
+ (e.g. 2000-01-xx .. 2001-01-xx), year was not printed in month headings
54
+
3
55
  ## [0.3.0] 2020-06-21
4
56
 
5
57
  ### Added
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # calrom
2
2
 
3
- [![Build Status](https://travis-ci.org/calendarium-romanum/calrom.svg?branch=master)](https://travis-ci.org/calendarium-romanum/calrom)
3
+ ![Build Status](https://github.com/calendarium-romanum/calrom/actions/workflows/ci.yml/badge.svg)
4
4
  [![Gem Version](https://badge.fury.io/rb/calrom.svg)](https://badge.fury.io/rb/calrom)
5
5
 
6
6
  Command line utility providing access to the Roman Catholic
@@ -46,6 +46,35 @@ Print liturgical calendar for the current month (default):
46
46
 
47
47
  `$ calrom 2028-01-15 2028-03-07`
48
48
 
49
+ ### Day and celebration filtering
50
+
51
+ In addition to specifying date range, filtering is a way to further refine
52
+ the selection of data to be displayed. Options `--day-filter=` and `--celebration-filter=`
53
+ both accept a snippet of Ruby code, which is then `eval`ed in context of each
54
+ `CalendariumRomanum::Day` / `CalendariumRomanum::Celebration` within the selected date range
55
+ and only days/celebrations for which the expression evaluates truthy are displayed.
56
+
57
+ Display only Saturdays:
58
+
59
+ `$ calrom --day-filter='date.saturday?'`
60
+
61
+ Display all Mondays with a celebration of a rank higher than memorial:
62
+
63
+ `$ calrom --day-filter='date.monday?' --day-filter='celebrations[0].rank > MEMORIAL_GENERAL'`
64
+
65
+ (As you can see, `calendarium-romanum` constants like ranks or seasons are available
66
+ as top-level constants. Noone likes extensive writing in the terminal.)
67
+
68
+ Display only ferials:
69
+
70
+ `$ calrom --celebration-filter='ferial?'`
71
+
72
+ Display only celebrations in green:
73
+
74
+ `$ calrom --celebration-filter='colour == GREEN'`
75
+
76
+ The options can be combined and used repeatedly to narrow the selection down as needed.
77
+
49
78
  ### Selecting calendar
50
79
 
51
80
  There are a few calendars bundled in calrom (actually in the calendarium-romanum gem)
@@ -69,12 +98,28 @@ of the local church:
69
98
 
70
99
  `$ calrom --calendar=universal-la --calendar=path/to/our_local_celebrations.txt`
71
100
 
101
+ Please note that specifying more than one calendar disables automatic loading of
102
+ parent calendars. If any of the listed calendars extends a parent calendar,
103
+ the parent either has to be explicitly listed using the `--calendar` option in order to be loaded,
104
+ or automatic parent loading has to be explicitly enabled using the `--load-parents` option.
105
+
106
+ Limited support for remote calendars is provided. Calendar URL from the
107
+ [Liturgical Calendar API](http://calapi.inadiutorium.cz/) or a compatible calendar API
108
+ is accepted as a value of `--calendar=`:
109
+
110
+ `$ calrom --calendar=http://calapi.inadiutorium.cz/api/v0/en/calendars/general-la`
111
+
72
112
  ### Data presentation settings
73
113
 
74
114
  Print detailed listing:
75
115
 
76
116
  `$ calrom -l`
77
117
 
118
+ Print current day in a condensed format (intended mainly for use cases like
119
+ window manager toolbars):
120
+
121
+ `$ calrom --format=condensed --today`
122
+
78
123
  Disable colours:
79
124
 
80
125
  `$ calrom --no-color`
@@ -94,13 +139,11 @@ They are processed in this order and both are used if available.
94
139
  Their syntax is that of shell options and arguments (with the sole exception that newline
95
140
  is not considered end of shell input, but generic whitespace), supported are all options and arguments
96
141
  accepted by the command.
97
- It usually makes sense to use configuration files only for the most fundamental settings
98
- you will never change, like selecting calendar (if you know you will always check this single one)
99
- or disabling colours (if you hate colourful output).
100
142
 
101
143
  If a custom configuration file location is specified on the command line,
102
144
  `$ calrom --config=path/to/my/custom/config`, the standard system-wide and user-specific configuration
103
- files are *not* loaded.
145
+ files are *not* loaded. Empty config path `$ calrom --config=` makes calrom ignore all configuration
146
+ files and use the built-in default configuration.
104
147
 
105
148
  Example configuration file, loading the proper calendar of the archdiocese of Prague
106
149
  and disabling colours:
@@ -108,15 +151,27 @@ and disabling colours:
108
151
  ```bash
109
152
  # shell-like comments can be used in configuration files
110
153
 
111
- --calendar=czech-cs # celebrations common for the whole Czech Republic
112
- --calendar=czech-cechy-cs # Bohemia
113
- --calendar=czech-praha-cs # archdiocese of Prague
114
- --calendar=/home/igneus/calendar_data/local_church.txt # path to a custom calendar file with proper celebrations of the parish where I live (titular feast of the church, dedication)
154
+ --calendar=czech-praha-cs # calendar of the archdiocese of Prague
155
+ --calendar=~/calendar_data/local_church.txt # path to a custom calendar file with proper celebrations of the parish where I live (titular feast of the church, dedication)
156
+
157
+ --load-parents # load also parent calendars specified by the calendar file(s)
158
+ # (default if just one calendar file is specified, but we specified two)
115
159
 
116
160
  --no-color # disable colours
117
161
  ```
118
162
 
119
- (Configuration file format is inspired by [.rspec][dotrspec].)
163
+ (Configuration file format is inspired by [.rspec][dotrspec], [.yardopts][dotyardopts]
164
+ and others.)
165
+
166
+ Most options work in such a way that if several conflicting options are provided,
167
+ the last one wins. You can thus e.g. set your favourite display format (e.g. `--list`)
168
+ or date range (e.g. `-3`) in the configuration file and override it, if necessary,
169
+ by providing some other option from the same group on the command line.
170
+ An exception from this rule is the `--calendar=` option, repeated occurrences of which
171
+ do not cancel each other, but are all composed together in the given order to build a calendar
172
+ by layering.
173
+ Also repeated occurrences of the `--day-filter=` and `--celebration-filter=` options
174
+ don't cancel each other, but all specified filtering expressions are applied.
120
175
 
121
176
  ## Running tests
122
177
 
@@ -131,17 +186,16 @@ Clone the repository, `$ bundle install` to install dependencies, then:
131
186
  ## Project roadmap
132
187
 
133
188
  * [x] detailed listing of a day/month/year/range of dates
134
- * [ ] month/year overview - options and output mostly mimicking
189
+ * [x] month/year overview - options and output mostly mimicking
135
190
  the BSD Unix [`cal`][cal] utility,
136
191
  but with liturgical colours and celebration ranks
137
- * [ ] condensed format (but with detailed information) suitable for awesome/i3 toolbars etc.
192
+ * [x] condensed format (but with detailed information) suitable for awesome/i3 toolbars etc.
138
193
  * [x] machine-readable detailed listing
139
194
  * [ ] year summary: lectionary cycles, movable feasts
140
195
  * [x] configuration file to set default options
141
196
  * [x] specify calendar data path (with support for layering several calendars)
142
197
  * [ ] option to auto-select one of optional celebrations - with multiple supported strategies (prefer ferial, take first non-ferial, configured whitelist, blacklist)
143
198
  * [ ] integrate online data sources
144
- * [ ] interactive browsing
145
199
 
146
200
  ## Backward compatibility
147
201
 
@@ -168,7 +222,7 @@ command line interface
168
222
 
169
223
  * [(BSD version of) `cal`][cal] should be mimicked where reasonable
170
224
  * the [Command-Line Options][taoup] chapter from E. S. Raymond's
171
- "The Art of Unix Programming" should be consulted in the rest
225
+ *The Art of Unix Programming* should be consulted in the rest
172
226
  of cases
173
227
 
174
228
  ## License
@@ -182,3 +236,4 @@ GNU/GPL 3.0 or later
182
236
  [cal]: https://www.freebsd.org/cgi/man.cgi?query=cal
183
237
  [taoup]: http://www.catb.org/esr/writings/taoup/html/ch10s05.html
184
238
  [dotrspec]: https://relishapp.com/rspec/rspec-core/v/2-0/docs/configuration/read-command-line-configuration-options-from-files
239
+ [dotyardopts]: https://rubydoc.info/gems/yard/file/docs/GettingStarted.md#yardopts-options-file
data/calrom.gemspec CHANGED
@@ -20,7 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ['lib']
22
22
 
23
- spec.add_dependency 'calendarium-romanum', '~> 0.6.0'
23
+ spec.add_dependency 'calendarium-romanum', '~> 0.9.0'
24
+ spec.add_dependency 'calendarium-romanum-remote', '~> 0.3.0'
24
25
  spec.add_dependency 'colorize', '~> 0.8'
25
26
  spec.add_dependency 'pattern-match', '~> 1.0'
26
27
 
data/lib/calrom/cli.rb CHANGED
@@ -4,20 +4,42 @@ module Calrom
4
4
  begin
5
5
  config_files = OptionParser.call(argv).configs
6
6
 
7
+ config = EnvironmentReader.call
7
8
  config = OptionParser.call(
8
9
  rc_options(config_files.empty? ? nil : config_files) +
9
- argv
10
+ argv,
11
+ config
10
12
  )
11
13
 
12
14
  calendar = config.calendar
13
- rescue ::OptionParser::ParseError, InputError => e
15
+ rescue OptionParser::Error, InputError => e
14
16
  STDERR.puts e.message
15
17
  exit 1
16
18
  end
17
19
 
18
- I18n.locale = config.locale
20
+ begin
21
+ I18n.locale = config.locale
22
+ rescue I18n::InvalidLocale
23
+ locales_help = I18n.available_locales.join(', ')
24
+ STDERR.puts "Locale '#{config.locale}' unsupported (available locales: #{locales_help})"
25
+ exit 1
26
+ end
27
+
28
+ unless config.verbose
29
+ HTTPI.log = false
30
+ end
19
31
 
20
- config.formatter.call calendar, config.date_range
32
+ begin
33
+ config.build_formatter.call calendar, config.date_range
34
+ rescue CR::Remote::UnexpectedResponseError => e
35
+ STDERR.puts "Remote calendar query failed: #{e.message}"
36
+ exit 1
37
+ rescue InputError => e
38
+ STDERR.puts e.message
39
+ exit 1
40
+ rescue Errno::EPIPE
41
+ # broken pipe - simply stop execution, exit successfully
42
+ end
21
43
  end
22
44
 
23
45
  private
@@ -42,7 +64,7 @@ module Calrom
42
64
 
43
65
  begin
44
66
  OptionParser.call(options)
45
- rescue ::OptionParser::ParseError => e
67
+ rescue OptionParser::Error => e
46
68
  raise InputError.new("Error loading '#{f}': #{e.message}")
47
69
  end
48
70
 
data/lib/calrom/config.rb CHANGED
@@ -8,12 +8,55 @@ module Calrom
8
8
  self.date_range = Month.new(today.year, today.month)
9
9
  self.sanctorale = []
10
10
  self.configs = []
11
+ self.verbose = false
12
+ self.highlight = Set.new(%i(colour rank today))
13
+ self.transfer_to_sunday = []
14
+ self.temporale_extensions = []
15
+ self.filter_days = []
16
+ self.filter_celebrations = []
11
17
  end
12
18
 
13
- attr_accessor :today, :date_range, :formatter, :colours, :sanctorale, :locale, :configs
19
+ ATTRIBUTES = [
20
+ :today,
21
+ :date_range,
22
+ :formatter,
23
+ :colours,
24
+ :sanctorale,
25
+ :transfer_to_sunday,
26
+ :temporale_extensions,
27
+ :locale,
28
+ :configs,
29
+ :load_parents,
30
+ :highlight,
31
+ :verbose,
32
+ :filter_days,
33
+ :filter_celebrations,
34
+ ]
35
+
36
+ attr_accessor *ATTRIBUTES
37
+
38
+ def ==(b)
39
+ self.class == b.class &&
40
+ ATTRIBUTES.all? {|prop| public_send(prop) == b.public_send(prop) }
41
+ end
14
42
 
15
43
  def calendar
16
- CR::PerpetualCalendar.new(sanctorale: build_sanctorale)
44
+ calendar =
45
+ if is_remote_calendar?
46
+ if @sanctorale.size > 1
47
+ raise InputError.new '--calendar option provided multiple times, but at least one of the calendars is remote. Remote calendars cannot be layered.'
48
+ end
49
+
50
+ CR::Remote::Calendar.new date_range.first.year, @sanctorale.last
51
+ else
52
+ CR::PerpetualCalendar.new(sanctorale: build_sanctorale, temporale_options: temporale_options, vespers: true)
53
+ end
54
+
55
+ FilteringCalendar.new(
56
+ calendar,
57
+ filter_days,
58
+ filter_celebrations,
59
+ )
17
60
  end
18
61
 
19
62
  def build_sanctorale
@@ -22,56 +65,86 @@ module Calrom
22
65
  end
23
66
 
24
67
  data = @sanctorale.collect do |s|
68
+ expanded = File.expand_path s
69
+
25
70
  if s == '-'
26
71
  CR::SanctoraleLoader.new.load_from_string STDIN.read
27
- elsif File.file? s
28
- CR::SanctoraleLoader.new.load_from_file s
29
- elsif CR::Data[s]
30
- CR::Data[s].load
31
72
  else
32
- raise InputError.new "\"#{s}\" is neither a file, nor a valid identifier of a bundled calendar. " +
33
- "Valid identifiers are: " +
34
- CR::Data.each.collect(&:siglum).inspect
73
+ data_file =
74
+ if File.file? expanded
75
+ SanctoraleFile.new expanded
76
+ elsif CR::Data[s]
77
+ CR::Data[s]
78
+ else
79
+ raise InputError.new "\"#{s}\" is neither a file, nor a valid identifier of a bundled calendar. " +
80
+ "Valid identifiers are: " +
81
+ CR::Data.each.collect(&:siglum).inspect
82
+ end
83
+
84
+ if load_parents?
85
+ data_file.load_with_parents
86
+ else
87
+ data_file.load
88
+ end
35
89
  end
36
90
  end
37
91
 
38
92
  CR::SanctoraleFactory.create_layered(*data)
39
93
  end
40
94
 
95
+ def temporale_options
96
+ {transfer_to_sunday: transfer_to_sunday, extensions: temporale_extensions}
97
+ end
98
+
41
99
  def locale
42
- @locale || locale_in_file_name || DEFAULT_LOCALE
100
+ @locale || locale_in_file_metadata || DEFAULT_LOCALE
43
101
  end
44
102
 
45
- def formatter
46
- if @formatter == :list || (@formatter.nil? && date_range.is_a?(Day))
47
- Formatter::List.new highlighter(Highlighter::List), today
48
- elsif @formatter == :easter
49
- Formatter::Easter.new
50
- elsif @formatter == :calendars
51
- Formatter::Calendars.new highlighter(Highlighter::Overview), today
52
- elsif @formatter == :csv
53
- Formatter::Csv.new
54
- elsif @formatter == :json
55
- Formatter::Json.new
56
- else
57
- Formatter::Overview.new highlighter(Highlighter::Overview), today
103
+ def build_formatter
104
+ highlighter = Highlighter::List
105
+ klass = @formatter && Formatter.const_get(@formatter.capitalize)
106
+
107
+ if @formatter.nil?
108
+ klass = date_range.is_a?(Day) ? Formatter::List : Formatter::Overview
109
+ end
110
+
111
+ if [Formatter::Calendars, Formatter::Overview].include? klass
112
+ highlighter = Highlighter::Overview
58
113
  end
114
+
115
+ klass.new build_highlighter(highlighter), today
59
116
  end
60
117
 
61
- def highlighter(colourful)
118
+ def build_highlighter(colourful)
62
119
  if (self.colours == false || (self.colours.nil? && !STDOUT.isatty))
63
120
  return Highlighter::No.new
64
121
  end
65
122
 
66
- colourful.new
123
+ Highlighter::Selective.new highlight, colourful.new
124
+ end
125
+
126
+ # Should calendars be loaded including parent files they reference?
127
+ def load_parents?
128
+ load_parents == true ||
129
+ (load_parents.nil? && @sanctorale.size == 1)
130
+ end
131
+
132
+ def highlight
133
+ if date_range.is_a? Day
134
+ @highlight - [:today]
135
+ else
136
+ @highlight
137
+ end
67
138
  end
68
139
 
69
140
  private
70
141
 
71
- def locale_in_file_name
72
- locale = (sanctorale.last || DEFAULT_DATA.siglum).split('-').last&.to_sym
142
+ def locale_in_file_metadata
143
+ is_remote_calendar? ? nil : build_sanctorale.metadata['locale']&.to_sym
144
+ end
73
145
 
74
- I18n.available_locales.include?(locale) ? locale : nil
146
+ def is_remote_calendar?
147
+ !!@sanctorale.find {|s| s =~ /^https?:\/\// }
75
148
  end
76
149
  end
77
150
  end
@@ -13,7 +13,6 @@ module Calrom
13
13
  .each_with_index do |m,i|
14
14
  if i == 0 && first.day > 1
15
15
  # first month, incomplete
16
- end_of_month = first.next_month - first.day + 1
17
16
  yield self.class.new(first, m.last)
18
17
  elsif m.first.year == last.year && m.first.month == last.month && last != m.last
19
18
  # last month, incomplete
@@ -23,6 +22,11 @@ module Calrom
23
22
  end
24
23
  end
25
24
  end
25
+
26
+ def spans_multiple_months?
27
+ first.month != last.month ||
28
+ first.year != last.year
29
+ end
26
30
  end
27
31
 
28
32
  class Year < DateRange
@@ -41,11 +45,30 @@ module Calrom
41
45
  end
42
46
  end
43
47
 
48
+ class ThreeMonths < DateRange
49
+ def initialize(year, month)
50
+ super first_day_of_last_month(year, month), last_day_of_next_month(year, month)
51
+ end
52
+
53
+ private
54
+
55
+ def first_day_of_last_month(year, month)
56
+ Date.new(year, month, 1).prev_month
57
+ end
58
+
59
+ def last_day_of_next_month(year, month)
60
+ n = Date.new(year, month).next_month
61
+
62
+ Date.new(n.year, n.month, -1)
63
+ end
64
+ end
65
+
44
66
  class Month < DateRange
45
67
  def initialize(year, month)
46
68
  @year = year
47
69
  @month = month
48
- super Date.new(year, month, 1), next_month_beginning - 1
70
+
71
+ super Date.new(year, month, 1), Date.new(year, month, -1)
49
72
  end
50
73
 
51
74
  def to_s
@@ -59,7 +82,7 @@ module Calrom
59
82
  end
60
83
 
61
84
  def succ
62
- n = next_month_beginning
85
+ n = Date.new(@year, @month, 1).next_month
63
86
  self.class.new(n.year, n.month)
64
87
  end
65
88
 
@@ -76,16 +99,6 @@ module Calrom
76
99
  protected
77
100
 
78
101
  attr_reader :year, :month
79
-
80
- private
81
-
82
- def next_month_beginning
83
- if @month == 12
84
- Date.new(@year + 1, 1, 1)
85
- else
86
- Date.new(@year, @month + 1, 1)
87
- end
88
- end
89
102
  end
90
103
 
91
104
  class Day < DateRange
@@ -0,0 +1,36 @@
1
+ module Calrom
2
+ # Reads configuration from environment variables
3
+ class EnvironmentReader
4
+ def self.call(config = nil)
5
+ new(config || Config.new).call
6
+ end
7
+
8
+ def initialize(config)
9
+ @config = config
10
+ end
11
+
12
+ def call
13
+ today
14
+
15
+ @config
16
+ end
17
+
18
+ private
19
+
20
+ def today
21
+ with_envvar 'CALROM_CURRENT_DATE' do |value, name|
22
+ begin
23
+ @config.today = Date.parse value
24
+ rescue ArgumentError
25
+ raise InputError.new "value of environment variable #{name} is not a valid date"
26
+ end
27
+ end
28
+ end
29
+
30
+ def with_envvar(name)
31
+ value = ENV[name]
32
+
33
+ yield value, name if value
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,71 @@
1
+ require 'delegate'
2
+
3
+ module Calrom
4
+ # decorates /(Perpetual)?Calendar/, returns data filtered
5
+ class FilteringCalendar < SimpleDelegator
6
+ using Refinement::CalendariumRomanum::TriduumNameClashWorkaround
7
+
8
+ def initialize(calendar, days_filter_expressions=[], celebrations_filter_expressions=[])
9
+ super(calendar)
10
+
11
+ @days_filter = proc do |day|
12
+ days_filter_expressions.all? do |expr|
13
+ eval_filtering_expression(day, expr)
14
+ end
15
+ end
16
+
17
+ @celebrations_filter = proc do |celebration|
18
+ celebrations_filter_expressions.all? do |expr|
19
+ eval_filtering_expression(celebration, expr)
20
+ end
21
+ end
22
+ end
23
+
24
+ def [](arg)
25
+ raw = super(arg)
26
+
27
+ unless @days_filter.(raw)
28
+ return FilteredDay.build_skipped raw
29
+ end
30
+
31
+ FilteredDay.new raw, raw.celebrations.select(&@celebrations_filter)
32
+ end
33
+
34
+ def each_day_in_range(range, include_skipped: false)
35
+ return to_enum(__method__, range, include_skipped: include_skipped) unless block_given?
36
+
37
+ range.each do |date|
38
+ day = self[date]
39
+ yield day if (include_skipped || !day.skipped?)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def eval_filtering_expression(object, expression)
46
+ object.instance_eval expression
47
+ rescue StandardError, SyntaxError => exception
48
+ raise InputError.new "Filter expression '#{expression}' raised #{exception.class}: #{exception.message}"
49
+ end
50
+
51
+ class FilteredDay < SimpleDelegator
52
+ def initialize(day, filtered_celebrations)
53
+ super(day)
54
+
55
+ @filtered_celebrations = filtered_celebrations
56
+ end
57
+
58
+ def self.build_skipped(day)
59
+ new day, []
60
+ end
61
+
62
+ def celebrations
63
+ @filtered_celebrations
64
+ end
65
+
66
+ def skipped?
67
+ celebrations.empty?
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,3 @@
1
- require 'yaml'
2
-
3
1
  module Calrom
4
2
  module Formatter
5
3
  # Prints list of available bundled calendars
@@ -7,16 +5,25 @@ module Calrom
7
5
  def call(calendar, date_range)
8
6
  last_locale = nil
9
7
  CR::Data.each do |d|
10
- meta = load_front_matter d
8
+ sanctorale = d.load_with_parents
9
+ meta = sanctorale.metadata
11
10
  puts if last_locale && last_locale != meta['locale']
12
- puts "%-20s: %s [%s]" % [d.siglum, meta['title'], meta['locale']]
11
+ default = d == Config::DEFAULT_DATA ? ' [default]' : ''
12
+ puts "%-20s: %s [%s]%s" % [d.siglum, meta['title'], meta['locale'], default]
13
+
14
+ next unless meta['components']
15
+
16
+ parents =
17
+ meta['components']
18
+ .collect {|c| c['extends'] }
19
+ .compact
20
+ .map {|e| e.is_a?(Array) ? e : [e] } # 'extends' is String or Array
21
+ .flatten
22
+ .map {|p| p.sub(/\.\w{3,4}$/, '') } # file name to "siglum"
23
+ parents.each {|p| puts " < #{p}" }
13
24
  last_locale = meta['locale']
14
25
  end
15
26
  end
16
-
17
- def load_front_matter(data_file)
18
- YAML.load File.read data_file.path
19
- end
20
27
  end
21
28
  end
22
29
  end
@@ -0,0 +1,51 @@
1
+ module Calrom
2
+ module Formatter
3
+ class Condensed < Formatter
4
+ def call(calendar, date_range)
5
+ calendar.each_day_in_range(date_range) {|d| day d }
6
+ end
7
+
8
+ private
9
+
10
+ def day(liturgical_day)
11
+ c = liturgical_day.celebrations.first
12
+
13
+ colour = highlighter.colour(c.colour.name[0].upcase, c.colour)
14
+ rank = highlighter.rank(rank(c.rank), c.rank)
15
+ title = short_title c
16
+ more = additional_celebrations(liturgical_day) + vespers(liturgical_day)
17
+
18
+ puts "#{title} #{rank}#{colour}#{more}"
19
+ end
20
+
21
+ def rank(rank)
22
+ if rank.solemnity?
23
+ '*'
24
+ elsif rank.feast?
25
+ '+'
26
+ else
27
+ ''
28
+ end
29
+ end
30
+
31
+ def short_title(celebration)
32
+ if celebration.cycle == :sanctorale
33
+ # naive attempt to strip feast titles
34
+ celebration.title.sub /,[^,]*$/, ''
35
+ else
36
+ celebration.title
37
+ end
38
+ end
39
+
40
+ def additional_celebrations(day)
41
+ size = day.celebrations.size
42
+
43
+ size > 1 ? " +#{size-1}" : ''
44
+ end
45
+
46
+ def vespers(day)
47
+ day.vespers_from_following? ? '>' : ''
48
+ end
49
+ end
50
+ end
51
+ end
@@ -2,13 +2,12 @@ require 'csv'
2
2
 
3
3
  module Calrom
4
4
  module Formatter
5
- class Csv
5
+ class Csv < Formatter
6
6
  def call(calendar, date_range)
7
7
  CSV do |out|
8
8
  out << %w(date title symbol rank rank_num colour season)
9
9
 
10
- date_range.each do |date|
11
- day = calendar[date]
10
+ calendar.each_day_in_range(date_range) do |day|
12
11
  day.celebrations.each do |c|
13
12
  out << [
14
13
  day.date,
@@ -1,7 +1,7 @@
1
1
  module Calrom
2
2
  module Formatter
3
3
  # Prints (only) date of Easter for the specified year.
4
- class Easter
4
+ class Easter < Formatter
5
5
  def call(calendar, date_range)
6
6
  unless date_range.is_a?(Year) || date_range.is_a?(Month)
7
7
  raise 'unexpected date range, expected a year'
@@ -1,15 +1,26 @@
1
1
  module Calrom
2
2
  module Formatter
3
3
  class Formatter
4
- def initialize(highlighter, today)
4
+ def initialize(highlighter, today, io = STDOUT)
5
5
  @highlighter = highlighter
6
6
  @today = today
7
+ @io = io
7
8
  end
8
9
 
9
10
  attr_reader :highlighter, :today
10
11
 
11
12
  def call(calendar, date_range)
12
13
  end
14
+
15
+ private
16
+
17
+ def puts(s = '')
18
+ @io.puts s
19
+ end
20
+
21
+ def print(s)
22
+ @io.print s
23
+ end
13
24
  end
14
25
  end
15
26
  end
@@ -3,14 +3,14 @@ require 'json'
3
3
  module Calrom
4
4
  module Formatter
5
5
  # JSON format mimicking Church Calendar API v0 (https://github.com/igneus/church-calendar-api)
6
- class Json
6
+ class Json < Formatter
7
7
  def call(calendar, date_range)
8
8
  # We build the outer JSON Array manually in order to be able to print
9
9
  # vast amounts of calendar data without risking RAM exhaustion.
10
10
  print "["
11
11
 
12
- date_range.each_with_index do |date, i|
13
- day = calendar[date]
12
+ calendar.each_day_in_range(date_range).each_with_index do |day,i|
13
+ date = day.date
14
14
  hash = {
15
15
  date: date,
16
16
  season: day.season.symbol,
@@ -2,22 +2,20 @@ module Calrom
2
2
  module Formatter
3
3
  class List < Formatter
4
4
  def call(calendar, date_range)
5
- print_months = date_range.first.month != date_range.last.month
5
+ print_months = date_range.spans_multiple_months?
6
6
 
7
7
  puts date_range.to_s
8
8
  puts
9
9
 
10
10
  current_month = nil
11
11
 
12
- date_range.each do |date|
13
- liturgical_day = calendar[date]
14
-
12
+ calendar.each_day_in_range(date_range) do |liturgical_day|
15
13
  if print_months && liturgical_day.date.month != current_month
16
- current_month = liturgical_day.date.month
17
-
18
- puts
14
+ puts unless current_month == nil
19
15
  puts liturgical_day.date.strftime('%B') #current_month
20
16
  puts
17
+
18
+ current_month = liturgical_day.date.month
21
19
  end
22
20
 
23
21
  day liturgical_day
@@ -42,7 +40,7 @@ module Calrom
42
40
  s += highlighter.colour(colour.name[0].upcase, colour) +
43
41
  ' ' +
44
42
  highlighter.rank(celebration.title, rank) +
45
- (rank.short_desc.nil? ? '' : ', ' + rank.short_desc)
43
+ ((rank.short_desc.nil? || rank.sunday? || rank.ferial?) ? '' : ', ' + rank.short_desc)
46
44
 
47
45
  if liturgical_day.date == today
48
46
  s = highlighter.today s
@@ -4,10 +4,10 @@ require 'stringio'
4
4
  module Calrom
5
5
  module Formatter
6
6
  class Overview < Formatter
7
- def call(calendar, date_range, io = STDOUT)
8
- colnum = (date_range.is_a?(Year) || date_range.each_month.to_a.size > 3) ? 3 : 1 # TODO: expose configuration
7
+ def call(calendar, date_range)
8
+ colnum = 3 # TODO: expose configuration
9
9
  if date_range.is_a? Year
10
- io.puts center_on(weekdays.size * colnum + 2 * (colnum - 1), date_range.to_s)
10
+ puts center_on(weekdays.size * colnum + 2 * (colnum - 1), date_range.to_s)
11
11
  end
12
12
 
13
13
  date_range.each_month.each_slice(colnum) do |months|
@@ -16,7 +16,7 @@ module Calrom
16
16
  print_month io, calendar, month, date_range.is_a?(Year)
17
17
  end
18
18
  end
19
- print_columns columns, io
19
+ print_columns columns, @io
20
20
  end
21
21
  end
22
22
 
@@ -29,14 +29,19 @@ module Calrom
29
29
  io.puts weekdays
30
30
 
31
31
  io.print ' ' * month.first.wday
32
- month.each do |date|
33
- liturgical_day = calendar[date]
32
+ calendar.each_day_in_range(month, include_skipped: true) do |liturgical_day|
33
+ date = liturgical_day.date
34
34
 
35
- celebration = liturgical_day.celebrations.first
35
+ if liturgical_day.skipped?
36
+ datestr = ' '
37
+ else
38
+ celebration = liturgical_day.celebrations.first
39
+
40
+ datestr = date.day.to_s.rjust(2)
41
+ datestr = highlighter.colour(datestr, celebration.colour)
42
+ datestr = highlighter.rank(datestr, celebration.rank)
43
+ end
36
44
 
37
- datestr = date.day.to_s.rjust(2)
38
- datestr = highlighter.colour(datestr, celebration.colour)
39
- datestr = highlighter.rank(datestr, celebration.rank)
40
45
  if date == today
41
46
  datestr = highlighter.today datestr
42
47
  end
@@ -0,0 +1,34 @@
1
+ module Calrom
2
+ module Highlighter
3
+ class Selective
4
+ def initialize(selected, highlighter)
5
+ @selected = selected
6
+ @highlighter = highlighter
7
+ end
8
+
9
+ def colour(text, colour)
10
+ if @selected.include? __method__
11
+ @highlighter.public_send __method__, text, colour
12
+ else
13
+ text
14
+ end
15
+ end
16
+
17
+ def rank(text, rank)
18
+ if @selected.include? __method__
19
+ @highlighter.public_send __method__, text, rank
20
+ else
21
+ text
22
+ end
23
+ end
24
+
25
+ def today(text)
26
+ if @selected.include? __method__
27
+ @highlighter.public_send __method__, text
28
+ else
29
+ text
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -6,20 +6,28 @@ module Calrom
6
6
  class OptionParser
7
7
  using PatternMatch
8
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
+
9
16
  class CustomizedOptionParser < ::OptionParser
10
17
  def separator(string)
11
18
  super "\n" + string
12
19
  end
13
20
  end
14
21
 
15
- def self.call(argv)
16
- self.new.call(argv)
22
+ def self.call(*args)
23
+ self.new.call(*args)
17
24
  end
18
25
 
19
- def call(argv)
20
- config = Config.new
26
+ def call(argv, config = nil)
27
+ config ||= Config.new
21
28
 
22
29
  today = config.today
30
+
23
31
  year = today.year
24
32
  month = today.month
25
33
  day = nil
@@ -42,6 +50,7 @@ module Calrom
42
50
  calrom 2000 - whole year 2000
43
51
  calrom -y 2000 - also whole year 2000
44
52
  calrom -y - whole current year
53
+ calrom -3 - display the previous, current and next month surrounding today
45
54
 
46
55
  Specifying date range (not cal-compatible):
47
56
 
@@ -70,23 +79,28 @@ module Calrom
70
79
  end
71
80
  end
72
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
+
73
87
  # cal
74
88
  opts.on('-y', '--year', 'display specified (or current) year') do |value|
75
89
  range_type = :year
76
90
  end
77
91
 
78
92
  opts.on('--yesterday', 'display previous day') do |value|
79
- day = Date.today - 1
93
+ day = today - 1
80
94
  range_type = :day
81
95
  end
82
96
 
83
97
  opts.on('--today', 'display current day') do |value|
84
- day = Date.today
98
+ day = today
85
99
  range_type = :day
86
100
  end
87
101
 
88
102
  opts.on('--tomorrow', 'display following day') do |value|
89
- day = Date.today + 1
103
+ day = today + 1
90
104
  range_type = :day
91
105
  end
92
106
 
@@ -96,8 +110,21 @@ module Calrom
96
110
  config.sanctorale << value
97
111
  end
98
112
 
99
- locales_help = I18n.available_locales.join(', ')
100
- opts.on('--locale=LOCALE', "override language in which temporale celebration titles are rendered (supported: #{locales_help})") do |value|
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|
101
128
  config.locale = value.to_sym
102
129
  end
103
130
 
@@ -107,12 +134,23 @@ module Calrom
107
134
  config.formatter = :list
108
135
  end
109
136
 
110
- supported_formats = %i(overview list csv json)
137
+ supported_formats =
138
+ Calrom::Formatter.constants
139
+ .collect(&:downcase)
140
+ .delete_if {|i| i == :formatter }
111
141
  formats_help = supported_formats.join(', ')
112
142
  opts.on('--format=FORMAT', supported_formats, "specify output format (supported: #{formats_help})") do |value|
113
143
  config.formatter = value
114
144
  end
115
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
+
116
154
  # cal
117
155
  opts.on('-e', '--easter', 'display date of Easter (only)') do
118
156
  config.formatter = :easter
@@ -126,6 +164,10 @@ module Calrom
126
164
  config.colours = value
127
165
  end
128
166
 
167
+ opts.on('-v', '--verbose', 'enable verbose output') do
168
+ config.verbose = true
169
+ end
170
+
129
171
  opts.separator 'Debugging options'
130
172
 
131
173
  # cal
@@ -142,6 +184,7 @@ module Calrom
142
184
 
143
185
  opts.on('-V', '--version', 'display calrom version') do
144
186
  puts 'calrom v' + Calrom::VERSION
187
+ puts 'using calendarium-romanum v' + CR::VERSION
145
188
  exit
146
189
  end
147
190
 
@@ -153,9 +196,13 @@ module Calrom
153
196
  end
154
197
  end
155
198
 
156
- 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
157
204
 
158
- iso_date_regexp = /^(\d{4}-\d{2}-\d{2})$/
205
+ iso_date_regexp = /^(\d{4,}-\d{2}-\d{2})$/
159
206
  match(arguments) do
160
207
  with(_[iso_date_regexp.(date)]) do
161
208
  range_type = :day
@@ -233,6 +280,8 @@ module Calrom
233
280
  Day.new(day)
234
281
  when :free
235
282
  DateRange.new(day, another_day)
283
+ when :three_months
284
+ ThreeMonths.new(year, month)
236
285
  else
237
286
  Month.new(year, month)
238
287
  end
@@ -244,5 +293,9 @@ module Calrom
244
293
 
245
294
  range
246
295
  end
296
+
297
+ def supported_values(values)
298
+ " (supported: #{values.join(', ')})"
299
+ end
247
300
  end
248
301
  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.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
data/lib/calrom.rb CHANGED
@@ -1,20 +1,29 @@
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'
13
19
  require 'calrom/rc_parser'
14
20
  require 'calrom/exceptions'
21
+ require 'calrom/sanctorale_file'
22
+ require 'calrom/filtering_calendar'
15
23
  require 'calrom/formatter/formatter'
16
24
  require 'calrom/formatter/list'
17
25
  require 'calrom/formatter/overview'
26
+ require 'calrom/formatter/condensed'
18
27
  require 'calrom/formatter/csv'
19
28
  require 'calrom/formatter/json'
20
29
  require 'calrom/formatter/easter'
@@ -22,3 +31,4 @@ require 'calrom/formatter/calendars'
22
31
  require 'calrom/highlighter/no'
23
32
  require 'calrom/highlighter/list'
24
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.3.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: 2020-06-21 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
@@ -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,8 +147,11 @@ 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
135
151
  - lib/calrom/exceptions.rb
152
+ - lib/calrom/filtering_calendar.rb
136
153
  - lib/calrom/formatter/calendars.rb
154
+ - lib/calrom/formatter/condensed.rb
137
155
  - lib/calrom/formatter/csv.rb
138
156
  - lib/calrom/formatter/easter.rb
139
157
  - lib/calrom/formatter/formatter.rb
@@ -143,8 +161,11 @@ files:
143
161
  - lib/calrom/highlighter/list.rb
144
162
  - lib/calrom/highlighter/no.rb
145
163
  - lib/calrom/highlighter/overview.rb
164
+ - lib/calrom/highlighter/selective.rb
146
165
  - lib/calrom/option_parser.rb
147
166
  - lib/calrom/rc_parser.rb
167
+ - lib/calrom/refinement/calendarium-romanum/triduum_nameclash_workaround.rb
168
+ - lib/calrom/sanctorale_file.rb
148
169
  - lib/calrom/version.rb
149
170
  homepage: https://github.com/calendarium-romanum/calrom
150
171
  licenses: