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 +4 -4
- data/.github/workflows/ci.yml +24 -0
- data/.travis.yml +2 -2
- data/CHANGELOG.md +52 -0
- data/README.md +69 -14
- data/calrom.gemspec +2 -1
- data/lib/calrom/cli.rb +27 -5
- data/lib/calrom/config.rb +101 -28
- data/lib/calrom/date_range.rb +26 -13
- data/lib/calrom/environment_reader.rb +36 -0
- data/lib/calrom/filtering_calendar.rb +71 -0
- data/lib/calrom/formatter/calendars.rb +15 -8
- data/lib/calrom/formatter/condensed.rb +51 -0
- data/lib/calrom/formatter/csv.rb +2 -3
- data/lib/calrom/formatter/easter.rb +1 -1
- data/lib/calrom/formatter/formatter.rb +12 -1
- data/lib/calrom/formatter/json.rb +3 -3
- data/lib/calrom/formatter/list.rb +6 -8
- data/lib/calrom/formatter/overview.rb +15 -10
- data/lib/calrom/highlighter/selective.rb +34 -0
- data/lib/calrom/option_parser.rb +65 -12
- data/lib/calrom/refinement/calendarium-romanum/triduum_nameclash_workaround.rb +34 -0
- data/lib/calrom/sanctorale_file.rb +14 -0
- data/lib/calrom/version.rb +1 -1
- data/lib/calrom.rb +10 -0
- metadata +25 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2e561032a6b91d68a87839856d8ce94b794187a539ac544fc907cfd2568add7
|
4
|
+
data.tar.gz: 8c9ab4bbdc83cc0c9884dbb4fb9f658c578e83956ce63da45b8698f59c55124f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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
|
-
|
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
|
112
|
-
--calendar
|
113
|
-
|
114
|
-
--
|
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
|
-
* [
|
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
|
-
* [
|
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
|
-
|
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.
|
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
|
15
|
+
rescue OptionParser::Error, InputError => e
|
14
16
|
STDERR.puts e.message
|
15
17
|
exit 1
|
16
18
|
end
|
17
19
|
|
18
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
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 ||
|
100
|
+
@locale || locale_in_file_metadata || DEFAULT_LOCALE
|
43
101
|
end
|
44
102
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
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
|
72
|
-
|
142
|
+
def locale_in_file_metadata
|
143
|
+
is_remote_calendar? ? nil : build_sanctorale.metadata['locale']&.to_sym
|
144
|
+
end
|
73
145
|
|
74
|
-
|
146
|
+
def is_remote_calendar?
|
147
|
+
!!@sanctorale.find {|s| s =~ /^https?:\/\// }
|
75
148
|
end
|
76
149
|
end
|
77
150
|
end
|
data/lib/calrom/date_range.rb
CHANGED
@@ -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
|
-
|
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 =
|
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
|
-
|
8
|
+
sanctorale = d.load_with_parents
|
9
|
+
meta = sanctorale.metadata
|
11
10
|
puts if last_locale && last_locale != meta['locale']
|
12
|
-
|
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
|
data/lib/calrom/formatter/csv.rb
CHANGED
@@ -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
|
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 |
|
13
|
-
|
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.
|
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
|
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
|
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
|
8
|
-
colnum =
|
7
|
+
def call(calendar, date_range)
|
8
|
+
colnum = 3 # TODO: expose configuration
|
9
9
|
if date_range.is_a? Year
|
10
|
-
|
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
|
33
|
-
|
32
|
+
calendar.each_day_in_range(month, include_skipped: true) do |liturgical_day|
|
33
|
+
date = liturgical_day.date
|
34
34
|
|
35
|
-
|
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
|
data/lib/calrom/option_parser.rb
CHANGED
@@ -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(
|
16
|
-
self.new.call(
|
22
|
+
def self.call(*args)
|
23
|
+
self.new.call(*args)
|
17
24
|
end
|
18
25
|
|
19
|
-
def call(argv)
|
20
|
-
config
|
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 =
|
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 =
|
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 =
|
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
|
-
|
100
|
-
|
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 =
|
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
|
-
|
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
|
data/lib/calrom/version.rb
CHANGED
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.
|
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:
|
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.
|
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.
|
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:
|