irb 1.8.0 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/irb.gemspec +2 -2
- data/lib/irb/cmd/show_source.rb +11 -6
- data/lib/irb/completion.rb +89 -117
- data/lib/irb/debug/ui.rb +2 -3
- data/lib/irb/debug.rb +2 -5
- data/lib/irb/history.rb +3 -1
- data/lib/irb/input-method.rb +132 -81
- data/lib/irb/ruby-lex.rb +14 -41
- data/lib/irb/source_finder.rb +2 -2
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +52 -47
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 811c1b4343957dac57d58178adbc13195e6d53de980f63810ec83eec09d1f8c1
|
4
|
+
data.tar.gz: bbc99d3f46a8e7afa6a7a8e32dc137300e3da15935631e05a56b203a901887fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76b770cf0a8012031f11306cc96879173d819cbd0501efdd41c434571028c3dee8bc12b5928696232d61215f6e22ecec3b9a6e3ff93e085349282c035c9389ec
|
7
|
+
data.tar.gz: f48e1f3912d5bb59acfa041718014dafb24d7f39ac23e1f0b267047ca4e4f937af77bdb0d40a940813da71f5920f53b5bbdc987b9dc50d16e5bdb85a754e02b7
|
data/README.md
CHANGED
@@ -150,7 +150,7 @@ Context
|
|
150
150
|
|
151
151
|
Starting from version 1.8.0, IRB boasts a powerful integration with `debug.gem`, providing a debugging experience akin to `pry-byebug`.
|
152
152
|
|
153
|
-
After hitting a `binding.irb` breakpoint, you can activate the debugger with the `debug` command.
|
153
|
+
After hitting a `binding.irb` breakpoint, you can activate the debugger with the `debug` command. Alternatively, if the `debug` method happens to already be defined in the current scope, you can call `irb_debug`.
|
154
154
|
|
155
155
|
```shell
|
156
156
|
From: test.rb @ line 3 :
|
data/irb.gemspec
CHANGED
@@ -41,6 +41,6 @@ Gem::Specification.new do |spec|
|
|
41
41
|
|
42
42
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.7")
|
43
43
|
|
44
|
-
spec.add_dependency "reline", ">= 0.3.
|
45
|
-
spec.add_dependency "rdoc"
|
44
|
+
spec.add_dependency "reline", ">= 0.3.8"
|
45
|
+
spec.add_dependency "rdoc"
|
46
46
|
end
|
data/lib/irb/cmd/show_source.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative "nop"
|
4
4
|
require_relative "../source_finder"
|
5
|
+
require_relative "../pager"
|
5
6
|
require_relative "../color"
|
6
7
|
|
7
8
|
module IRB
|
@@ -40,12 +41,16 @@ module IRB
|
|
40
41
|
private
|
41
42
|
|
42
43
|
def show_source(source)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
file_content = IRB::Color.colorize_code(File.read(source.file))
|
45
|
+
code = file_content.lines[(source.first_line - 1)...source.last_line].join
|
46
|
+
content = <<~CONTENT
|
47
|
+
|
48
|
+
#{bold("From")}: #{source.file}:#{source.first_line}
|
49
|
+
|
50
|
+
#{code}
|
51
|
+
CONTENT
|
52
|
+
|
53
|
+
Pager.page_content(content)
|
49
54
|
end
|
50
55
|
|
51
56
|
def bold(str)
|
data/lib/irb/completion.rb
CHANGED
@@ -8,55 +8,14 @@
|
|
8
8
|
require_relative 'ruby-lex'
|
9
9
|
|
10
10
|
module IRB
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
::Kernel.instance_method(:methods).bind(eval("self")).call
|
16
|
-
end
|
17
|
-
|
18
|
-
def eval_private_methods
|
19
|
-
::Kernel.instance_method(:private_methods).bind(eval("self")).call
|
20
|
-
end
|
21
|
-
|
22
|
-
def eval_instance_variables
|
23
|
-
::Kernel.instance_method(:instance_variables).bind(eval("self")).call
|
24
|
-
end
|
25
|
-
|
26
|
-
def eval_global_variables
|
27
|
-
::Kernel.instance_method(:global_variables).bind(eval("self")).call
|
28
|
-
end
|
29
|
-
|
30
|
-
def eval_class_constants
|
31
|
-
::Module.instance_method(:constants).bind(eval("self.class")).call
|
32
|
-
end
|
33
|
-
end
|
34
|
-
}
|
35
|
-
|
36
|
-
# Set of reserved words used by Ruby, you should not use these for
|
37
|
-
# constants or variables
|
38
|
-
ReservedWords = %w[
|
39
|
-
__ENCODING__ __LINE__ __FILE__
|
40
|
-
BEGIN END
|
41
|
-
alias and
|
42
|
-
begin break
|
43
|
-
case class
|
44
|
-
def defined? do
|
45
|
-
else elsif end ensure
|
46
|
-
false for
|
47
|
-
if in
|
48
|
-
module
|
49
|
-
next nil not
|
50
|
-
or
|
51
|
-
redo rescue retry return
|
52
|
-
self super
|
53
|
-
then true
|
54
|
-
undef unless until
|
55
|
-
when while
|
56
|
-
yield
|
57
|
-
]
|
11
|
+
class BaseCompletor # :nodoc:
|
12
|
+
def completion_candidates(preposing, target, postposing, bind:)
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
58
15
|
|
59
|
-
|
16
|
+
def doc_namespace(preposing, matched, postposing, bind:)
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
60
19
|
|
61
20
|
GEM_PATHS =
|
62
21
|
if defined?(Gem::Specification)
|
@@ -73,7 +32,7 @@ module IRB
|
|
73
32
|
[]
|
74
33
|
end.freeze
|
75
34
|
|
76
|
-
def
|
35
|
+
def retrieve_gem_and_system_load_path
|
77
36
|
candidates = (GEM_PATHS | $LOAD_PATH)
|
78
37
|
candidates.map do |p|
|
79
38
|
if p.respond_to?(:to_path)
|
@@ -84,8 +43,8 @@ module IRB
|
|
84
43
|
end.compact.sort
|
85
44
|
end
|
86
45
|
|
87
|
-
def
|
88
|
-
|
46
|
+
def retrieve_files_to_require_from_load_path
|
47
|
+
@files_from_load_path ||=
|
89
48
|
(
|
90
49
|
shortest = []
|
91
50
|
rest = retrieve_gem_and_system_load_path.each_with_object([]) { |path, result|
|
@@ -103,13 +62,62 @@ module IRB
|
|
103
62
|
)
|
104
63
|
end
|
105
64
|
|
106
|
-
def
|
107
|
-
|
65
|
+
def retrieve_files_to_require_relative_from_current_dir
|
66
|
+
@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
|
108
67
|
path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
|
109
68
|
}
|
110
69
|
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class RegexpCompletor < BaseCompletor # :nodoc:
|
73
|
+
using Module.new {
|
74
|
+
refine ::Binding do
|
75
|
+
def eval_methods
|
76
|
+
::Kernel.instance_method(:methods).bind(eval("self")).call
|
77
|
+
end
|
78
|
+
|
79
|
+
def eval_private_methods
|
80
|
+
::Kernel.instance_method(:private_methods).bind(eval("self")).call
|
81
|
+
end
|
82
|
+
|
83
|
+
def eval_instance_variables
|
84
|
+
::Kernel.instance_method(:instance_variables).bind(eval("self")).call
|
85
|
+
end
|
86
|
+
|
87
|
+
def eval_global_variables
|
88
|
+
::Kernel.instance_method(:global_variables).bind(eval("self")).call
|
89
|
+
end
|
90
|
+
|
91
|
+
def eval_class_constants
|
92
|
+
::Module.instance_method(:constants).bind(eval("self.class")).call
|
93
|
+
end
|
94
|
+
end
|
95
|
+
}
|
111
96
|
|
112
|
-
|
97
|
+
# Set of reserved words used by Ruby, you should not use these for
|
98
|
+
# constants or variables
|
99
|
+
ReservedWords = %w[
|
100
|
+
__ENCODING__ __LINE__ __FILE__
|
101
|
+
BEGIN END
|
102
|
+
alias and
|
103
|
+
begin break
|
104
|
+
case class
|
105
|
+
def defined? do
|
106
|
+
else elsif end ensure
|
107
|
+
false for
|
108
|
+
if in
|
109
|
+
module
|
110
|
+
next nil not
|
111
|
+
or
|
112
|
+
redo rescue retry return
|
113
|
+
self super
|
114
|
+
then true
|
115
|
+
undef unless until
|
116
|
+
when while
|
117
|
+
yield
|
118
|
+
]
|
119
|
+
|
120
|
+
def complete_require_path(target, preposing, postposing)
|
113
121
|
if target =~ /\A(['"])([^'"]+)\Z/
|
114
122
|
quote = $1
|
115
123
|
actual_target = $2
|
@@ -124,39 +132,37 @@ module IRB
|
|
124
132
|
break
|
125
133
|
end
|
126
134
|
end
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
end
|
135
|
+
return unless tok&.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
|
136
|
+
|
137
|
+
case tok.tok
|
138
|
+
when 'require'
|
139
|
+
retrieve_files_to_require_from_load_path.select { |path|
|
140
|
+
path.start_with?(actual_target)
|
141
|
+
}.map { |path|
|
142
|
+
quote + path
|
143
|
+
}
|
144
|
+
when 'require_relative'
|
145
|
+
retrieve_files_to_require_relative_from_current_dir.select { |path|
|
146
|
+
path.start_with?(actual_target)
|
147
|
+
}.map { |path|
|
148
|
+
quote + path
|
149
|
+
}
|
143
150
|
end
|
144
|
-
|
145
|
-
}
|
151
|
+
end
|
146
152
|
|
147
|
-
|
153
|
+
def completion_candidates(preposing, target, postposing, bind:)
|
148
154
|
if preposing && postposing
|
149
|
-
result =
|
150
|
-
|
151
|
-
result = retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
|
152
|
-
end
|
153
|
-
result
|
154
|
-
else
|
155
|
-
retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
|
155
|
+
result = complete_require_path(target, preposing, postposing)
|
156
|
+
return result if result
|
156
157
|
end
|
157
|
-
|
158
|
+
retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
|
159
|
+
end
|
160
|
+
|
161
|
+
def doc_namespace(_preposing, matched, _postposing, bind:)
|
162
|
+
retrieve_completion_data(matched, bind: bind, doc_namespace: true)
|
163
|
+
end
|
158
164
|
|
159
|
-
def
|
165
|
+
def retrieve_completion_data(input, bind:, doc_namespace:)
|
160
166
|
case input
|
161
167
|
# this regexp only matches the closing character because of irb's Reline.completer_quote_characters setting
|
162
168
|
# details are described in: https://github.com/ruby/irb/pull/523
|
@@ -394,44 +400,10 @@ module IRB
|
|
394
400
|
end
|
395
401
|
end
|
396
402
|
|
397
|
-
PerfectMatchedProc = ->(matched, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding) {
|
398
|
-
begin
|
399
|
-
require 'rdoc'
|
400
|
-
rescue LoadError
|
401
|
-
return
|
402
|
-
end
|
403
|
-
|
404
|
-
RDocRIDriver ||= RDoc::RI::Driver.new
|
405
|
-
|
406
|
-
if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
|
407
|
-
IRB.__send__(:easter_egg)
|
408
|
-
return
|
409
|
-
end
|
410
|
-
|
411
|
-
namespace = retrieve_completion_data(matched, bind: bind, doc_namespace: true)
|
412
|
-
return unless namespace
|
413
|
-
|
414
|
-
if namespace.is_a?(Array)
|
415
|
-
out = RDoc::Markup::Document.new
|
416
|
-
namespace.each do |m|
|
417
|
-
begin
|
418
|
-
RDocRIDriver.add_method(out, m)
|
419
|
-
rescue RDoc::RI::Driver::NotFoundError
|
420
|
-
end
|
421
|
-
end
|
422
|
-
RDocRIDriver.display(out)
|
423
|
-
else
|
424
|
-
begin
|
425
|
-
RDocRIDriver.display_names([namespace])
|
426
|
-
rescue RDoc::RI::Driver::NotFoundError
|
427
|
-
end
|
428
|
-
end
|
429
|
-
}
|
430
|
-
|
431
403
|
# Set of available operators in Ruby
|
432
404
|
Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
|
433
405
|
|
434
|
-
def
|
406
|
+
def select_message(receiver, message, candidates, sep = ".")
|
435
407
|
candidates.grep(/^#{Regexp.quote(message)}/).collect do |e|
|
436
408
|
case e
|
437
409
|
when /^[a-zA-Z_]/
|
data/lib/irb/debug/ui.rb
CHANGED
@@ -4,8 +4,7 @@ require 'debug/console'
|
|
4
4
|
module IRB
|
5
5
|
module Debug
|
6
6
|
class UI < DEBUGGER__::UI_Base
|
7
|
-
def initialize(
|
8
|
-
@thread = thread
|
7
|
+
def initialize(irb)
|
9
8
|
@irb = irb
|
10
9
|
end
|
11
10
|
|
@@ -56,7 +55,7 @@ module IRB
|
|
56
55
|
|
57
56
|
def readline _
|
58
57
|
setup_interrupt do
|
59
|
-
tc = DEBUGGER__::SESSION.
|
58
|
+
tc = DEBUGGER__::SESSION.instance_variable_get(:@tc)
|
60
59
|
cmd = @irb.debug_readline(tc.current_frame.binding || TOPLEVEL_BINDING)
|
61
60
|
|
62
61
|
case cmd
|
data/lib/irb/debug.rb
CHANGED
@@ -32,17 +32,14 @@ module IRB
|
|
32
32
|
end
|
33
33
|
DEBUGGER__::CONFIG.set_config
|
34
34
|
configure_irb_for_debugger(irb)
|
35
|
-
thread = Thread.current
|
36
35
|
|
37
|
-
DEBUGGER__.initialize_session{ IRB::Debug::UI.new(
|
36
|
+
DEBUGGER__.initialize_session{ IRB::Debug::UI.new(irb) }
|
38
37
|
end
|
39
38
|
|
40
39
|
# When debug session was previously started but not by IRB
|
41
40
|
if defined?(DEBUGGER__::SESSION) && !irb.context.with_debugger
|
42
41
|
configure_irb_for_debugger(irb)
|
43
|
-
|
44
|
-
|
45
|
-
DEBUGGER__::SESSION.reset_ui(IRB::Debug::UI.new(thread, irb))
|
42
|
+
DEBUGGER__::SESSION.reset_ui(IRB::Debug::UI.new(irb))
|
46
43
|
end
|
47
44
|
|
48
45
|
# Apply patches to debug gem so it skips IRB frames
|
data/lib/irb/history.rb
CHANGED
@@ -10,6 +10,7 @@ module IRB
|
|
10
10
|
|
11
11
|
def load_history
|
12
12
|
history = self.class::HISTORY
|
13
|
+
|
13
14
|
if history_file = IRB.conf[:HISTORY_FILE]
|
14
15
|
history_file = File.expand_path(history_file)
|
15
16
|
end
|
@@ -32,7 +33,8 @@ module IRB
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def save_history
|
35
|
-
history = self.class::HISTORY
|
36
|
+
history = self.class::HISTORY.to_a
|
37
|
+
|
36
38
|
if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) != 0
|
37
39
|
if history_file = IRB.conf[:HISTORY_FILE]
|
38
40
|
history_file = File.expand_path(history_file)
|
data/lib/irb/input-method.rb
CHANGED
@@ -11,6 +11,8 @@ require 'reline'
|
|
11
11
|
|
12
12
|
module IRB
|
13
13
|
class InputMethod
|
14
|
+
BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
|
15
|
+
|
14
16
|
# The irb prompt associated with this input method
|
15
17
|
attr_accessor :prompt
|
16
18
|
|
@@ -179,12 +181,16 @@ module IRB
|
|
179
181
|
super
|
180
182
|
|
181
183
|
@eof = false
|
184
|
+
@completor = RegexpCompletor.new
|
182
185
|
|
183
186
|
if Readline.respond_to?("basic_word_break_characters=")
|
184
|
-
Readline.basic_word_break_characters =
|
187
|
+
Readline.basic_word_break_characters = BASIC_WORD_BREAK_CHARACTERS
|
185
188
|
end
|
186
189
|
Readline.completion_append_character = nil
|
187
|
-
Readline.completion_proc =
|
190
|
+
Readline.completion_proc = ->(target) {
|
191
|
+
bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
|
192
|
+
@completor.completion_candidates('', target, '', bind: bind)
|
193
|
+
}
|
188
194
|
end
|
189
195
|
|
190
196
|
# Reads the next line from this input method.
|
@@ -230,11 +236,16 @@ module IRB
|
|
230
236
|
super
|
231
237
|
|
232
238
|
@eof = false
|
239
|
+
@completor = RegexpCompletor.new
|
233
240
|
|
234
|
-
Reline.basic_word_break_characters =
|
241
|
+
Reline.basic_word_break_characters = BASIC_WORD_BREAK_CHARACTERS
|
235
242
|
Reline.completion_append_character = nil
|
236
243
|
Reline.completer_quote_characters = ''
|
237
|
-
Reline.completion_proc =
|
244
|
+
Reline.completion_proc = ->(target, preposing, postposing) {
|
245
|
+
bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
|
246
|
+
@completion_params = [preposing, target, postposing, bind]
|
247
|
+
@completor.completion_candidates(preposing, target, postposing, bind: bind)
|
248
|
+
}
|
238
249
|
Reline.output_modifier_proc =
|
239
250
|
if IRB.conf[:USE_COLORIZE]
|
240
251
|
proc do |output, complete: |
|
@@ -247,13 +258,13 @@ module IRB
|
|
247
258
|
Reline::Unicode.escape_for_print(output)
|
248
259
|
end
|
249
260
|
end
|
250
|
-
Reline.dig_perfect_match_proc =
|
261
|
+
Reline.dig_perfect_match_proc = ->(matched) { display_document(matched) }
|
251
262
|
Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
|
252
263
|
|
253
264
|
if IRB.conf[:USE_AUTOCOMPLETE]
|
254
265
|
begin
|
255
266
|
require 'rdoc'
|
256
|
-
Reline.add_dialog_proc(:show_doc,
|
267
|
+
Reline.add_dialog_proc(:show_doc, show_doc_dialog_proc, Reline::DEFAULT_DIALOG_CONTEXT)
|
257
268
|
rescue LoadError
|
258
269
|
end
|
259
270
|
end
|
@@ -271,100 +282,140 @@ module IRB
|
|
271
282
|
@auto_indent_proc = block
|
272
283
|
end
|
273
284
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
285
|
+
def show_doc_dialog_proc
|
286
|
+
doc_namespace = ->(matched) {
|
287
|
+
preposing, _target, postposing, bind = @completion_params
|
288
|
+
@completor.doc_namespace(preposing, matched, postposing, bind: bind)
|
289
|
+
}
|
290
|
+
->() {
|
291
|
+
dialog.trap_key = nil
|
292
|
+
alt_d = [
|
293
|
+
[Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d.
|
294
|
+
[27, 100], # Normal Alt+d when convert-meta isn't used.
|
295
|
+
[195, 164], # The "ä" that appears when Alt+d is pressed on xterm.
|
296
|
+
[226, 136, 130] # The "∂" that appears when Alt+d in pressed on iTerm2.
|
297
|
+
]
|
298
|
+
|
299
|
+
if just_cursor_moving and completion_journey_data.nil?
|
300
|
+
return nil
|
301
|
+
end
|
302
|
+
cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4)
|
303
|
+
return nil if result.nil? or pointer.nil? or pointer < 0
|
282
304
|
|
283
|
-
|
284
|
-
return nil
|
285
|
-
end
|
286
|
-
cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4)
|
287
|
-
return nil if result.nil? or pointer.nil? or pointer < 0
|
288
|
-
name = result[pointer]
|
289
|
-
name = IRB::InputCompletor.retrieve_completion_data(name, doc_namespace: true)
|
305
|
+
name = doc_namespace.call(result[pointer])
|
290
306
|
|
291
|
-
|
292
|
-
|
293
|
-
|
307
|
+
options = {}
|
308
|
+
options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
|
309
|
+
driver = RDoc::RI::Driver.new(options)
|
294
310
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
311
|
+
if key.match?(dialog.name)
|
312
|
+
begin
|
313
|
+
driver.display_names([name])
|
314
|
+
rescue RDoc::RI::Driver::NotFoundError
|
315
|
+
end
|
299
316
|
end
|
300
|
-
end
|
301
317
|
|
302
|
-
begin
|
303
|
-
name = driver.expand_name(name)
|
304
|
-
rescue RDoc::RI::Driver::NotFoundError
|
305
|
-
return nil
|
306
|
-
rescue
|
307
|
-
return nil # unknown error
|
308
|
-
end
|
309
|
-
doc = nil
|
310
|
-
used_for_class = false
|
311
|
-
if not name =~ /#|\./
|
312
|
-
found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
|
313
|
-
if not found.empty?
|
314
|
-
doc = driver.class_document(name, found, klasses, includes, extends)
|
315
|
-
used_for_class = true
|
316
|
-
end
|
317
|
-
end
|
318
|
-
unless used_for_class
|
319
|
-
doc = RDoc::Markup::Document.new
|
320
318
|
begin
|
321
|
-
driver.
|
319
|
+
name = driver.expand_name(name)
|
322
320
|
rescue RDoc::RI::Driver::NotFoundError
|
323
|
-
|
321
|
+
return nil
|
324
322
|
rescue
|
325
323
|
return nil # unknown error
|
326
324
|
end
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
325
|
+
doc = nil
|
326
|
+
used_for_class = false
|
327
|
+
if not name =~ /#|\./
|
328
|
+
found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
|
329
|
+
if not found.empty?
|
330
|
+
doc = driver.class_document(name, found, klasses, includes, extends)
|
331
|
+
used_for_class = true
|
332
|
+
end
|
333
|
+
end
|
334
|
+
unless used_for_class
|
335
|
+
doc = RDoc::Markup::Document.new
|
336
|
+
begin
|
337
|
+
driver.add_method(doc, name)
|
338
|
+
rescue RDoc::RI::Driver::NotFoundError
|
339
|
+
doc = nil
|
340
|
+
rescue
|
341
|
+
return nil # unknown error
|
342
|
+
end
|
343
|
+
end
|
344
|
+
return nil if doc.nil?
|
345
|
+
width = 40
|
346
|
+
|
347
|
+
right_x = cursor_pos_to_render.x + autocomplete_dialog.width
|
348
|
+
if right_x + width > screen_width
|
349
|
+
right_width = screen_width - (right_x + 1)
|
350
|
+
left_x = autocomplete_dialog.column - width
|
351
|
+
left_x = 0 if left_x < 0
|
352
|
+
left_width = width > autocomplete_dialog.column ? autocomplete_dialog.column : width
|
353
|
+
if right_width.positive? and left_width.positive?
|
354
|
+
if right_width >= left_width
|
355
|
+
width = right_width
|
356
|
+
x = right_x
|
357
|
+
else
|
358
|
+
width = left_width
|
359
|
+
x = left_x
|
360
|
+
end
|
361
|
+
elsif right_width.positive? and left_width <= 0
|
339
362
|
width = right_width
|
340
363
|
x = right_x
|
341
|
-
|
364
|
+
elsif right_width <= 0 and left_width.positive?
|
342
365
|
width = left_width
|
343
366
|
x = left_x
|
367
|
+
else # Both are negative width.
|
368
|
+
return nil
|
344
369
|
end
|
345
|
-
|
346
|
-
width = right_width
|
370
|
+
else
|
347
371
|
x = right_x
|
348
|
-
elsif right_width <= 0 and left_width.positive?
|
349
|
-
width = left_width
|
350
|
-
x = left_x
|
351
|
-
else # Both are negative width.
|
352
|
-
return nil
|
353
372
|
end
|
373
|
+
formatter = RDoc::Markup::ToAnsi.new
|
374
|
+
formatter.width = width
|
375
|
+
dialog.trap_key = alt_d
|
376
|
+
mod_key = RUBY_PLATFORM.match?(/darwin/) ? "Option" : "Alt"
|
377
|
+
message = "Press #{mod_key}+d to read the full document"
|
378
|
+
contents = [message] + doc.accept(formatter).split("\n")
|
379
|
+
contents = contents.take(preferred_dialog_height)
|
380
|
+
|
381
|
+
y = cursor_pos_to_render.y
|
382
|
+
Reline::DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
|
383
|
+
}
|
384
|
+
end
|
385
|
+
|
386
|
+
def display_document(matched, driver: nil)
|
387
|
+
begin
|
388
|
+
require 'rdoc'
|
389
|
+
rescue LoadError
|
390
|
+
return
|
391
|
+
end
|
392
|
+
|
393
|
+
if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
|
394
|
+
IRB.__send__(:easter_egg)
|
395
|
+
return
|
396
|
+
end
|
397
|
+
|
398
|
+
_target, preposing, postposing, bind = @completion_params
|
399
|
+
namespace = @completor.doc_namespace(preposing, matched, postposing, bind: bind)
|
400
|
+
return unless namespace
|
401
|
+
|
402
|
+
driver ||= RDoc::RI::Driver.new
|
403
|
+
if namespace.is_a?(Array)
|
404
|
+
out = RDoc::Markup::Document.new
|
405
|
+
namespace.each do |m|
|
406
|
+
begin
|
407
|
+
driver.add_method(out, m)
|
408
|
+
rescue RDoc::RI::Driver::NotFoundError
|
409
|
+
end
|
410
|
+
end
|
411
|
+
driver.display(out)
|
354
412
|
else
|
355
|
-
|
413
|
+
begin
|
414
|
+
driver.display_names([namespace])
|
415
|
+
rescue RDoc::RI::Driver::NotFoundError
|
416
|
+
end
|
356
417
|
end
|
357
|
-
|
358
|
-
formatter.width = width
|
359
|
-
dialog.trap_key = alt_d
|
360
|
-
mod_key = RUBY_PLATFORM.match?(/darwin/) ? "Option" : "Alt"
|
361
|
-
message = "Press #{mod_key}+d to read the full document"
|
362
|
-
contents = [message] + doc.accept(formatter).split("\n")
|
363
|
-
contents = contents.take(preferred_dialog_height)
|
364
|
-
|
365
|
-
y = cursor_pos_to_render.y
|
366
|
-
Reline::DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
|
367
|
-
}
|
418
|
+
end
|
368
419
|
|
369
420
|
# Reads the next line from this input method.
|
370
421
|
#
|
data/lib/irb/ruby-lex.rb
CHANGED
@@ -42,14 +42,6 @@ module IRB
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
attr_reader :line_no
|
46
|
-
|
47
|
-
def initialize(context)
|
48
|
-
@context = context
|
49
|
-
@line_no = 1
|
50
|
-
@prompt = nil
|
51
|
-
end
|
52
|
-
|
53
45
|
def self.compile_with_errors_suppressed(code, line_no: 1)
|
54
46
|
begin
|
55
47
|
result = yield code, line_no
|
@@ -67,10 +59,6 @@ module IRB
|
|
67
59
|
result
|
68
60
|
end
|
69
61
|
|
70
|
-
def set_prompt(&block)
|
71
|
-
@prompt = block
|
72
|
-
end
|
73
|
-
|
74
62
|
ERROR_TOKENS = [
|
75
63
|
:on_parse_error,
|
76
64
|
:compile_error,
|
@@ -116,9 +104,9 @@ module IRB
|
|
116
104
|
interpolated
|
117
105
|
end
|
118
106
|
|
119
|
-
def self.ripper_lex_without_warning(code,
|
107
|
+
def self.ripper_lex_without_warning(code, local_variables: [])
|
120
108
|
verbose, $VERBOSE = $VERBOSE, nil
|
121
|
-
lvars_code = generate_local_variables_assign_code(
|
109
|
+
lvars_code = generate_local_variables_assign_code(local_variables)
|
122
110
|
original_code = code
|
123
111
|
if lvars_code
|
124
112
|
code = "#{lvars_code}\n#{code}"
|
@@ -146,20 +134,14 @@ module IRB
|
|
146
134
|
$VERBOSE = verbose
|
147
135
|
end
|
148
136
|
|
149
|
-
def
|
150
|
-
|
151
|
-
indent_level = calc_indent_level(opens)
|
152
|
-
@prompt&.call(ltype, indent_level, opens.any? || continue, @line_no + line_num_offset)
|
153
|
-
end
|
154
|
-
|
155
|
-
def check_code_state(code)
|
156
|
-
tokens = self.class.ripper_lex_without_warning(code, context: @context)
|
137
|
+
def check_code_state(code, local_variables:)
|
138
|
+
tokens = self.class.ripper_lex_without_warning(code, local_variables: local_variables)
|
157
139
|
opens = NestingParser.open_tokens(tokens)
|
158
|
-
[tokens, opens, code_terminated?(code, tokens, opens)]
|
140
|
+
[tokens, opens, code_terminated?(code, tokens, opens, local_variables: local_variables)]
|
159
141
|
end
|
160
142
|
|
161
|
-
def code_terminated?(code, tokens, opens)
|
162
|
-
case check_code_syntax(code)
|
143
|
+
def code_terminated?(code, tokens, opens, local_variables:)
|
144
|
+
case check_code_syntax(code, local_variables: local_variables)
|
163
145
|
when :unrecoverable_error
|
164
146
|
true
|
165
147
|
when :recoverable_error
|
@@ -171,16 +153,7 @@ module IRB
|
|
171
153
|
end
|
172
154
|
end
|
173
155
|
|
174
|
-
def
|
175
|
-
# Implicitly saves prompt string to `@context.io.prompt`. This will be used in the next `@input.call`.
|
176
|
-
prompt(opens, continue, line_num_offset)
|
177
|
-
end
|
178
|
-
|
179
|
-
def increase_line_no(addition)
|
180
|
-
@line_no += addition
|
181
|
-
end
|
182
|
-
|
183
|
-
def assignment_expression?(code)
|
156
|
+
def assignment_expression?(code, local_variables:)
|
184
157
|
# Try to parse the code and check if the last of possibly multiple
|
185
158
|
# expressions is an assignment type.
|
186
159
|
|
@@ -190,7 +163,7 @@ module IRB
|
|
190
163
|
# array of parsed expressions. The first element of each expression is the
|
191
164
|
# expression's type.
|
192
165
|
verbose, $VERBOSE = $VERBOSE, nil
|
193
|
-
code = "#{RubyLex.generate_local_variables_assign_code(
|
166
|
+
code = "#{RubyLex.generate_local_variables_assign_code(local_variables) || 'nil;'}\n#{code}"
|
194
167
|
# Get the last node_type of the line. drop(1) is to ignore the local_variables_assign_code part.
|
195
168
|
node_type = Ripper.sexp(code)&.dig(1)&.drop(1)&.dig(-1, 0)
|
196
169
|
ASSIGNMENT_NODE_TYPES.include?(node_type)
|
@@ -222,8 +195,8 @@ module IRB
|
|
222
195
|
false
|
223
196
|
end
|
224
197
|
|
225
|
-
def check_code_syntax(code)
|
226
|
-
lvars_code = RubyLex.generate_local_variables_assign_code(
|
198
|
+
def check_code_syntax(code, local_variables:)
|
199
|
+
lvars_code = RubyLex.generate_local_variables_assign_code(local_variables)
|
227
200
|
code = "#{lvars_code}\n#{code}"
|
228
201
|
|
229
202
|
begin # check if parser error are available
|
@@ -455,8 +428,8 @@ module IRB
|
|
455
428
|
end
|
456
429
|
end
|
457
430
|
|
458
|
-
def check_termination_in_prev_line(code)
|
459
|
-
tokens = self.class.ripper_lex_without_warning(code,
|
431
|
+
def check_termination_in_prev_line(code, local_variables:)
|
432
|
+
tokens = self.class.ripper_lex_without_warning(code, local_variables: local_variables)
|
460
433
|
past_first_newline = false
|
461
434
|
index = tokens.rindex do |t|
|
462
435
|
# traverse first token before last line
|
@@ -486,7 +459,7 @@ module IRB
|
|
486
459
|
tokens_without_last_line = tokens[0..index]
|
487
460
|
code_without_last_line = tokens_without_last_line.map(&:tok).join
|
488
461
|
opens_without_last_line = NestingParser.open_tokens(tokens_without_last_line)
|
489
|
-
if code_terminated?(code_without_last_line, tokens_without_last_line, opens_without_last_line)
|
462
|
+
if code_terminated?(code_without_last_line, tokens_without_last_line, opens_without_last_line, local_variables: local_variables)
|
490
463
|
return last_line_tokens.map(&:tok).join
|
491
464
|
end
|
492
465
|
end
|
data/lib/irb/source_finder.rb
CHANGED
@@ -43,7 +43,7 @@ module IRB
|
|
43
43
|
private
|
44
44
|
|
45
45
|
def find_end(file, first_line)
|
46
|
-
lex = RubyLex.new
|
46
|
+
lex = RubyLex.new
|
47
47
|
lines = File.read(file).lines[(first_line - 1)..-1]
|
48
48
|
tokens = RubyLex.ripper_lex_without_warning(lines.join)
|
49
49
|
prev_tokens = []
|
@@ -53,7 +53,7 @@ module IRB
|
|
53
53
|
code = lines[0..lnum].join
|
54
54
|
prev_tokens.concat chunk
|
55
55
|
continue = lex.should_continue?(prev_tokens)
|
56
|
-
syntax = lex.check_code_syntax(code)
|
56
|
+
syntax = lex.check_code_syntax(code, local_variables: [])
|
57
57
|
if !continue && syntax == :valid
|
58
58
|
return first_line + lnum
|
59
59
|
end
|
data/lib/irb/version.rb
CHANGED
data/lib/irb.rb
CHANGED
@@ -436,7 +436,8 @@ module IRB
|
|
436
436
|
@context = Context.new(self, workspace, input_method)
|
437
437
|
@context.workspace.load_commands_to_main
|
438
438
|
@signal_status = :IN_IRB
|
439
|
-
@scanner = RubyLex.new
|
439
|
+
@scanner = RubyLex.new
|
440
|
+
@line_no = 1
|
440
441
|
end
|
441
442
|
|
442
443
|
# A hook point for `debug` command's breakpoint after :IRB_EXIT as well as its clean-up
|
@@ -454,7 +455,7 @@ module IRB
|
|
454
455
|
workspace = IRB::WorkSpace.new(binding)
|
455
456
|
context.workspace = workspace
|
456
457
|
context.workspace.load_commands_to_main
|
457
|
-
|
458
|
+
@line_no += 1
|
458
459
|
|
459
460
|
# When users run:
|
460
461
|
# 1. Debugging commands, like `step 2`
|
@@ -476,7 +477,7 @@ module IRB
|
|
476
477
|
end
|
477
478
|
|
478
479
|
if input&.include?("\n")
|
479
|
-
|
480
|
+
@line_no += input.count("\n") - 1
|
480
481
|
end
|
481
482
|
|
482
483
|
input
|
@@ -513,34 +514,38 @@ module IRB
|
|
513
514
|
# The lexer used by this irb session
|
514
515
|
attr_accessor :scanner
|
515
516
|
|
516
|
-
|
517
|
-
|
518
|
-
@scanner.
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
f =
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
517
|
+
private def generate_prompt(opens, continue, line_offset)
|
518
|
+
ltype = @scanner.ltype_from_open_tokens(opens)
|
519
|
+
indent = @scanner.calc_indent_level(opens)
|
520
|
+
continue = opens.any? || continue
|
521
|
+
line_no = @line_no + line_offset
|
522
|
+
|
523
|
+
if ltype
|
524
|
+
f = @context.prompt_s
|
525
|
+
elsif continue
|
526
|
+
f = @context.prompt_c
|
527
|
+
else
|
528
|
+
f = @context.prompt_i
|
529
|
+
end
|
530
|
+
f = "" unless f
|
531
|
+
if @context.prompting?
|
532
|
+
p = format_prompt(f, ltype, indent, line_no)
|
533
|
+
else
|
534
|
+
p = ""
|
535
|
+
end
|
536
|
+
if @context.auto_indent_mode and !@context.io.respond_to?(:auto_indent)
|
537
|
+
unless ltype
|
538
|
+
prompt_i = @context.prompt_i.nil? ? "" : @context.prompt_i
|
539
|
+
ind = format_prompt(prompt_i, ltype, indent, line_no)[/.*\z/].size +
|
540
|
+
indent * 2 - p.size
|
541
|
+
p += " " * ind if ind > 0
|
540
542
|
end
|
541
|
-
@context.io.prompt
|
542
543
|
end
|
544
|
+
p
|
545
|
+
end
|
543
546
|
|
547
|
+
# Evaluates input for this session.
|
548
|
+
def eval_input
|
544
549
|
configure_io
|
545
550
|
|
546
551
|
each_top_level_statement do |statement, line_no|
|
@@ -572,8 +577,9 @@ module IRB
|
|
572
577
|
end
|
573
578
|
end
|
574
579
|
|
575
|
-
def read_input
|
580
|
+
def read_input(prompt)
|
576
581
|
signal_status(:IN_INPUT) do
|
582
|
+
@context.io.prompt = prompt
|
577
583
|
if l = @context.io.gets
|
578
584
|
print l if @context.verbose?
|
579
585
|
else
|
@@ -591,16 +597,16 @@ module IRB
|
|
591
597
|
end
|
592
598
|
|
593
599
|
def readmultiline
|
594
|
-
|
600
|
+
prompt = generate_prompt([], false, 0)
|
595
601
|
|
596
602
|
# multiline
|
597
|
-
return read_input if @context.io.respond_to?(:check_termination)
|
603
|
+
return read_input(prompt) if @context.io.respond_to?(:check_termination)
|
598
604
|
|
599
605
|
# nomultiline
|
600
606
|
code = ''
|
601
607
|
line_offset = 0
|
602
608
|
loop do
|
603
|
-
line = read_input
|
609
|
+
line = read_input(prompt)
|
604
610
|
unless line
|
605
611
|
return code.empty? ? nil : code
|
606
612
|
end
|
@@ -610,12 +616,12 @@ module IRB
|
|
610
616
|
# Accept any single-line input for symbol aliases or commands that transform args
|
611
617
|
return code if single_line_command?(code)
|
612
618
|
|
613
|
-
tokens, opens, terminated = @scanner.check_code_state(code)
|
619
|
+
tokens, opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
|
614
620
|
return code if terminated
|
615
621
|
|
616
622
|
line_offset += 1
|
617
623
|
continue = @scanner.should_continue?(tokens)
|
618
|
-
|
624
|
+
prompt = generate_prompt(opens, continue, line_offset)
|
619
625
|
end
|
620
626
|
end
|
621
627
|
|
@@ -625,9 +631,9 @@ module IRB
|
|
625
631
|
break unless code
|
626
632
|
|
627
633
|
if code != "\n"
|
628
|
-
yield build_statement(code), @
|
634
|
+
yield build_statement(code), @line_no
|
629
635
|
end
|
630
|
-
@
|
636
|
+
@line_no += code.count("\n")
|
631
637
|
rescue RubyLex::TerminateLineInput
|
632
638
|
end
|
633
639
|
end
|
@@ -643,7 +649,8 @@ module IRB
|
|
643
649
|
if command_class
|
644
650
|
Statement::Command.new(code, command, arg, command_class)
|
645
651
|
else
|
646
|
-
|
652
|
+
is_assignment_expression = @scanner.assignment_expression?(code, local_variables: @context.local_variables)
|
653
|
+
Statement::Expression.new(code, is_assignment_expression)
|
647
654
|
end
|
648
655
|
end
|
649
656
|
|
@@ -656,7 +663,7 @@ module IRB
|
|
656
663
|
if @context.io.respond_to?(:check_termination)
|
657
664
|
@context.io.check_termination do |code|
|
658
665
|
if Reline::IOGate.in_pasting?
|
659
|
-
rest = @scanner.check_termination_in_prev_line(code)
|
666
|
+
rest = @scanner.check_termination_in_prev_line(code, local_variables: @context.local_variables)
|
660
667
|
if rest
|
661
668
|
Reline.delete_text
|
662
669
|
rest.bytes.reverse_each do |c|
|
@@ -670,7 +677,7 @@ module IRB
|
|
670
677
|
# Accept any single-line input for symbol aliases or commands that transform args
|
671
678
|
next true if single_line_command?(code)
|
672
679
|
|
673
|
-
_tokens, _opens, terminated = @scanner.check_code_state(code)
|
680
|
+
_tokens, _opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
|
674
681
|
terminated
|
675
682
|
end
|
676
683
|
end
|
@@ -678,7 +685,7 @@ module IRB
|
|
678
685
|
if @context.io.respond_to?(:dynamic_prompt)
|
679
686
|
@context.io.dynamic_prompt do |lines|
|
680
687
|
lines << '' if lines.empty?
|
681
|
-
tokens = RubyLex.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join,
|
688
|
+
tokens = RubyLex.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, local_variables: @context.local_variables)
|
682
689
|
line_results = IRB::NestingParser.parse_by_line(tokens)
|
683
690
|
tokens_until_line = []
|
684
691
|
line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset|
|
@@ -687,7 +694,7 @@ module IRB
|
|
687
694
|
tokens_until_line << token if token != tokens_until_line.last
|
688
695
|
end
|
689
696
|
continue = @scanner.should_continue?(tokens_until_line)
|
690
|
-
|
697
|
+
generate_prompt(next_opens, continue, line_num_offset)
|
691
698
|
end
|
692
699
|
end
|
693
700
|
end
|
@@ -698,7 +705,7 @@ module IRB
|
|
698
705
|
next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/)
|
699
706
|
|
700
707
|
code = lines[0..line_index].map { |l| "#{l}\n" }.join
|
701
|
-
tokens = RubyLex.ripper_lex_without_warning(code,
|
708
|
+
tokens = RubyLex.ripper_lex_without_warning(code, local_variables: @context.local_variables)
|
702
709
|
@scanner.process_indent_level(tokens, lines, line_index, is_newline)
|
703
710
|
end
|
704
711
|
end
|
@@ -873,7 +880,7 @@ module IRB
|
|
873
880
|
end
|
874
881
|
end
|
875
882
|
|
876
|
-
def truncate_prompt_main(str) # :nodoc:
|
883
|
+
private def truncate_prompt_main(str) # :nodoc:
|
877
884
|
str = str.tr(CONTROL_CHARACTERS_PATTERN, ' ')
|
878
885
|
if str.size <= PROMPT_MAIN_TRUNCATE_LENGTH
|
879
886
|
str
|
@@ -882,9 +889,8 @@ module IRB
|
|
882
889
|
end
|
883
890
|
end
|
884
891
|
|
885
|
-
def
|
886
|
-
|
887
|
-
p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
|
892
|
+
private def format_prompt(format, ltype, indent, line_no) # :nodoc:
|
893
|
+
format.gsub(/%([0-9]+)?([a-zA-Z])/) do
|
888
894
|
case $2
|
889
895
|
when "N"
|
890
896
|
@context.irb_name
|
@@ -918,7 +924,6 @@ module IRB
|
|
918
924
|
"%"
|
919
925
|
end
|
920
926
|
end
|
921
|
-
p
|
922
927
|
end
|
923
928
|
|
924
929
|
def output_value(omit = false) # :nodoc:
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: irb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-10-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: reline
|
@@ -17,28 +17,28 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.3.
|
20
|
+
version: 0.3.8
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.3.
|
27
|
+
version: 0.3.8
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rdoc
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - "
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '0'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - "
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '0'
|
42
42
|
description: Interactive Ruby command-line tool for REPL (Read Eval Print Loop).
|
43
43
|
email:
|
44
44
|
- aycabta@gmail.com
|