lib/citeproc/names.rb in citeproc-1.0.0.pre12 vs lib/citeproc/names.rb in citeproc-1.0.0
- old
+ new
@@ -42,23 +42,21 @@
include Attributes
include Comparable
# Class instance variables
- @romanesque = CiteProc.oniguruma {
- '^[\p{Latin}\p{Greek}\p{Cyrillic}\p{Hebrew}\p{Armenian}\p{Georgian}\p{Common}]*$'
- } || CiteProc.ruby_18 {
- # @todo improve fallback range
- /^[a-zA-Zäöüéè\s[:punct:]]*$/u
- }
+ @romanesque =
+ /^[\p{Latin}\p{Greek}\p{Cyrillic}\p{Hebrew}\p{Armenian}\p{Georgian}\p{Common}]*$/
# Default formatting options
@defaults = {
:form => 'long',
:'name-as-sort-order' => false,
:'demote-non-dropping-particle' => :never,
:'sort-separator' => ', ',
+ :initialize => true,
+ :'initialize-with-hyphen' => true,
:'initialize-with' => nil
}.freeze
@parts = [:family, :given,:literal, :suffix, :'dropping-particle',
:'non-dropping-particle'].freeze
@@ -73,10 +71,12 @@
# @!attribute [r] options
# @return the name's formatting options
attr_reader :options
+ attr_reader :sort_prefix
+
attr_predicates :'comma-suffix', :'static-ordering', :multi, *@parts
# Aliases
[[:particle, :'non_dropping_particle']].each do |a, m|
alias_method(a, m) if method_defined?(m)
@@ -90,12 +90,13 @@
pa, pm = "has_#{a}?", "has_#{m}?"
alias_method(pa, pm) if method_defined?(pm)
end
# Names quack sorta like a String
- def_delegators :to_s, :=~, :===,
- *String.instance_methods(false).reject { |m| m =~ /^\W|!$|to_s|replace|first|last/ }
+ def_delegators :to_s, :=~, :===, *String.instance_methods(false).reject { |m|
+ m.to_s =~ /^[\W_]|[!=_]$|^(to_s|inspect|replace|first|last|dup|clone)$/
+ }
# Delegate bang! methods to each field's value
String.instance_methods(false).each do |m|
if m.to_s.end_with?('!')
define_method(m) do |*arguments, &block|
@@ -124,16 +125,28 @@
@attributes = other.attributes.deep_copy
@options = other.options.dup
end
+ # Resets the object's options to the default settings.
+ # @return [self]
+ def reset!
+ @options = Name.defaults.dup
+ end
+
+ # Returns a copy of the name object with all options
+ # reset to their default settings.
+ # @return [Name] a copy of the name with default options
+ def reset
+ dup.reset!
+ end
+
# @return [Boolean] whether or not the Name looks like it belongs to a person
def personal?
!empty? && !literal?
end
-
# A name is `romanesque' if it contains only romanesque characters. This
# should be the case for the majority of names written in latin- or
# greek-based script. It will be false, for example, for names written
# in Chinese, Japanese, Arabic or Hebrew.
#
@@ -171,19 +184,19 @@
!sort_order?
end
# Sets the name to use sort-order. The reverse of {#display_order!}.
# @return [self]
- def sort_order!
- options[:'name-as-sort-order'] = true
+ def sort_order!(toggle = true)
+ options[:'name-as-sort-order'] = !!toggle
self
end
# Sets the name to use display-order. The reverse of {#sort_order!}.
# @return [self]
- def display_order!
- options[:'name-as-sort-order'] = false
+ def display_order!(toggle = true)
+ options[:'name-as-sort-order'] = !toggle
self
end
# @return [String] the current sort separator
def sort_separator
@@ -198,11 +211,11 @@
end
# Use short form for printing the name
# @return [self]
def short_form!
- options[:form] = :short
+ options[:form] = 'short'
self
end
# @return [Boolean] whether or not the long form will be used for printing
def long_form?
@@ -210,19 +223,46 @@
end
# Use long form for printing the name
# @return [self]
def long_form!
- options[:form] = :long
+ options[:form] = 'long'
self
end
# @return [Boolean] whether or not initials will be used for printing
def initials?
!!options[:'initialize-with'] && personal? && romanesque?
end
+ def initialize_with
+ options[:'initialize-with'].to_s
+ end
+
+ def initialize_existing_only?
+ options[:initialize].to_s == 'false'
+ end
+
+ def initialize_without_hyphen?
+ !options[:'initialize-with-hyphen']
+ end
+
+ def initialize_without_hyphen!
+ options[:'initialize-with-hyphen'] = false
+ end
+
+ def initials
+ case
+ when !initials?
+ given
+ when initialize_existing_only?
+ existing_initials_of given
+ else
+ initials_of given
+ end
+ end
+
def demote_non_dropping_particle?
always_demote_non_dropping_particle? ||
!!(sort_order? && options[:'demote-non-dropping-particle'] =~ /^sort(-only)?$/i)
end
@@ -264,35 +304,40 @@
def <=>(other)
return nil unless other.respond_to?(:sort_order_downcase)
sort_order_downcase <=> other.sort_order_downcase
end
- # @return [String] the name formatted according to the current options
def to_s
+ [given, family].compact_join(' ')
+ end
+
+ # @return [String] the name formatted according to the current options
+ def format
case
when literal?
literal.to_s
when static_order?
- [family, given].compact.join(' ')
+ [family, initials].compact.join(' ')
when !short_form?
case
when !sort_order?
- [[given, dropping_particle, particle, family].compact_join(' '),
+ [[initials, dropping_particle, particle, family].compact_join(' '),
suffix].compact_join(comma_suffix? ? comma : ' ')
when !demote_particle?
- [[particle, family].compact_join(' '), [given,
+ [[particle, family].compact_join(' '), [initials,
dropping_particle].compact_join(' '), suffix].compact_join(comma)
else
- [family, [given, dropping_particle, particle].compact_join(' '),
+ [family, [initials, dropping_particle, particle].compact_join(' '),
suffix].compact_join(comma)
end
else
[particle, family].compact_join(' ')
end
end
+ alias print format
# @return [Array<String>] an ordered array of formatted name parts to be used for sorting
def sort_order
case
when literal?
@@ -324,12 +369,46 @@
"#<CiteProc::Name #{to_s.inspect}>"
end
private
- attr_reader :sort_prefix
+ def filter_key(key)
+ key = key.to_s.tr('_', '-')
+ key = 'non-dropping-particle' if key == 'particle'
+ super key
+ end
+ def initials_of(string)
+ string = string.dup
+
+ string.gsub!(/([[:upper:]])[^[:upper:]\s-]*\s*/, "\\1#{initialize_with}")
+
+ initialize_hyphen!(string)
+
+ string.strip!
+ string
+ end
+
+ def initialize_hyphen!(string)
+ if initialize_without_hyphen?
+ string.tr!('-', '')
+ else
+ string.gsub!(/\s*-/, '-')
+ end
+ end
+
+ def existing_initials_of(string)
+ string = string.dup
+
+ string.gsub!(/([[:upper:]])([[:upper:]])/, '\1 \2')
+ string.gsub!(/\b([[:upper:]])\b[^[:alpha:]-]*/, "\\1#{initialize_with}")
+
+ initialize_hyphen!(string)
+
+ string.strip!
+ string
+ end
end
@@ -481,11 +560,11 @@
@value << value
when value.respond_to?(:each_pair), value.respond_to?(:to_hash)
@value << Name.new(value)
when value.respond_to?(:to_s)
begin
- @value.concat Namae.parse!(value.to_s)
+ @value.concat Namae.parse!(value.to_s).map { |n| Name.new n }
rescue
raise TypeError, $!.message
end
else
raise TypeError, "failed to create names from #{value.inspect}"
@@ -633,19 +712,19 @@
# @return [String] the formatted list of names
def to_s
case
when truncate?
[names[0...max_names].join(delimiter), options[:'et-al']].join(truncated_delimiter)
- when length < 2
+ when length < 3
names.join(last_delimiter)
else
[names[0...-1].join(delimiter), names[-1]].join(last_delimiter)
end
end
# @return [String] the names in a BibTeX-compatible format
def to_bibtex
- map { |n| n.dup.sort_order! }.join(' and ')
+ map { |n| n.dup.sort_order!.format }.join(' and ')
end
# @return [Array<Hash>] the list of names converted to hash objects
def to_citeproc
map(&:to_citeproc)