lib/debug_helper.rb in debug_helper-1.7.0 vs lib/debug_helper.rb in debug_helper-1.8.0

- old
+ new

@@ -1,10 +1,34 @@ +require 'ostruct' require 'set' require 'yaml' -require 'debug_helper/version' +require_relative 'debug_helper/version' +require_relative 'debug_helper/handler' + + require_relative 'debug_helper/each_with_index_handler' + require_relative 'debug_helper/array_handler' + require_relative 'debug_helper/set_handler' + + require_relative 'debug_helper/each_pair_handler' + require_relative 'debug_helper/hash_handler' + require_relative 'debug_helper/struct_handler' + + require_relative 'debug_helper/dir_handler' + require_relative 'debug_helper/exception_handler' + require_relative 'debug_helper/file_handler' + require_relative 'debug_helper/generic_handler' + require_relative 'debug_helper/io_handler' + require_relative 'debug_helper/match_data_handler' + require_relative 'debug_helper/object_handler' + require_relative 'debug_helper/open_struct_handler' + require_relative 'debug_helper/regexp_handler' + require_relative 'debug_helper/string_handler' + require_relative 'debug_helper/symbol_handler' + require_relative 'debug_helper/range_handler' + class DebugHelper module Putd def putd(obj, message, options = {}) @@ -19,185 +43,80 @@ :object_ids, :depth def self.show(obj, message = obj.class, options = {}) debug_helper = DebugHelper.new(obj, message, options) - x = debug_helper.send(:_show, obj, message, info = {}) - puts x.to_yaml + s = debug_helper.show(obj, message, info = {}) + puts s.to_yaml end - private - def initialize(obj, message, options) self.obj = obj self.message = message self.depth = options[:depth] || 3 self.object_ids = [] end - def _show(obj, message, info) - if object_ids.include?(obj.object_id) - s = show_object(obj, message, info) - elsif depth == object_ids.size - s = show_object(obj, message, info) - else - object_ids.push(obj.object_id) - s = case - when obj.kind_of?(Array) - show_array(obj, message, info) - when obj.kind_of?(Hash) - show_hash(obj, message, info) - when obj.kind_of?(Set) - show_array(obj, message, info) - when obj.kind_of?(Struct) - show_struct(obj, message, info) - # when obj.kind_of?(Range) - else - show_object(obj, message, info) - end - object_ids.pop - end - s + def object_seen?(obj) + object_ids.include?(obj.object_id) end - def show_array(obj, message, info) - content = {} - obj.each_with_index do |item, i| - content.store("Element #{i}", _show(item, nil, {})) - end - attrs = { - :message => message, - :size => obj.size, - } - _show_item(obj.class.name, content, attrs, info) + def depth_reached? + depth == object_ids.size end - def show_hash(obj, message, info) - content = {} - obj.each_with_index do |pair, i| - key, value = *pair - pair = {'Key' => _show(key, nil, {}), 'Value' => _show(value, nil, {})} - content.store("Pair #{i}", pair) - end - attrs = { - :size => obj.size, - :default => obj.default, - :default_proc => obj.default_proc, - :message => message, - } - _show_item(obj.class.name, content, attrs, info) - end - - def show_object(obj, message, info) - methods = methods_for_object(obj) - if methods.nil? - message_info = message.nil? ? '' : " (message='#{message}')" - "#{obj.class.name}#{message_info} #{obj.inspect}" + def show(obj, message, info) + handler = nil + if object_seen?(obj) || depth_reached? + handler = GenericHandler.new(self, obj, message, info) + s = handler.show else - content = {} - attrs = {:message => message} - methods[:instance].each do |instance_method| - value = obj.send(instance_method) - if instance_method == :size - attrs.store(:size, value) + object_ids.push(obj.object_id) + begin + # If there's a handler for the class, use it. + # Note that the class may be a custom class, not defined here, + # but instead defined outside this project. + # So if the user of this library has defined DebugHelper::FooHandler + # and the object is a Foo, that handler will be selected and called. + handler_class_name = "DebugHelper::#{obj.class.name}Handler" + handler_class = Object.const_get(handler_class_name) + handler = handler_class.new(method(__method__), obj, message, info) + rescue + # If there's not a handler for the class, try using :kind_of?. + [ + Array, + Dir, + Exception, + File, + IO, + Hash, + OpenStruct, + Range, + Set, + String, + Struct, + # There's no method Symbol.new, so cannot instantiate a subclass. + # Symbol, + ].each do |klass| + if obj.kind_of?(klass) + handler_class_name = "DebugHelper::#{klass.name}Handler" + handler_class = Object.const_get(handler_class_name) + handler = handler_class.new(method(__method__), obj, message, info) + break + end + end + end + if handler.nil? + if obj.instance_of?(Object) + handler_class= ObjectHandler else - content.store(instance_method.to_s, value) + handler_class = GenericHandler end + handler = handler_class.new(self, obj, message, info) end - methods[:class].each do |pair| - class_method, arguments = *pair - value = Object.const_get(obj.class.to_s).send(class_method, *arguments) - content.store(class_method.to_s, value) - end - _show_item(obj.class.name, content, attrs, info) + s = handler.show + object_ids.pop end - end - - def show_struct(obj, message, info) - content = {} - i = 0 - obj.each_pair do |member| - member_name, value = *member - pair = {'Name' => member_name, 'Value' => _show(value, nil, {})} - content.store("Member #{i}", pair) - i += 1 - end - attrs = { - :message => message, - :size => obj.size, - } - _show_item(obj.class.name, content, attrs, info) - end - - def _show_item(class_name, content, attrs, info) - message = attrs[:message] - unless message.nil? - attrs[:message] = "'#{message}'" - end - label = label(class_name, attrs) - info.store(label, content) - info - end - - def label(class_name, attrs) - a = [] - attrs.each_pair do |key, value| - a.push("#{key}=#{value}") unless value.nil? - end - return class_name if a.empty? - attrs_s = a.join(' ') - "#{class_name} (#{attrs_s})" - end - - def methods_for_object(obj) - methods = case - when obj.kind_of?(File) - { - # The instance forms of some of these require the file to be open. - :class => { - :absolute_path => [obj.path], - :atime => [obj.path], - :ctime => [obj.path], - :executable? => [obj.path], - :exist? => [obj.path], - :ftype => [obj.path], - :mtime => [obj.path], - :path => [obj.path], - :pipe? => [obj.path], - :readable? => [obj.path], - :realpath => [obj.path], - :setgid? => [obj.path], - :setuid? => [obj.path], - :size => [obj.path], - :socket? => [obj.path], - :symlink? => [obj.path], - :writable? => [obj.path], - }, - :instance => [], - } - when obj.kind_of?(String) - { - :class => {}, - :instance => [ - :to_s, - :size, - :encoding, - :ascii_only?, - :bytesize, - ] - } - when obj.kind_of?(Symbol) - { - :class => {}, - :instance => [ - :to_s, - :size, - :encoding, - ] - } - else - nil - end - methods + s end end