DEFINITIONS
This source file includes following functions.
1 #
2 # irb/multi-irb.rb - multiple irb module
3 # $Release Version: 0.9$
4 # $Revision: 1.1 $
5 # $Date: 2002/07/09 11:17:17 $
6 # by Keiju ISHITSUKA(keiju@ishitsuka.com)
7 #
8 # --
9 #
10 #
11 #
12 IRB.fail CanNotGoMultiIrbMode unless defined?(Thread)
13 require "thread"
14
15 module IRB
16 # job management class
17 class JobManager
18 @RCS_ID='-$Id: multi-irb.rb,v 1.1 2002/07/09 11:17:17 keiju Exp $-'
19
20 def initialize
21 # @jobs = [[thread, irb],...]
22 @jobs = []
23 @current_job = nil
24 end
25
26 attr_accessor :current_job
27
28 def n_jobs
29 @jobs.size
30 end
31
32 def thread(key)
33 th, irb = search(key)
34 th
35 end
36
37 def irb(key)
38 th, irb = search(key)
39 irb
40 end
41
42 def main_thread
43 @jobs[0][0]
44 end
45
46 def main_irb
47 @jobs[0][1]
48 end
49
50 def insert(irb)
51 @jobs.push [Thread.current, irb]
52 end
53
54 def switch(key)
55 th, irb = search(key)
56 IRB.fail IrbAlreadyDead unless th.alive?
57 IRB.fail IrbSwitchToCurrentThread if th == Thread.current
58 @current_job = irb
59 th.run
60 Thread.stop
61 @current_job = irb(Thread.current)
62 end
63
64 def kill(*keys)
65 for key in keys
66 th, irb = search(key)
67 IRB.fail IrbAlreadyDead unless th.alive?
68 th.exit
69 end
70 end
71
72 def search(key)
73 case key
74 when Integer
75 @jobs[key]
76 when Irb
77 @jobs.find{|k, v| v.equal?(key)}
78 when Thread
79 @jobs.assoc(key)
80 else
81 assoc = @jobs.find{|k, v| v.context.main.equal?(key)}
82 IRB.fail NoSuchJob, key if assoc.nil?
83 assoc
84 end
85 end
86
87 def delete(key)
88 case key
89 when Integer
90 IRB.fail NoSuchJob, key unless @jobs[key]
91 @jobs[key] = nil
92 else
93 catch(:EXISTS) do
94 @jobs.each_index do
95 |i|
96 if @jobs[i] and (@jobs[i][0] == key ||
97 @jobs[i][1] == key ||
98 @jobs[i][1].context.main.equal?(key))
99 @jobs[i] = nil
100 throw :EXISTS
101 end
102 end
103 IRB.fail NoSuchJob, key
104 end
105 end
106 until assoc = @jobs.pop; end unless @jobs.empty?
107 @jobs.push assoc
108 end
109
110 def inspect
111 ary = []
112 @jobs.each_index do
113 |i|
114 th, irb = @jobs[i]
115 next if th.nil?
116
117 if th.alive?
118 if th.stop?
119 t_status = "stop"
120 else
121 t_status = "running"
122 end
123 else
124 t_status = "exited"
125 end
126 ary.push format("#%d->%s on %s (%s: %s)",
127 i,
128 irb.context.irb_name,
129 irb.context.main,
130 th,
131 t_status)
132 end
133 ary.join("\n")
134 end
135 end
136
137 @JobManager = JobManager.new
138
139 def IRB.JobManager
140 @JobManager
141 end
142
143 def IRB.CurrentContext
144 IRB.JobManager.irb(Thread.current).context
145 end
146
147 # invoke multi-irb
148 def IRB.irb(file = nil, *main)
149 workspace = WorkSpace.new(*main)
150 parent_thread = Thread.current
151 Thread.start do
152 begin
153 irb = Irb.new(workspace, file)
154 rescue
155 print "Subirb can't start with context(self): ", workspace.main.inspect, "\n"
156 print "return to main irb\n"
157 Thread.pass
158 Thread.main.wakeup
159 Thread.exit
160 end
161 @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
162 @JobManager.insert(irb)
163 @JobManager.current_job = irb
164 begin
165 system_exit = false
166 catch(:IRB_EXIT) do
167 irb.eval_input
168 end
169 rescue SystemExit
170 system_exit = true
171 raise
172 #fail
173 ensure
174 unless system_exit
175 @JobManager.delete(irb)
176 if parent_thread.alive?
177 @JobManager.current_job = @JobManager.irb(parent_thread)
178 parent_thread.run
179 else
180 @JobManager.current_job = @JobManager.main_irb
181 @JobManager.main_thread.run
182 end
183 end
184 end
185 end
186 Thread.stop
187 @JobManager.current_job = @JobManager.irb(Thread.current)
188 end
189
190 # class Context
191 # def set_last_value(value)
192 # @last_value = value
193 # @workspace.evaluate "_ = IRB.JobManager.irb(Thread.current).context.last_value"
194 # if @eval_history #and !@__.equal?(@last_value)
195 # @eval_history_values.push @line_no, @last_value
196 # @workspace.evaluate "__ = IRB.JobManager.irb(Thread.current).context.instance_eval{@eval_history_values}"
197 # end
198 # @last_value
199 # end
200 # end
201
202 # module ExtendCommand
203 # def irb_context
204 # IRB.JobManager.irb(Thread.current).context
205 # end
206 # # alias conf irb_context
207 # end
208
209 @CONF[:SINGLE_IRB_MODE] = false
210 @JobManager.insert(@CONF[:MAIN_CONTEXT].irb)
211 @JobManager.current_job = @CONF[:MAIN_CONTEXT].irb
212
213 class Irb
214 def signal_handle
215 unless @context.ignore_sigint?
216 print "\nabort!!\n" if @context.verbose?
217 exit
218 end
219
220 case @signal_status
221 when :IN_INPUT
222 print "^C\n"
223 IRB.JobManager.thread(self).raise RubyLex::TerminateLineInput
224 when :IN_EVAL
225 IRB.irb_abort(self)
226 when :IN_LOAD
227 IRB.irb_abort(self, LoadAbort)
228 when :IN_IRB
229 # ignore
230 else
231 # ignore other cases as well
232 end
233 end
234 end
235
236 trap("SIGINT") do
237 @JobManager.current_job.signal_handle
238 Thread.stop
239 end
240
241 end