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