lib/csl/locale/term.rb in csl-1.0.0.pre15 vs lib/csl/locale/term.rb in csl-1.0.0.pre16

- old
+ new

@@ -19,21 +19,40 @@ yield self if block_given? end alias each each_child - # @return [Term, nil] the first term that matches the query + # If a style uses a term in a form that is undefined, there is a + # fallback to other forms: "verb-short" first falls back to "verb", + # "symbol" first falls back to "short", and "verb" and "short" both + # fall back to "long". If no form fallback is available, nil is + # returned instead. + # + # @return [Term, nil] the term that matches the query def lookup(name, options = {}) options = Term.specialize(options) + options[:name] = name = name.to_s + options[:form] = 'long' unless options.key?(:form) - # TODO default to long form + # NB: currently only ordinals support gender-forms + options.delete(:'gender-form') - term = registry[name].detect { |t| t.match?(options) } - return term unless term.nil? && options.delete(:'gender-form') + candidates = registry[name] + return if candidates.empty? - registry[name].detect { |t| t.match?(options) } + # loop terminates when a matching term is found or + # when there are no more form fallbacks left + while true do + term = candidates.detect { |t| t.match?(options) } + return term unless term.nil? + + fallback = Term.form_fallbacks[options[:form].to_s] + return if fallback == options[:form] + + options[:form] = fallback + end end alias [] lookup def ordinalize(number, options = {}) return unless has_ordinals? @@ -173,15 +192,28 @@ class Term < Node attr_struct :name, :form, :gender, :'gender-form', :match attr_children :single, :multiple + attr_defaults :form => 'long' + attr_accessor :text def_delegators :attributes, :hash, :eql?, :name, :form, :gender + @form_fallbacks = { + 'long' => 'long', + 'verb' => 'long', + 'short' => 'long', + 'verb-short' => 'verb', + 'symbol' => 'short' + }.freeze + class << self + + attr_reader :form_fallbacks + def specialize(options) options = options.select do |k,v| !v.nil? && Term::Attributes.keys.include?(k.to_sym) end @@ -241,11 +273,11 @@ def ordinal return unless ordinal? return :default if attributes.name == 'ordinal' attributes.name[/\d+/].to_i end - + def gendered? !attributes.gender.blank? end def neutral? @@ -254,11 +286,24 @@ def short? attribute?(:form) && attributes.form.to_s =~ /^short$/i end + def verb? + attribute?(:form) && attributes.form.to_s =~ /^verb$/i + end + + def verb_short? + attribute?(:form) && attributes.form.to_s =~ /^verb-short$/i + end + + def symbol? + attribute?(:form) && attributes.form.to_s =~ /^symbol$/i + end + def long? - !short? + return true unless attribute?(:form) + attributes.form.to_s =~ /^long$/i end def textnode? !text.blank? end \ No newline at end of file