irb 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +6 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +55 -0
- data/Rakefile +10 -0
- data/bin/console +6 -0
- data/bin/setup +6 -0
- data/exe/irb +11 -0
- data/irb.gemspec +26 -0
- data/lib/irb.rb +798 -0
- data/lib/irb/cmd/chws.rb +34 -0
- data/lib/irb/cmd/fork.rb +39 -0
- data/lib/irb/cmd/help.rb +42 -0
- data/lib/irb/cmd/load.rb +67 -0
- data/lib/irb/cmd/nop.rb +39 -0
- data/lib/irb/cmd/pushws.rb +41 -0
- data/lib/irb/cmd/subirb.rb +43 -0
- data/lib/irb/completion.rb +244 -0
- data/lib/irb/context.rb +425 -0
- data/lib/irb/ext/change-ws.rb +46 -0
- data/lib/irb/ext/history.rb +119 -0
- data/lib/irb/ext/loader.rb +129 -0
- data/lib/irb/ext/multi-irb.rb +265 -0
- data/lib/irb/ext/save-history.rb +105 -0
- data/lib/irb/ext/tracer.rb +72 -0
- data/lib/irb/ext/use-loader.rb +74 -0
- data/lib/irb/ext/workspaces.rb +67 -0
- data/lib/irb/extend-command.rb +306 -0
- data/lib/irb/frame.rb +81 -0
- data/lib/irb/help.rb +37 -0
- data/lib/irb/init.rb +302 -0
- data/lib/irb/input-method.rb +192 -0
- data/lib/irb/inspector.rb +132 -0
- data/lib/irb/lc/.document +4 -0
- data/lib/irb/lc/error.rb +32 -0
- data/lib/irb/lc/help-message +49 -0
- data/lib/irb/lc/ja/encoding_aliases.rb +11 -0
- data/lib/irb/lc/ja/error.rb +31 -0
- data/lib/irb/lc/ja/help-message +52 -0
- data/lib/irb/locale.rb +182 -0
- data/lib/irb/magic-file.rb +38 -0
- data/lib/irb/notifier.rb +232 -0
- data/lib/irb/output-method.rb +92 -0
- data/lib/irb/ruby-lex.rb +1180 -0
- data/lib/irb/ruby-token.rb +267 -0
- data/lib/irb/slex.rb +282 -0
- data/lib/irb/src_encoding.rb +7 -0
- data/lib/irb/version.rb +17 -0
- data/lib/irb/workspace.rb +143 -0
- data/lib/irb/ws-for-case-2.rb +15 -0
- data/lib/irb/xmp.rb +170 -0
- metadata +125 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
#
|
3
|
+
# history.rb -
|
4
|
+
# $Release Version: 0.9.6$
|
5
|
+
# $Revision$
|
6
|
+
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
7
|
+
#
|
8
|
+
# --
|
9
|
+
#
|
10
|
+
#
|
11
|
+
#
|
12
|
+
|
13
|
+
module IRB # :nodoc:
|
14
|
+
|
15
|
+
class Context
|
16
|
+
|
17
|
+
NOPRINTING_IVARS.push "@eval_history_values"
|
18
|
+
|
19
|
+
# See #set_last_value
|
20
|
+
alias _set_last_value set_last_value
|
21
|
+
|
22
|
+
def set_last_value(value)
|
23
|
+
_set_last_value(value)
|
24
|
+
|
25
|
+
if @eval_history
|
26
|
+
@eval_history_values.push @line_no, @last_value
|
27
|
+
@workspace.evaluate self, "__ = IRB.CurrentContext.instance_eval{@eval_history_values}"
|
28
|
+
end
|
29
|
+
|
30
|
+
@last_value
|
31
|
+
end
|
32
|
+
|
33
|
+
# The command result history limit.
|
34
|
+
attr_reader :eval_history
|
35
|
+
# Sets command result history limit.
|
36
|
+
#
|
37
|
+
# +no+ is an Integer or +nil+.
|
38
|
+
#
|
39
|
+
# Returns +no+ of history items if greater than 0.
|
40
|
+
#
|
41
|
+
# If +no+ is 0, the number of history items is unlimited.
|
42
|
+
#
|
43
|
+
# If +no+ is +nil+, execution result history isn't used (default).
|
44
|
+
def eval_history=(no)
|
45
|
+
if no
|
46
|
+
if defined?(@eval_history) && @eval_history
|
47
|
+
@eval_history_values.size(no)
|
48
|
+
else
|
49
|
+
@eval_history_values = History.new(no)
|
50
|
+
IRB.conf[:__TMP__EHV__] = @eval_history_values
|
51
|
+
@workspace.evaluate(self, "__ = IRB.conf[:__TMP__EHV__]")
|
52
|
+
IRB.conf.delete(:__TMP_EHV__)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
@eval_history_values = nil
|
56
|
+
end
|
57
|
+
@eval_history = no
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class History # :nodoc:
|
62
|
+
|
63
|
+
def initialize(size = 16)
|
64
|
+
@size = size
|
65
|
+
@contents = []
|
66
|
+
end
|
67
|
+
|
68
|
+
def size(size)
|
69
|
+
if size != 0 && size < @size
|
70
|
+
@contents = @contents[@size - size .. @size]
|
71
|
+
end
|
72
|
+
@size = size
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](idx)
|
76
|
+
begin
|
77
|
+
if idx >= 0
|
78
|
+
@contents.find{|no, val| no == idx}[1]
|
79
|
+
else
|
80
|
+
@contents[idx][1]
|
81
|
+
end
|
82
|
+
rescue NameError
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def push(no, val)
|
88
|
+
@contents.push [no, val]
|
89
|
+
@contents.shift if @size != 0 && @contents.size > @size
|
90
|
+
end
|
91
|
+
|
92
|
+
alias real_inspect inspect
|
93
|
+
|
94
|
+
def inspect
|
95
|
+
if @contents.empty?
|
96
|
+
return real_inspect
|
97
|
+
end
|
98
|
+
|
99
|
+
unless (last = @contents.pop)[1].equal?(self)
|
100
|
+
@contents.push last
|
101
|
+
last = nil
|
102
|
+
end
|
103
|
+
str = @contents.collect{|no, val|
|
104
|
+
if val.equal?(self)
|
105
|
+
"#{no} ...self-history..."
|
106
|
+
else
|
107
|
+
"#{no} #{val.inspect}"
|
108
|
+
end
|
109
|
+
}.join("\n")
|
110
|
+
if str == ""
|
111
|
+
str = "Empty."
|
112
|
+
end
|
113
|
+
@contents.push last if last
|
114
|
+
str
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
#
|
3
|
+
# loader.rb -
|
4
|
+
# $Release Version: 0.9.6$
|
5
|
+
# $Revision$
|
6
|
+
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
7
|
+
#
|
8
|
+
# --
|
9
|
+
#
|
10
|
+
#
|
11
|
+
#
|
12
|
+
|
13
|
+
|
14
|
+
module IRB # :nodoc:
|
15
|
+
# Raised in the event of an exception in a file loaded from an Irb session
|
16
|
+
class LoadAbort < Exception;end
|
17
|
+
|
18
|
+
# Provides a few commands for loading files within an irb session.
|
19
|
+
#
|
20
|
+
# See ExtendCommandBundle for more information.
|
21
|
+
module IrbLoader
|
22
|
+
|
23
|
+
alias ruby_load load
|
24
|
+
alias ruby_require require
|
25
|
+
|
26
|
+
# Loads the given file similarly to Kernel#load
|
27
|
+
def irb_load(fn, priv = nil)
|
28
|
+
path = search_file_from_ruby_path(fn)
|
29
|
+
raise LoadError, "No such file to load -- #{fn}" unless path
|
30
|
+
|
31
|
+
load_file(path, priv)
|
32
|
+
end
|
33
|
+
|
34
|
+
def search_file_from_ruby_path(fn) # :nodoc:
|
35
|
+
if /^#{Regexp.quote(File::Separator)}/ =~ fn
|
36
|
+
return fn if File.exist?(fn)
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
|
40
|
+
for path in $:
|
41
|
+
if File.exist?(f = File.join(path, fn))
|
42
|
+
return f
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
|
48
|
+
# Loads a given file in the current session and displays the source lines
|
49
|
+
#
|
50
|
+
# See Irb#suspend_input_method for more information.
|
51
|
+
def source_file(path)
|
52
|
+
irb.suspend_name(path, File.basename(path)) do
|
53
|
+
irb.suspend_input_method(FileInputMethod.new(path)) do
|
54
|
+
|back_io|
|
55
|
+
irb.signal_status(:IN_LOAD) do
|
56
|
+
if back_io.kind_of?(FileInputMethod)
|
57
|
+
irb.eval_input
|
58
|
+
else
|
59
|
+
begin
|
60
|
+
irb.eval_input
|
61
|
+
rescue LoadAbort
|
62
|
+
print "load abort!!\n"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Loads the given file in the current session's context and evaluates it.
|
71
|
+
#
|
72
|
+
# See Irb#suspend_input_method for more information.
|
73
|
+
def load_file(path, priv = nil)
|
74
|
+
irb.suspend_name(path, File.basename(path)) do
|
75
|
+
|
76
|
+
if priv
|
77
|
+
ws = WorkSpace.new(Module.new)
|
78
|
+
else
|
79
|
+
ws = WorkSpace.new
|
80
|
+
end
|
81
|
+
irb.suspend_workspace(ws) do
|
82
|
+
irb.suspend_input_method(FileInputMethod.new(path)) do
|
83
|
+
|back_io|
|
84
|
+
irb.signal_status(:IN_LOAD) do
|
85
|
+
if back_io.kind_of?(FileInputMethod)
|
86
|
+
irb.eval_input
|
87
|
+
else
|
88
|
+
begin
|
89
|
+
irb.eval_input
|
90
|
+
rescue LoadAbort
|
91
|
+
print "load abort!!\n"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def old # :nodoc:
|
101
|
+
back_io = @io
|
102
|
+
back_path = @irb_path
|
103
|
+
back_name = @irb_name
|
104
|
+
back_scanner = @irb.scanner
|
105
|
+
begin
|
106
|
+
@io = FileInputMethod.new(path)
|
107
|
+
@irb_name = File.basename(path)
|
108
|
+
@irb_path = path
|
109
|
+
@irb.signal_status(:IN_LOAD) do
|
110
|
+
if back_io.kind_of?(FileInputMethod)
|
111
|
+
@irb.eval_input
|
112
|
+
else
|
113
|
+
begin
|
114
|
+
@irb.eval_input
|
115
|
+
rescue LoadAbort
|
116
|
+
print "load abort!!\n"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
ensure
|
121
|
+
@io = back_io
|
122
|
+
@irb_name = back_name
|
123
|
+
@irb_path = back_path
|
124
|
+
@irb.scanner = back_scanner
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
@@ -0,0 +1,265 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
#
|
3
|
+
# irb/multi-irb.rb - multiple irb module
|
4
|
+
# $Release Version: 0.9.6$
|
5
|
+
# $Revision$
|
6
|
+
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
7
|
+
#
|
8
|
+
# --
|
9
|
+
#
|
10
|
+
#
|
11
|
+
#
|
12
|
+
IRB.fail CantShiftToMultiIrbMode unless defined?(Thread)
|
13
|
+
|
14
|
+
module IRB
|
15
|
+
class JobManager
|
16
|
+
|
17
|
+
# Creates a new JobManager object
|
18
|
+
def initialize
|
19
|
+
@jobs = []
|
20
|
+
@current_job = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
# The active irb session
|
24
|
+
attr_accessor :current_job
|
25
|
+
|
26
|
+
# The total number of irb sessions, used to set +irb_name+ of the current
|
27
|
+
# Context.
|
28
|
+
def n_jobs
|
29
|
+
@jobs.size
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the thread for the given +key+ object, see #search for more
|
33
|
+
# information.
|
34
|
+
def thread(key)
|
35
|
+
th, = search(key)
|
36
|
+
th
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the irb session for the given +key+ object, see #search for more
|
40
|
+
# information.
|
41
|
+
def irb(key)
|
42
|
+
_, irb = search(key)
|
43
|
+
irb
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the top level thread.
|
47
|
+
def main_thread
|
48
|
+
@jobs[0][0]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the top level irb session.
|
52
|
+
def main_irb
|
53
|
+
@jobs[0][1]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Add the given +irb+ session to the jobs Array.
|
57
|
+
def insert(irb)
|
58
|
+
@jobs.push [Thread.current, irb]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Changes the current active irb session to the given +key+ in the jobs
|
62
|
+
# Array.
|
63
|
+
#
|
64
|
+
# Raises an IrbAlreadyDead exception if the given +key+ is no longer alive.
|
65
|
+
#
|
66
|
+
# If the given irb session is already active, an IrbSwitchedToCurrentThread
|
67
|
+
# exception is raised.
|
68
|
+
def switch(key)
|
69
|
+
th, irb = search(key)
|
70
|
+
IRB.fail IrbAlreadyDead unless th.alive?
|
71
|
+
IRB.fail IrbSwitchedToCurrentThread if th == Thread.current
|
72
|
+
@current_job = irb
|
73
|
+
th.run
|
74
|
+
Thread.stop
|
75
|
+
@current_job = irb(Thread.current)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Terminates the irb sessions specified by the given +keys+.
|
79
|
+
#
|
80
|
+
# Raises an IrbAlreadyDead exception if one of the given +keys+ is already
|
81
|
+
# terminated.
|
82
|
+
#
|
83
|
+
# See Thread#exit for more information.
|
84
|
+
def kill(*keys)
|
85
|
+
for key in keys
|
86
|
+
th, _ = search(key)
|
87
|
+
IRB.fail IrbAlreadyDead unless th.alive?
|
88
|
+
th.exit
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the associated job for the given +key+.
|
93
|
+
#
|
94
|
+
# If given an Integer, it will return the +key+ index for the jobs Array.
|
95
|
+
#
|
96
|
+
# When an instance of Irb is given, it will return the irb session
|
97
|
+
# associated with +key+.
|
98
|
+
#
|
99
|
+
# If given an instance of Thread, it will return the associated thread
|
100
|
+
# +key+ using Object#=== on the jobs Array.
|
101
|
+
#
|
102
|
+
# Otherwise returns the irb session with the same top-level binding as the
|
103
|
+
# given +key+.
|
104
|
+
#
|
105
|
+
# Raises a NoSuchJob exception if no job can be found with the given +key+.
|
106
|
+
def search(key)
|
107
|
+
job = case key
|
108
|
+
when Integer
|
109
|
+
@jobs[key]
|
110
|
+
when Irb
|
111
|
+
@jobs.find{|k, v| v.equal?(key)}
|
112
|
+
when Thread
|
113
|
+
@jobs.assoc(key)
|
114
|
+
else
|
115
|
+
@jobs.find{|k, v| v.context.main.equal?(key)}
|
116
|
+
end
|
117
|
+
IRB.fail NoSuchJob, key if job.nil?
|
118
|
+
job
|
119
|
+
end
|
120
|
+
|
121
|
+
# Deletes the job at the given +key+.
|
122
|
+
def delete(key)
|
123
|
+
case key
|
124
|
+
when Integer
|
125
|
+
IRB.fail NoSuchJob, key unless @jobs[key]
|
126
|
+
@jobs[key] = nil
|
127
|
+
else
|
128
|
+
catch(:EXISTS) do
|
129
|
+
@jobs.each_index do
|
130
|
+
|i|
|
131
|
+
if @jobs[i] and (@jobs[i][0] == key ||
|
132
|
+
@jobs[i][1] == key ||
|
133
|
+
@jobs[i][1].context.main.equal?(key))
|
134
|
+
@jobs[i] = nil
|
135
|
+
throw :EXISTS
|
136
|
+
end
|
137
|
+
end
|
138
|
+
IRB.fail NoSuchJob, key
|
139
|
+
end
|
140
|
+
end
|
141
|
+
until assoc = @jobs.pop; end unless @jobs.empty?
|
142
|
+
@jobs.push assoc
|
143
|
+
end
|
144
|
+
|
145
|
+
# Outputs a list of jobs, see the irb command +irb_jobs+, or +jobs+.
|
146
|
+
def inspect
|
147
|
+
ary = []
|
148
|
+
@jobs.each_index do
|
149
|
+
|i|
|
150
|
+
th, irb = @jobs[i]
|
151
|
+
next if th.nil?
|
152
|
+
|
153
|
+
if th.alive?
|
154
|
+
if th.stop?
|
155
|
+
t_status = "stop"
|
156
|
+
else
|
157
|
+
t_status = "running"
|
158
|
+
end
|
159
|
+
else
|
160
|
+
t_status = "exited"
|
161
|
+
end
|
162
|
+
ary.push format("#%d->%s on %s (%s: %s)",
|
163
|
+
i,
|
164
|
+
irb.context.irb_name,
|
165
|
+
irb.context.main,
|
166
|
+
th,
|
167
|
+
t_status)
|
168
|
+
end
|
169
|
+
ary.join("\n")
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
@JobManager = JobManager.new
|
174
|
+
|
175
|
+
# The current JobManager in the session
|
176
|
+
def IRB.JobManager
|
177
|
+
@JobManager
|
178
|
+
end
|
179
|
+
|
180
|
+
# The current Context in this session
|
181
|
+
def IRB.CurrentContext
|
182
|
+
IRB.JobManager.irb(Thread.current).context
|
183
|
+
end
|
184
|
+
|
185
|
+
# Creates a new IRB session, see Irb.new.
|
186
|
+
#
|
187
|
+
# The optional +file+ argument is given to Context.new, along with the
|
188
|
+
# workspace created with the remaining arguments, see WorkSpace.new
|
189
|
+
def IRB.irb(file = nil, *main)
|
190
|
+
workspace = WorkSpace.new(*main)
|
191
|
+
parent_thread = Thread.current
|
192
|
+
Thread.start do
|
193
|
+
begin
|
194
|
+
irb = Irb.new(workspace, file)
|
195
|
+
rescue
|
196
|
+
print "Subirb can't start with context(self): ", workspace.main.inspect, "\n"
|
197
|
+
print "return to main irb\n"
|
198
|
+
Thread.pass
|
199
|
+
Thread.main.wakeup
|
200
|
+
Thread.exit
|
201
|
+
end
|
202
|
+
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
|
203
|
+
@JobManager.insert(irb)
|
204
|
+
@JobManager.current_job = irb
|
205
|
+
begin
|
206
|
+
system_exit = false
|
207
|
+
catch(:IRB_EXIT) do
|
208
|
+
irb.eval_input
|
209
|
+
end
|
210
|
+
rescue SystemExit
|
211
|
+
system_exit = true
|
212
|
+
raise
|
213
|
+
#fail
|
214
|
+
ensure
|
215
|
+
unless system_exit
|
216
|
+
@JobManager.delete(irb)
|
217
|
+
if @JobManager.current_job == irb
|
218
|
+
if parent_thread.alive?
|
219
|
+
@JobManager.current_job = @JobManager.irb(parent_thread)
|
220
|
+
parent_thread.run
|
221
|
+
else
|
222
|
+
@JobManager.current_job = @JobManager.main_irb
|
223
|
+
@JobManager.main_thread.run
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
Thread.stop
|
230
|
+
@JobManager.current_job = @JobManager.irb(Thread.current)
|
231
|
+
end
|
232
|
+
|
233
|
+
@CONF[:SINGLE_IRB_MODE] = false
|
234
|
+
@JobManager.insert(@CONF[:MAIN_CONTEXT].irb)
|
235
|
+
@JobManager.current_job = @CONF[:MAIN_CONTEXT].irb
|
236
|
+
|
237
|
+
class Irb
|
238
|
+
def signal_handle
|
239
|
+
unless @context.ignore_sigint?
|
240
|
+
print "\nabort!!\n" if @context.verbose?
|
241
|
+
exit
|
242
|
+
end
|
243
|
+
|
244
|
+
case @signal_status
|
245
|
+
when :IN_INPUT
|
246
|
+
print "^C\n"
|
247
|
+
IRB.JobManager.thread(self).raise RubyLex::TerminateLineInput
|
248
|
+
when :IN_EVAL
|
249
|
+
IRB.irb_abort(self)
|
250
|
+
when :IN_LOAD
|
251
|
+
IRB.irb_abort(self, LoadAbort)
|
252
|
+
when :IN_IRB
|
253
|
+
# ignore
|
254
|
+
else
|
255
|
+
# ignore other cases as well
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
trap("SIGINT") do
|
261
|
+
@JobManager.current_job.signal_handle
|
262
|
+
Thread.stop
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|