lib/csl/locale/term.rb in csl-1.0.0.pre5 vs lib/csl/locale/term.rb in csl-1.0.0.pre6
- old
+ new
@@ -1,93 +1,130 @@
module CSL
class Locale
-
+
class Terms < Node
attr_children :term
-
+
alias terms term
def_delegators :terms, :size, :length
-
+
undef_method :[]=
-
+
def initialize(attributes = {})
- super(attributes)
+ super(attributes)
@registry, children[:term] = Hash.new { |h,k| h[k] = [] }, []
yield self if block_given?
end
alias each each_child
-
+
def lookup(query)
query = { :name => query } unless query.is_a?(Hash)
-
+
terms = if query[:name].is_a?(Regexp)
registry.select { |name, _| name =~ query[:name] }.flatten(1)
else
registry[query[:name].to_s]
end
- terms.detect { |t| t.exact_match?(query) }
+ terms.detect { |t| t.match?(query) }
end
-
+
alias [] lookup
+
+ def lookup_modulo(query, divisor)
+ term = lookup(query)
+ return if term.nil? || !term.match_modulo?(divisor)
+ term
+ end
private
-
+
# @!attribute [r] registry
# @return [Hash] a private registry to map term names to the respective
# term objects for quick term look-up
attr_reader :registry
-
+
def added_child(term)
raise ValidationError, "failed to register term #{term.inspect}: name attribute missing" unless
term.attribute?(:name)
-
+
registry[term[:name]].push(term)
term
end
-
+
def deleted_child(term)
registry[term[:name]].delete(term)
end
end
-
+
class Term < Node
- attr_struct :name, :form, :gender, :'gender-form'
+ attr_struct :name, :form, :gender, :'gender-form', :match
attr_children :single, :multiple
attr_accessor :text
def_delegators :attributes, :hash, :eql?, :name, :form, :gender
+ # This method returns whether or not the ordinal term matchs the
+ # passed-in modulus. This is determined by the ordinal term's match
+ # attribute: a value of '2-digits' matches a divisor of 100, '1-digit'
+ # matches a divisor of 10 and 'whole-number' matches a divisor of 1.
+ #
+ # If the term is no ordinal term, this methods always returns false.
+ #
+ # @return [Boolean] whether or not the ordinal term matches the
+ # passed-in divisor.
+ def match_modulo?(divisor)
+ return false unless ordinal?
+
+ case attributes.match
+ when '2-digits'
+ divisor.to_i == 100
+ when '1-digit'
+ divisor.to_i == 10
+ when 'whole-number'
+ divisor.to_i == 1
+ else
+ true
+ end
+ end
+
+ alias matches_modulo? match_modulo?
+
+ # @return [Boolean] whether or not this term is an ordinal term
+ def ordinal?
+ /^ordinal(-\d\d+)?$/ === attributes.name
+ end
+
def gendered?
!attributes.gender.blank?
end
-
+
def neutral?
!gendered?
end
-
+
def textnode?
!text.blank?
end
-
+
def singularize
return text if textnode?
children.single.to_s
end
alias singular singularize
-
+
def pluralize
return text if textnode?
children.multiple.to_s
- end
+ end
- alias plural pluralize
-
+ alias plural pluralize
+
# @!method masculine?
# @return [Boolean] whether or not the term is masculine
# @!method masculine!
# @return [self,nil] the term with the gender attribute set to
@@ -101,11 +138,11 @@
# 'feminine', or nil if the term was already feminine
%w{ masculine feminine }.each do |name|
define_method("#{name}?") do
attributes.gender.to_s == name
end
-
+
define_method("#{name}!") do
return nil if attributes.gender.to_s == name
attributes.gender = name
self
end
@@ -137,35 +174,35 @@
else
singularize
end
end
end
-
+
class Single < TextNode; end
class Multiple < TextNode; end
-
+
private
-
+
def pluralize?(options)
return false if options.nil?
-
+
case
when options.key?(:plural) || options.key?('plural')
options[:plural] || options['plural']
when options.key?(:number) || options.key?('number')
key = options[:number] || options['number']
-
+
if key.is_a?(Fixnum) || key.to_s =~ /^[+-]?\d+$/
key.to_i > 1
else
!key.blank? && key.to_s =~ /^plural/i
end
else
false
end
end
-
+
end
-
+
TextNode.types << Term
end
end
\ No newline at end of file