summaryrefslogtreecommitdiff
path: root/lib/irb/inspector.rb
blob: 94f42d52174a2250e52b541a8efa963cbabc639b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#
#   irb/inspector.rb - inspect methods
#   	$Release Version: 0.9.6$
#   	$Revision: 1.19 $
#   	$Date: 2002/06/11 07:51:31 $
#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
# --
#
#
#

module IRB # :nodoc:


  # Convenience method to create a new Inspector, using the given +inspect+
  # proc, and optional +init+ proc and passes them to Inspector.new
  #
  #     irb(main):001:0> ins = IRB::Inspector(proc{ |v| "omg! #{v}" })
  #     irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! #<IRB::Inspector:0x007f46f7ba7d28>
  #     irb(main):001:0> "what?" #=> omg! what?
  #
  def IRB::Inspector(inspect, init = nil)
    Inspector.new(inspect, init)
  end

  # An irb inspector
  #
  # In order to create your own custom inspector there are two things you
  # should be aware of:
  #
  # Inspector uses #inspect_value, or +inspect_proc+, for output of return values.
  #
  # This also allows for an optional #init+, or +init_proc+, which is called
  # when the inspector is activated.
  #
  # Knowing this, you can create a rudimentary inspector as follows:
  #
  #     irb(main):001:0> ins = IRB::Inspector.new(proc{ |v| "omg! #{v}" })
  #     irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! #<IRB::Inspector:0x007f46f7ba7d28>
  #     irb(main):001:0> "what?" #=> omg! what?
  #
  class Inspector
    # Creates a new inspector object, using the given +inspect_proc+ when
    # output return values in irb.
    def initialize(inspect_proc, init_proc = nil)
      @init = init_proc
      @inspect = inspect_proc
    end

    # Proc to call when the inspector is activated, good for requiring
    # dependant libraries.
    def init
      @init.call if @init
    end

    # Proc to call when the input is evaluated and output in irb.
    def inspect_value(v)
      @inspect.call(v)
    end
  end

  # Default inspectors available to irb, this includes:
  #
  # +:pp+::       Using Kernel#pretty_inspect
  # +:yaml+::     Using YAML.dump
  # +:marshal+::  Using Marshal.dump
  INSPECTORS = {}

  # Determines the inspector to use where +inspector+ is one of the keys passed
  # during inspector definition.
  def INSPECTORS.keys_with_inspector(inspector)
    select{|k,v| v == inspector}.collect{|k, v| k}
  end

  # Example
  #
  #     INSPECTORS.def_inspector(key, init_p=nil){|v| v.inspect}
  #     INSPECTORS.def_inspector([key1,..], init_p=nil){|v| v.inspect}
  #     INSPECTORS.def_inspector(key, inspector)
  #     INSPECTORS.def_inspector([key1,...], inspector)
  def INSPECTORS.def_inspector(key, arg=nil, &block)
#     if !block_given?
#       case arg
#       when nil, Proc
# 	inspector = IRB::Inspector(init_p)
#       when Inspector
# 	inspector = init_p
#       else
# 	IRB.Raise IllegalParameter, init_p
#       end
#       init_p = nil
#     else
#       inspector = IRB::Inspector(block, init_p)
#     end

    if block_given?
      inspector = IRB::Inspector(block, arg)
    else
      inspector = arg
    end

    case key
    when Array
      for k in key
	def_inspector(k, inspector)
      end
    when Symbol
      self[key] = inspector
      self[key.to_s] = inspector
    when String
      self[key] = inspector
      self[key.intern] = inspector
    else
      self[key] = inspector
    end
  end

  INSPECTORS.def_inspector([false, :to_s, :raw]){|v| v.to_s}
  INSPECTORS.def_inspector([true, :p, :inspect]){|v|
    begin
      v.inspect
    rescue NoMethodError
      puts "(Object doesn't support #inspect)"
    end
  }
  INSPECTORS.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v| v.pretty_inspect.chomp}
  INSPECTORS.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
    begin
      YAML.dump(v)
    rescue
      puts "(can't dump yaml. use inspect)"
      v.inspect
    end
  }

  INSPECTORS.def_inspector([:marshal, :Marshal, :MARSHAL, Marshal]){|v|
    Marshal.dump(v)
  }
end