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
105
106
# 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
      @binding = eval("self.class.remove_method(:irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding",
                      TOPLEVEL_BINDING,
                      __FILE__,
                      __LINE__ - 3)
    when 4  # binding is a copy of TOPLEVEL_BINDING (default)
      @binding = TOPLEVEL_BINDING.dup
    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



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

def binding
  @binding
end

#mainObject (readonly)

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



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

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



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
177
178
179
# File 'lib/irb/workspace.rb', line 141

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 if use_colorize}\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.



115
116
117
# File 'lib/irb/workspace.rb', line 115

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

#filter_backtrace(bt) ⇒ Object

error message manipulator



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

def filter_backtrace(bt)
  return nil if bt =~ /\/irb\/.*\.rb/
  return nil if bt =~ /\/irb\.rb/
  return nil if bt =~ /tool\/lib\/.*\.rb|runner\.rb/ # for tests in Ruby repository
  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



123
124
125
# File 'lib/irb/workspace.rb', line 123

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

#local_variable_set(name, value) ⇒ Object



119
120
121
# File 'lib/irb/workspace.rb', line 119

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