lib/thor/core_ext/ordered_hash.rb
class Thor module CoreExt #:nodoc: if RUBY_VERSION >= "1.9" class OrderedHash < ::Hash end else # This class is based on the Ruby 1.9 ordered hashes. # # It keeps the semantics and most of the efficiency of normal hashes # while also keeping track of the order in which elements were set. # class OrderedHash #:nodoc: include Enumerable Node = Struct.new(:key, :value, :next, :prev) def initialize @hash = {} end def [](key) @hash[key] && @hash[key].value end def []=(key, value) if node = @hash[key] # rubocop:disable AssignmentInCondition node.value = value else node = Node.new(key, value) if !defined?(@first) || @first.nil? @first = @last = node else node.prev = @last @last.next = node @last = node end end @hash[key] = node value end def delete(key) if node = @hash[key] # rubocop:disable AssignmentInCondition prev_node = node.prev next_node = node.next next_node.prev = prev_node if next_node prev_node.next = next_node if prev_node @first = next_node if @first == node @last = prev_node if @last == node value = node.value end @hash.delete(key) value end def keys map { |k, v| k } end def values map { |k, v| v } end def each return unless defined?(@first) && @first yield [@first.key, @first.value] node = @first yield [node.key, node.value] while node = node.next # rubocop:disable AssignmentInCondition self end def merge(other) hash = self.class.new each do |key, value| hash[key] = value end other.each do |key, value| hash[key] = value end hash end def empty? @hash.empty? end end end end end