class CalendariumRomanum::SanctoraleLoader
Understands a custom plaintext calendar format and knows how to transform it to {Celebration}s and fill them in a {Sanctorale}.
For specification of the data format see {file:data/README.md} of the data directory, For a complete example see e.g. {file:universal-en.txt the file describing General Roman Calendar}.
Constants
- COLOUR_CODES
@api private
- RANK_CODES
@api private
Public Instance Methods
load(src, dest = nil)
click to toggle source
Load from an object which understands #each_line
@param src [String, File, each_line]
source of the loaded data
@param dest [Sanctorale, nil]
objects to populate. If not provided, a new {Sanctorale} instance will be created
@return [Sanctorale] @raise [InvalidDataError]
# File lib/calendarium-romanum/sanctorale_loader.rb, line 44 def load(src, dest = nil) dest ||= Sanctorale.new in_front_matter = false front_matter = '' month_section = nil src.each_line.with_index(1) do |l, line_num| # skip YAML front matter if line_num == 1 && l.start_with?('---') in_front_matter = true front_matter += l next elsif in_front_matter if l.start_with?('---') in_front_matter = false dest.metadata = YAML.load(front_matter).freeze end front_matter += l next end # strip whitespace and comments l.sub!(/#.*/, '') l.strip! next if l.empty? # month section heading n = l.match(/^=\s*(\d+)\s*$/) unless n.nil? month_section = n[1].to_i unless month_section >= 1 && month_section <= 12 raise error("Invalid month #{month_section}", line_num) end next end begin celebration = load_line l, month_section rescue RangeError, RuntimeError => err raise error(err.message, line_num) end dest.add( celebration.date.month, celebration.date.day, celebration ) end dest end
Also aliased as: load_from_string
load_from_file(filename, dest = nil, encoding = 'utf-8')
click to toggle source
Load from a filesystem path
@param filename [String] @param dest [Sanctorale, nil] @param encoding [String] @return (see load
) @raise (see load
)
# File lib/calendarium-romanum/sanctorale_loader.rb, line 107 def load_from_file(filename, dest = nil, encoding = 'utf-8') load File.open(filename, 'r', encoding: encoding), dest end
Private Instance Methods
error(message, line_number)
click to toggle source
# File lib/calendarium-romanum/sanctorale_loader.rb, line 176 def error(message, line_number) InvalidDataError.new("L#{line_number}: #{message}") end
line_regexp()
click to toggle source
# File lib/calendarium-romanum/sanctorale_loader.rb, line 113 def line_regexp @line_regexp ||= begin rank_letters = RANK_CODES.keys.compact.join('|') colour_letters = COLOUR_CODES.keys.compact.join('') Regexp.new( '^((?<month>\d+)\/)?(?<day>\d+)' + # date '(\s+(?<rank_char>' + rank_letters + ')?(?<rank_num>\d\.\d{1,2})?)?' + # rank (optional) '(\s+(?<colour>[' + colour_letters + ']))?' + # colour (optional) '(\s+(?<symbol>[\w]{2,}))?' + # symbol (optional) '\s*:(?<title>.*)$', # title Regexp::IGNORECASE ) end end
load_line(line, month_section = nil)
click to toggle source
parses a line containing celebration record, returns a single Celebration
# File lib/calendarium-romanum/sanctorale_loader.rb, line 132 def load_line(line, month_section = nil) # celebration record m = line.match(line_regexp) if m.nil? raise RuntimeError.new("Syntax error, line skipped '#{line}'") end month = (m[:month] || month_section).to_i day = m[:day].to_i rank_char = m[:rank_char] rank_num = m[:rank_num] colour = m[:colour] symbol_str = m[:symbol] title = m[:title] rank = RANK_CODES[rank_char && rank_char.downcase] if rank_num rank_num = rank_num.to_f rank_by_num = Ranks[rank_num] if rank_by_num.nil? raise RuntimeError.new("Invalid celebration rank code #{rank_num}") elsif rank_char && (rank.priority.to_i != rank_by_num.priority.to_i) raise RuntimeError.new("Invalid combination of rank letter #{rank_char.inspect} and number #{rank_num}.") end rank = rank_by_num end symbol = nil if symbol_str symbol = symbol_str.to_sym end Celebration.new( title.strip, rank, COLOUR_CODES[colour && colour.downcase], symbol, AbstractDate.new(month, day) ) end