1 | #
|
---|
2 | # irb/multi-irb.rb - multiple irb module
|
---|
3 | # $Release Version: 0.9.5$
|
---|
4 | # $Revision: 11708 $
|
---|
5 | # $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
|
---|
6 | # by Keiju ISHITSUKA([email protected])
|
---|
7 | #
|
---|
8 | # --
|
---|
9 | #
|
---|
10 | #
|
---|
11 | #
|
---|
12 | IRB.fail CantShiftToMultiIrbMode unless defined?(Thread)
|
---|
13 | require "thread"
|
---|
14 |
|
---|
15 | module IRB
|
---|
16 | # job management class
|
---|
17 | class JobManager
|
---|
18 | @RCS_ID='-$Id: multi-irb.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
|
---|
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 IrbSwitchedToCurrentThread 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
|
---|