Class: IRB::WorkSpace

Inherits:
Object show all
Defined in:
lib/irb/workspace.rb,
lib/irb/ext/tracer.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*main) ⇒ WorkSpace

Creates a new workspace.

set self to main if specified, otherwise inherit main from TOPLEVEL_BINDING.


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
# File 'lib/irb/workspace.rb', line 21

def initialize(*main)
  if main[0].kind_of?(Binding)
    @binding = main.shift
  elsif IRB.conf[:SINGLE_IRB]
    @binding = TOPLEVEL_BINDING
  else
    case IRB.conf[:CONTEXT_MODE]
    when 0	# binding in proc on TOPLEVEL_BINDING
      @binding = eval("proc{binding}.call",
                      TOPLEVEL_BINDING,
                      __FILE__,
                      __LINE__)
    when 1	# binding in loaded file
      require "tempfile"
      f = Tempfile.open("irb-binding")
      f.print <<EOF
  $binding = binding
EOF
      f.close
      load f.path
      @binding = $binding

    when 2	# binding in loaded file(thread use)
      unless defined? BINDING_QUEUE
        IRB.const_set(:BINDING_QUEUE, Thread::SizedQueue.new(1))
        Thread.abort_on_exception = true
        Thread.start do
          eval "require \"irb/ws-for-case-2\"", TOPLEVEL_BINDING, __FILE__, __LINE__
        end
        Thread.pass
      end
      @binding = BINDING_QUEUE.pop

    when 3	# binding in function on TOPLEVEL_BINDING(default)
      @binding = eval("self.class.send(:remove_method, :irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding",
                      TOPLEVEL_BINDING,
                      __FILE__,
                      __LINE__ - 3)
    end
  end

  if main.empty?
    @main = eval("self", @binding)
  else
    @main = main[0]
  end
  IRB.conf[:__MAIN__] = @main

  unless main.empty?
    case @main
    when Module
      @binding = eval("IRB.conf[:__MAIN__].module_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
    else
      begin
        @binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
      rescue TypeError
        fail CantChangeBinding, @main.inspect
      end
    end
  end

  case @main
  when Object
    use_delegator = @main.frozen?
  else
    use_delegator = true
  end

  if use_delegator
    @main = SimpleDelegator.new(@main)
    IRB.conf[:__MAIN__] = @main
    @main.singleton_class.class_eval do
      private
      define_method(:exit) do |*a, &b|
        # Do nothing, will be overridden
      end
      define_method(:binding, Kernel.instance_method(:binding))
      define_method(:local_variables, Kernel.instance_method(:local_variables))
    end
    @binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, *@binding.source_location)
  end

  @binding.local_variable_set(:_, nil)
end

Instance Attribute Details

#bindingObject (readonly)

The Binding of this workspace


107
108
109
# File 'lib/irb/workspace.rb', line 107

def binding
  @binding
end

#mainObject (readonly)

The top-level workspace of this context, also available as IRB.conf[:__MAIN__]


110
111
112
# File 'lib/irb/workspace.rb', line 110

def main
  @main
end

Instance Method Details

#__evaluate__Object

Evaluate the given statements within the context of this workspace.


64
65
66
# File 'lib/irb/ext/tracer.rb', line 64

def evaluate(context, statements, file = __FILE__, line = __LINE__)
  eval(statements, @binding, file, line)
end

#code_around_bindingObject


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/irb/workspace.rb', line 138

def code_around_binding
  if @binding.respond_to?(:source_location)
    file, pos = @binding.source_location
  else
    file, pos = @binding.eval('[__FILE__, __LINE__]')
  end

  if defined?(::SCRIPT_LINES__[file]) && lines = ::SCRIPT_LINES__[file]
    code = ::SCRIPT_LINES__[file].join('')
  else
    begin
      code = File.read(file)
    rescue SystemCallError
      return
    end
  end

  # NOT using #use_colorize? of IRB.conf[:MAIN_CONTEXT] because this method may be called before IRB::Irb#run
  use_colorize = IRB.conf.fetch(:USE_COLORIZE, true)
  if use_colorize
    lines = Color.colorize_code(code).lines
  else
    lines = code.lines
  end
  pos -= 1

  start_pos = [pos - 5, 0].max
  end_pos   = [pos + 5, lines.size - 1].min

  if use_colorize
    fmt = " %2s #{Color.colorize("%#{end_pos.to_s.length}d", [:BLUE, :BOLD])}: %s"
  else
    fmt = " %2s %#{end_pos.to_s.length}d: %s"
  end
  body = (start_pos..end_pos).map do |current_pos|
    sprintf(fmt, pos == current_pos ? '=>' : '', current_pos + 1, lines[current_pos])
  end.join("")
  "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n"
end

#evaluate(context, statements, file = nil, line = nil) ⇒ Object

Evaluate the context of this workspace and use the Tracer library to output the exact lines of code are being executed in chronological order.

See lib/tracer.rb for more information.


113
114
115
# File 'lib/irb/workspace.rb', line 113

def evaluate(context, statements, file = __FILE__, line = __LINE__)
  eval(statements, @binding, file, line)
end

#filter_backtrace(bt) ⇒ Object

error message manipulator


126
127
128
129
130
131
132
133
134
135
136
# File 'lib/irb/workspace.rb', line 126

def filter_backtrace(bt)
  return nil if bt =~ /\/irb\/.*\.rb/
  return nil if bt =~ /\/irb\.rb/
  case IRB.conf[:CONTEXT_MODE]
  when 1
    return nil if bt =~ %r!/tmp/irb-binding!
  when 3
    bt = bt.sub(/:\s*in `irb_binding'/, '')
  end
  bt
end

#local_variable_get(name) ⇒ Object


121
122
123
# File 'lib/irb/workspace.rb', line 121

def local_variable_get(name)
  @binding.local_variable_get(name)
end

#local_variable_set(name, value) ⇒ Object


117
118
119
# File 'lib/irb/workspace.rb', line 117

def local_variable_set(name, value)
  @binding.local_variable_set(name, value)
end