lib/nanoc/base/ordered_hash.rb in nanoc-3.6.7 vs lib/nanoc/base/ordered_hash.rb in nanoc-3.6.8
- old
+ new
@@ -1,200 +1,228 @@
+# encoding: utf-8
# AUTHOR
# jan molic /mig/at/1984/dot/cz/
#
# DESCRIPTION
# Hash with preserved order and some array-like extensions
-# Public domain.
+# Public domain.
#
# THANKS
# Andrew Johnson for his suggestions and fixes of Hash[],
# merge, to_a, inspect and shift
class OrderedHash < ::Hash
- attr_accessor :order
+ attr_accessor :order
- class << self
- def [] *args
- hsh = OrderedHash.new
- if Hash === args[0]
- hsh.replace args[0]
- elsif (args.size % 2) != 0
- raise ArgumentError, "odd number of elements for Hash"
- else
- 0.step(args.size - 1, 2) do |a|
- b = a + 1
- hsh[args[a]] = args[b]
- end
- end
- hsh
+ class << self
+ def [](*args)
+ hsh = OrderedHash.new
+ if args[0].is_a?(Hash)
+ hsh.replace args[0]
+ elsif args.size.odd?
+ raise ArgumentError, 'odd number of elements for Hash'
+ else
+ 0.step(args.size - 1, 2) do |a|
+ b = a + 1
+ hsh[args[a]] = args[b]
end
+ end
+ hsh
end
- def initialize(*a, &b)
- super
- @order = []
+ end
+
+ def initialize(*a, &b)
+ super
+ @order = []
+ end
+
+ def store_only(a, b)
+ store a, b
+ end
+ alias_method :orig_store, :store
+
+ def store(a, b)
+ @order.push a unless key? a
+ super a, b
+ end
+ alias_method :[]=, :store
+
+ def ==(other)
+ return false if @order != other.order
+ super other
+ end
+
+ def clear
+ @order = []
+ super
+ end
+
+ def delete(key)
+ @order.delete key
+ super
+ end
+
+ def each_key
+ @order.each { |k| yield k }
+ self
+ end
+
+ def each_value
+ @order.each { |k| yield self[k] }
+ self
+ end
+
+ def each
+ @order.each { |k| yield k, self[k] }
+ self
+ end
+ alias_method :each_pair, :each
+
+ def delete_if
+ @order.clone.each do |k|
+ delete k if yield(k)
end
- def store_only a,b
- store a,b
+ self
+ end
+
+ def values
+ ary = []
+ @order.each { |k| ary.push self[k] }
+ ary
+ end
+
+ def keys
+ @order
+ end
+
+ def first
+ { @order.first => self[@order.first] }
+ end
+
+ def last
+ { @order.last => self[@order.last] }
+ end
+
+ def invert
+ hsh2 = {}
+ @order.each { |k| hsh2[self[k]] = k }
+ hsh2
+ end
+
+ def reject(&block)
+ dup.delete_if(&block)
+ end
+
+ def reject!(&block)
+ hsh2 = reject(&block)
+ self == hsh2 ? nil : hsh2
+ end
+
+ def replace(hsh2)
+ @order = hsh2.keys
+ super hsh2
+ end
+
+ def shift
+ key = @order.first
+ key ? [key, delete(key)] : super
+ end
+
+ def unshift(k, v)
+ if self.include? k
+ false
+ else
+ @order.unshift k
+ orig_store(k, v)
+ true
end
- alias orig_store store
- def store a,b
- @order.push a unless has_key? a
- super a,b
+ end
+
+ def push(k, v)
+ if self.include? k
+ false
+ else
+ @order.push k
+ orig_store(k, v)
+ true
end
- alias []= store
- def == hsh2
- return false if @order != hsh2.order
- super hsh2
- end
- def clear
- @order = []
- super
- end
- def delete key
- @order.delete key
- super
- end
- def each_key
- @order.each { |k| yield k }
- self
- end
- def each_value
- @order.each { |k| yield self[k] }
- self
- end
- def each
- @order.each { |k| yield k,self[k] }
- self
- end
- alias each_pair each
- def delete_if
- @order.clone.each { |k|
- delete k if yield(k)
- }
- self
- end
- def values
- ary = []
- @order.each { |k| ary.push self[k] }
- ary
- end
- def keys
- @order
- end
- def first
- {@order.first => self[@order.first]}
- end
- def last
- {@order.last => self[@order.last]}
- end
- def invert
- hsh2 = Hash.new
- @order.each { |k| hsh2[self[k]] = k }
- hsh2
- end
- def reject &block
- self.dup.delete_if &block
- end
- def reject! &block
- hsh2 = reject &block
- self == hsh2 ? nil : hsh2
- end
- def replace hsh2
- @order = hsh2.keys
- super hsh2
- end
- def shift
- key = @order.first
- key ? [key,delete(key)] : super
- end
- def unshift k,v
- unless self.include? k
- @order.unshift k
- orig_store(k,v)
- true
- else
- false
- end
- end
- def push k,v
- unless self.include? k
- @order.push k
- orig_store(k,v)
- true
- else
- false
- end
- end
- def pop
- key = @order.last
- key ? [key,delete(key)] : nil
- end
- def to_a
- ary = []
- each { |k,v| ary << [k,v] }
- ary
- end
- def to_s
- self.to_a.to_s
- end
- def inspect
- ary = []
- each {|k,v| ary << k.inspect + "=>" + v.inspect}
- '{' + ary.join(", ") + '}'
- end
- def update hsh2
- hsh2.each { |k,v| self[k] = v }
- self
- end
- alias :merge! update
- def merge hsh2
- self.dup update(hsh2)
- end
- def select
- ary = []
- each { |k,v| ary << [k,v] if yield k,v }
- ary
- end
- def class
- Hash
- end
- def __class__
- OrderedHash
- end
+ end
- attr_accessor "to_yaml_style"
- def yaml_inline= bool
- if respond_to?("to_yaml_style")
- self.to_yaml_style = :inline
- else
- unless defined? @__yaml_inline_meth
- @__yaml_inline_meth =
- lambda {|opts|
- YAML::quick_emit(object_id, opts) {|emitter|
- emitter << '{ ' << map{|kv| kv.join ': '}.join(', ') << ' }'
- }
- }
- class << self
- def to_yaml opts = {}
- begin
- @__yaml_inline ? @__yaml_inline_meth[ opts ] : super
- rescue
- @to_yaml_style = :inline
- super
- end
- end
+ def pop
+ key = @order.last
+ key ? [key, delete(key)] : nil
+ end
+
+ def to_a
+ ary = []
+ each { |k, v| ary << [k, v] }
+ ary
+ end
+
+ def to_s
+ to_a.to_s
+ end
+
+ def inspect
+ ary = []
+ each { |k, v| ary << k.inspect + '=>' + v.inspect }
+ '{' + ary.join(', ') + '}'
+ end
+
+ def update(hsh2)
+ hsh2.each { |k, v| self[k] = v }
+ self
+ end
+ alias_method :merge!, :update
+
+ def merge(hsh2)
+ dup update(hsh2)
+ end
+
+ def select
+ ary = []
+ each { |k, v| ary << [k, v] if yield k, v }
+ ary
+ end
+
+ def class
+ Hash
+ end
+
+ def __class__
+ OrderedHash
+ end
+
+ attr_accessor 'to_yaml_style'
+ def yaml_inline=(bool)
+ if respond_to?('to_yaml_style')
+ self.to_yaml_style = :inline
+ else
+ unless defined? @__yaml_inline_meth
+ @__yaml_inline_meth =
+ lambda do |opts|
+ YAML.quick_emit(object_id, opts) do |emitter|
+ emitter << '{ ' << map { |kv| kv.join ': ' }.join(', ') << ' }'
end
end
+ class << self
+ def to_yaml(opts = {})
+ @__yaml_inline ? @__yaml_inline_meth[ opts ] : super
+ rescue
+ @to_yaml_style = :inline
+ super
+ end
+ end
end
- @__yaml_inline = bool
end
- def yaml_inline!() self.yaml_inline = true end
+ @__yaml_inline = bool
+ end
- def each_with_index
- @order.each_with_index { |k, index| yield k, self[k], index }
- self
- end
-end # class OrderedHash
+ def yaml_inline!
+ self.yaml_inline = true
+ end
-def OrderedHash(*a, &b)
- OrderedHash.new(*a, &b)
-end
+ def each_with_index
+ @order.each_with_index { |k, index| yield k, self[k], index }
+ self
+ end
+end # class OrderedHash