irb 1.8.1 → 1.9.0
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/Gemfile +7 -0
- data/README.md +102 -1
- data/Rakefile +2 -2
- data/lib/irb/cmd/irb_info.rb +1 -0
- data/lib/irb/cmd/show_source.rb +11 -6
- data/lib/irb/completion.rb +87 -94
- data/lib/irb/context.rb +39 -2
- data/lib/irb/debug/ui.rb +2 -3
- data/lib/irb/debug.rb +2 -5
- data/lib/irb/easter-egg.rb +16 -6
- data/lib/irb/history.rb +3 -1
- data/lib/irb/init.rb +41 -0
- data/lib/irb/input-method.rb +155 -83
- data/lib/irb/lc/help-message +3 -0
- data/lib/irb/lc/ja/help-message +3 -0
- data/lib/irb/ruby-lex.rb +14 -41
- data/lib/irb/ruby_logo.aa +43 -0
- data/lib/irb/source_finder.rb +2 -2
- data/lib/irb/type_completion/completor.rb +235 -0
- data/lib/irb/type_completion/methods.rb +13 -0
- data/lib/irb/type_completion/scope.rb +412 -0
- data/lib/irb/type_completion/type_analyzer.rb +1169 -0
- data/lib/irb/type_completion/types.rb +426 -0
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +103 -142
- data/man/irb.1 +7 -0
- metadata +8 -3
data/lib/irb/init.rb
CHANGED
@@ -5,6 +5,41 @@
|
|
5
5
|
#
|
6
6
|
|
7
7
|
module IRB # :nodoc:
|
8
|
+
@CONF = {}
|
9
|
+
# Displays current configuration.
|
10
|
+
#
|
11
|
+
# Modifying the configuration is achieved by sending a message to IRB.conf.
|
12
|
+
#
|
13
|
+
# See IRB@Configuration for more information.
|
14
|
+
def IRB.conf
|
15
|
+
@CONF
|
16
|
+
end
|
17
|
+
|
18
|
+
def @CONF.inspect
|
19
|
+
array = []
|
20
|
+
for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
|
21
|
+
case k
|
22
|
+
when :MAIN_CONTEXT, :__TMP__EHV__
|
23
|
+
array.push format("CONF[:%s]=...myself...", k.id2name)
|
24
|
+
when :PROMPT
|
25
|
+
s = v.collect{
|
26
|
+
|kk, vv|
|
27
|
+
ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
|
28
|
+
format(":%s=>{%s}", kk.id2name, ss.join(", "))
|
29
|
+
}
|
30
|
+
array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
|
31
|
+
else
|
32
|
+
array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
array.join("\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the current version of IRB, including release version and last
|
39
|
+
# updated date.
|
40
|
+
def IRB.version
|
41
|
+
format("irb %s (%s)", @RELEASE_VERSION, @LAST_UPDATE_DATE)
|
42
|
+
end
|
8
43
|
|
9
44
|
# initialize config
|
10
45
|
def IRB.setup(ap_path, argv: ::ARGV)
|
@@ -28,6 +63,7 @@ module IRB # :nodoc:
|
|
28
63
|
unless ap_path and @CONF[:AP_NAME]
|
29
64
|
ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb")
|
30
65
|
end
|
66
|
+
@CONF[:VERSION] = version
|
31
67
|
@CONF[:AP_NAME] = File::basename(ap_path, ".rb")
|
32
68
|
|
33
69
|
@CONF[:IRB_NAME] = "irb"
|
@@ -40,6 +76,7 @@ module IRB # :nodoc:
|
|
40
76
|
@CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
|
41
77
|
@CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
|
42
78
|
@CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
|
79
|
+
@CONF[:COMPLETOR] = :regexp
|
43
80
|
@CONF[:INSPECT_MODE] = true
|
44
81
|
@CONF[:USE_TRACER] = false
|
45
82
|
@CONF[:USE_LOADER] = false
|
@@ -293,6 +330,10 @@ module IRB # :nodoc:
|
|
293
330
|
@CONF[:USE_AUTOCOMPLETE] = true
|
294
331
|
when "--noautocomplete"
|
295
332
|
@CONF[:USE_AUTOCOMPLETE] = false
|
333
|
+
when "--regexp-completor"
|
334
|
+
@CONF[:COMPLETOR] = :regexp
|
335
|
+
when "--type-completor"
|
336
|
+
@CONF[:COMPLETOR] = :type
|
296
337
|
when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/
|
297
338
|
opt = $1 || argv.shift
|
298
339
|
prompt_mode = opt.upcase.tr("-", "_").intern
|
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,20 @@ 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
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
def completion_info
|
197
|
+
'RegexpCompletor'
|
188
198
|
end
|
189
199
|
|
190
200
|
# Reads the next line from this input method.
|
@@ -224,17 +234,22 @@ module IRB
|
|
224
234
|
HISTORY = Reline::HISTORY
|
225
235
|
include HistorySavingAbility
|
226
236
|
# Creates a new input method object using Reline
|
227
|
-
def initialize
|
237
|
+
def initialize(completor)
|
228
238
|
IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false)
|
229
239
|
|
230
|
-
super
|
240
|
+
super()
|
231
241
|
|
232
242
|
@eof = false
|
243
|
+
@completor = completor
|
233
244
|
|
234
|
-
Reline.basic_word_break_characters =
|
245
|
+
Reline.basic_word_break_characters = BASIC_WORD_BREAK_CHARACTERS
|
235
246
|
Reline.completion_append_character = nil
|
236
247
|
Reline.completer_quote_characters = ''
|
237
|
-
Reline.completion_proc =
|
248
|
+
Reline.completion_proc = ->(target, preposing, postposing) {
|
249
|
+
bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
|
250
|
+
@completion_params = [preposing, target, postposing, bind]
|
251
|
+
@completor.completion_candidates(preposing, target, postposing, bind: bind)
|
252
|
+
}
|
238
253
|
Reline.output_modifier_proc =
|
239
254
|
if IRB.conf[:USE_COLORIZE]
|
240
255
|
proc do |output, complete: |
|
@@ -247,18 +262,23 @@ module IRB
|
|
247
262
|
Reline::Unicode.escape_for_print(output)
|
248
263
|
end
|
249
264
|
end
|
250
|
-
Reline.dig_perfect_match_proc =
|
265
|
+
Reline.dig_perfect_match_proc = ->(matched) { display_document(matched) }
|
251
266
|
Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
|
252
267
|
|
253
268
|
if IRB.conf[:USE_AUTOCOMPLETE]
|
254
269
|
begin
|
255
270
|
require 'rdoc'
|
256
|
-
Reline.add_dialog_proc(:show_doc,
|
271
|
+
Reline.add_dialog_proc(:show_doc, show_doc_dialog_proc, Reline::DEFAULT_DIALOG_CONTEXT)
|
257
272
|
rescue LoadError
|
258
273
|
end
|
259
274
|
end
|
260
275
|
end
|
261
276
|
|
277
|
+
def completion_info
|
278
|
+
autocomplete_message = Reline.autocompletion ? 'Autocomplete' : 'Tab Complete'
|
279
|
+
"#{autocomplete_message}, #{@completor.inspect}"
|
280
|
+
end
|
281
|
+
|
262
282
|
def check_termination(&block)
|
263
283
|
@check_termination_proc = block
|
264
284
|
end
|
@@ -271,100 +291,152 @@ module IRB
|
|
271
291
|
@auto_indent_proc = block
|
272
292
|
end
|
273
293
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
294
|
+
def show_doc_dialog_proc
|
295
|
+
doc_namespace = ->(matched) {
|
296
|
+
preposing, _target, postposing, bind = @completion_params
|
297
|
+
@completor.doc_namespace(preposing, matched, postposing, bind: bind)
|
298
|
+
}
|
299
|
+
->() {
|
300
|
+
dialog.trap_key = nil
|
301
|
+
alt_d = [
|
302
|
+
[Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d.
|
303
|
+
[27, 100], # Normal Alt+d when convert-meta isn't used.
|
304
|
+
[195, 164], # The "ä" that appears when Alt+d is pressed on xterm.
|
305
|
+
[226, 136, 130] # The "∂" that appears when Alt+d in pressed on iTerm2.
|
306
|
+
]
|
307
|
+
|
308
|
+
if just_cursor_moving and completion_journey_data.nil?
|
309
|
+
return nil
|
310
|
+
end
|
311
|
+
cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4)
|
312
|
+
return nil if result.nil? or pointer.nil? or pointer < 0
|
282
313
|
|
283
|
-
|
284
|
-
|
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)
|
314
|
+
name = doc_namespace.call(result[pointer])
|
315
|
+
show_easter_egg = name&.match?(/\ARubyVM/) && !ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
|
290
316
|
|
291
|
-
|
292
|
-
|
293
|
-
|
317
|
+
options = {}
|
318
|
+
options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
|
319
|
+
driver = RDoc::RI::Driver.new(options)
|
294
320
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
321
|
+
if key.match?(dialog.name)
|
322
|
+
if show_easter_egg
|
323
|
+
IRB.__send__(:easter_egg)
|
324
|
+
else
|
325
|
+
begin
|
326
|
+
driver.display_names([name])
|
327
|
+
rescue RDoc::RI::Driver::NotFoundError
|
328
|
+
end
|
329
|
+
end
|
299
330
|
end
|
300
|
-
end
|
301
331
|
|
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
332
|
begin
|
321
|
-
driver.
|
333
|
+
name = driver.expand_name(name)
|
322
334
|
rescue RDoc::RI::Driver::NotFoundError
|
323
|
-
|
335
|
+
return nil
|
324
336
|
rescue
|
325
337
|
return nil # unknown error
|
326
338
|
end
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
+
doc = nil
|
340
|
+
used_for_class = false
|
341
|
+
if not name =~ /#|\./
|
342
|
+
found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
|
343
|
+
if not found.empty?
|
344
|
+
doc = driver.class_document(name, found, klasses, includes, extends)
|
345
|
+
used_for_class = true
|
346
|
+
end
|
347
|
+
end
|
348
|
+
unless used_for_class
|
349
|
+
doc = RDoc::Markup::Document.new
|
350
|
+
begin
|
351
|
+
driver.add_method(doc, name)
|
352
|
+
rescue RDoc::RI::Driver::NotFoundError
|
353
|
+
doc = nil
|
354
|
+
rescue
|
355
|
+
return nil # unknown error
|
356
|
+
end
|
357
|
+
end
|
358
|
+
return nil if doc.nil?
|
359
|
+
width = 40
|
360
|
+
|
361
|
+
right_x = cursor_pos_to_render.x + autocomplete_dialog.width
|
362
|
+
if right_x + width > screen_width
|
363
|
+
right_width = screen_width - (right_x + 1)
|
364
|
+
left_x = autocomplete_dialog.column - width
|
365
|
+
left_x = 0 if left_x < 0
|
366
|
+
left_width = width > autocomplete_dialog.column ? autocomplete_dialog.column : width
|
367
|
+
if right_width.positive? and left_width.positive?
|
368
|
+
if right_width >= left_width
|
369
|
+
width = right_width
|
370
|
+
x = right_x
|
371
|
+
else
|
372
|
+
width = left_width
|
373
|
+
x = left_x
|
374
|
+
end
|
375
|
+
elsif right_width.positive? and left_width <= 0
|
339
376
|
width = right_width
|
340
377
|
x = right_x
|
341
|
-
|
378
|
+
elsif right_width <= 0 and left_width.positive?
|
342
379
|
width = left_width
|
343
380
|
x = left_x
|
381
|
+
else # Both are negative width.
|
382
|
+
return nil
|
344
383
|
end
|
345
|
-
|
346
|
-
width = right_width
|
384
|
+
else
|
347
385
|
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
386
|
end
|
387
|
+
formatter = RDoc::Markup::ToAnsi.new
|
388
|
+
formatter.width = width
|
389
|
+
dialog.trap_key = alt_d
|
390
|
+
mod_key = RUBY_PLATFORM.match?(/darwin/) ? "Option" : "Alt"
|
391
|
+
if show_easter_egg
|
392
|
+
type = STDOUT.external_encoding == Encoding::UTF_8 ? :unicode : :ascii
|
393
|
+
contents = IRB.send(:easter_egg_logo, type).split("\n")
|
394
|
+
message = "Press #{mod_key}+d to see more"
|
395
|
+
contents[0][0, message.size] = message
|
396
|
+
else
|
397
|
+
message = "Press #{mod_key}+d to read the full document"
|
398
|
+
contents = [message] + doc.accept(formatter).split("\n")
|
399
|
+
end
|
400
|
+
contents = contents.take(preferred_dialog_height)
|
401
|
+
|
402
|
+
y = cursor_pos_to_render.y
|
403
|
+
Reline::DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
|
404
|
+
}
|
405
|
+
end
|
406
|
+
|
407
|
+
def display_document(matched, driver: nil)
|
408
|
+
begin
|
409
|
+
require 'rdoc'
|
410
|
+
rescue LoadError
|
411
|
+
return
|
412
|
+
end
|
413
|
+
|
414
|
+
if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
|
415
|
+
IRB.__send__(:easter_egg)
|
416
|
+
return
|
417
|
+
end
|
418
|
+
|
419
|
+
_target, preposing, postposing, bind = @completion_params
|
420
|
+
namespace = @completor.doc_namespace(preposing, matched, postposing, bind: bind)
|
421
|
+
return unless namespace
|
422
|
+
|
423
|
+
driver ||= RDoc::RI::Driver.new
|
424
|
+
if namespace.is_a?(Array)
|
425
|
+
out = RDoc::Markup::Document.new
|
426
|
+
namespace.each do |m|
|
427
|
+
begin
|
428
|
+
driver.add_method(out, m)
|
429
|
+
rescue RDoc::RI::Driver::NotFoundError
|
430
|
+
end
|
431
|
+
end
|
432
|
+
driver.display(out)
|
354
433
|
else
|
355
|
-
|
434
|
+
begin
|
435
|
+
driver.display_names([namespace])
|
436
|
+
rescue RDoc::RI::Driver::NotFoundError
|
437
|
+
end
|
356
438
|
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
|
-
}
|
439
|
+
end
|
368
440
|
|
369
441
|
# Reads the next line from this input method.
|
370
442
|
#
|
data/lib/irb/lc/help-message
CHANGED
@@ -30,6 +30,9 @@ Usage: irb.rb [options] [programfile] [arguments]
|
|
30
30
|
--nocolorize Don't use color-highlighting.
|
31
31
|
--autocomplete Use auto-completion (default).
|
32
32
|
--noautocomplete Don't use auto-completion.
|
33
|
+
--regexp-completor
|
34
|
+
Use regexp based completion (default).
|
35
|
+
--type-completor Use type based completion.
|
33
36
|
--prompt prompt-mode, --prompt-mode prompt-mode
|
34
37
|
Set prompt mode. Pre-defined prompt modes are:
|
35
38
|
'default', 'classic', 'simple', 'inf-ruby', 'xmp', 'null'.
|
data/lib/irb/lc/ja/help-message
CHANGED
@@ -21,6 +21,9 @@ Usage: irb.rb [options] [programfile] [arguments]
|
|
21
21
|
--nocolorize 色付けを利用しない.
|
22
22
|
--autocomplete オートコンプリートを利用する.
|
23
23
|
--noautocomplete オートコンプリートを利用しない.
|
24
|
+
--regexp-completor
|
25
|
+
補完に正規表現を利用する.
|
26
|
+
--type-completor 補完に型情報を利用する.
|
24
27
|
--prompt prompt-mode/--prompt-mode prompt-mode
|
25
28
|
プロンプトモードを切替えます. 現在定義されているプ
|
26
29
|
ロンプトモードは, default, simple, xmp, inf-rubyが
|
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/ruby_logo.aa
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
TYPE: LARGE
|
1
2
|
|
2
3
|
-+smJYYN?mm-
|
3
4
|
HB"BBYT TQg NggT
|
@@ -35,3 +36,45 @@
|
|
35
36
|
m7 NW H N HSVO1z=?11-
|
36
37
|
NgTH bB kH WBHWWHBHWmQgg&gggggNNN
|
37
38
|
NNggggggNN
|
39
|
+
TYPE: ASCII
|
40
|
+
,,,;;;;''''';;;'';,
|
41
|
+
,,;'' ';;,;;; ',
|
42
|
+
,,'' ;;'';'''';;;;;;
|
43
|
+
,;' ;; ',, ;
|
44
|
+
,;' ,;' ';, ;
|
45
|
+
;' ,;; ',,,;
|
46
|
+
,' ,;;,,,,,,,,,,,;;;;
|
47
|
+
;' ;;';;;; ,;;
|
48
|
+
;' ,;' ;; '',, ,;;;
|
49
|
+
;; ,;' ; '';, ,; ;'
|
50
|
+
;; ,;;' ;; ;; ;;
|
51
|
+
;;, ,,;;' ; ;'; ;;
|
52
|
+
;';;,,,,;;;;;;;,,, ;; ,' ; ;;
|
53
|
+
; ;;''' ,;'; ''';,,, ; ,;' ;;;;
|
54
|
+
;;;;, ; '; ''';;;' ';;;
|
55
|
+
;'; ;, ;' '; ,;' ', ;;;
|
56
|
+
;;; ; ,; '; ,,' ',, ;;
|
57
|
+
;;; '; ;' ';,,'' ';,;;
|
58
|
+
'; ';,; ,,;''''''''';;;;;;,,;;;
|
59
|
+
';,,;;,,;;;;;;;;;;''''''''''''''
|
60
|
+
TYPE: UNICODE
|
61
|
+
⣀⣤⣴⣾⣿⣿⣿⡛⠛⠛⠛⠛⣻⣿⠿⠛⠛⠶⣤⡀
|
62
|
+
⣀⣴⠾⠛⠉⠁ ⠙⣿⣶⣤⣶⣟⣉ ⠈⠻⣦
|
63
|
+
⣀⣴⠟⠋ ⢸⣿⠟⠻⣯⡙⠛⠛⠛⠶⠶⠶⢶⣽⣇
|
64
|
+
⣠⡾⠋⠁ ⣾⡿ ⠈⠛⢦⣄ ⣿
|
65
|
+
⣠⡾⠋ ⣰⣿⠃ ⠙⠷⣤⡀ ⣿
|
66
|
+
⢀⡾⠋ ⣰⣿⡏ ⠈⠻⣦⣄⢠⣿
|
67
|
+
⣰⠟⠁ ⣴⣿⣿⣁⣀⣠⣤⣤⣤⣤⣤⣤⣤⣴⠶⠿⣿⡏
|
68
|
+
⣼⠏ ⢀⣾⣿⠟⣿⠿⣯⣍⠁ ⣰⣿⡇
|
69
|
+
⢀⣼⠋ ⢀⣴⣿⠟⠁ ⢸⡇ ⠙⠻⢦⣄⡀ ⢠⡿⣿⡇
|
70
|
+
⢀⣾⡏ ⢀⣴⣿⠟⠁ ⣿ ⠉⠻⢶⣄⡀⣰⡟ ⣿⠃
|
71
|
+
⣾⣿⠁ ⣠⣶⡿⠋⠁ ⢹⡇ ⠈⣿⡏ ⢸⣿
|
72
|
+
⣿⣿⡆ ⢀⣠⣴⣿⡿⠋ ⠈⣿ ⢀⡾⠋⣿ ⢸⣿
|
73
|
+
⣿⠸⣿⣶⣤⣤⣤⣤⣶⣾⠿⠿⣿⣿⠶⣤⣤⣀⡀ ⢹⡇ ⣴⠟⠁ ⣿⡀⢸⣿
|
74
|
+
⣿⢀⣿⣟⠛⠋⠉⠁ ⢰⡟⠹⣧ ⠈⠉⠛⠻⠶⢦⣤⣀⡀ ⠈⣿ ⣠⡾⠃ ⢸⡇⢸⡇
|
75
|
+
⣿⣾⣿⢿⡄ ⣿⠁ ⠘⣧ ⠉⠙⠛⠷⣿⣿⡋ ⠸⣇⣸⡇
|
76
|
+
⣿⠃⣿⠈⢿⡄ ⣸⠇ ⠘⣧ ⢀⣤⠾⠋⠈⠻⣦⡀ ⣿⣿⡇
|
77
|
+
⣿⢸⡏ ⠈⣷⡀ ⢠⡿ ⠘⣧⡀ ⣠⡴⠟⠁ ⠈⠻⣦⣀ ⢿⣿⠁
|
78
|
+
⢻⣾⡇ ⠘⣷ ⣼⠃ ⠘⣷⣠⣴⠟⠋ ⠙⢷⣄⢸⣿
|
79
|
+
⠻⣧⡀ ⠘⣧⣰⡏ ⢀⣠⣤⠶⠛⠉⠛⠛⠛⠛⠛⠛⠻⢶⣶⣶⣶⣶⣶⣤⣤⣽⣿⣿
|
80
|
+
⠈⠛⠷⢦⣤⣽⣿⣥⣤⣶⣶⡿⠿⠿⠶⠶⠶⠶⠾⠛⠛⠛⠛⠛⠛⠛⠋⠉⠉⠉⠉⠉⠉⠁
|
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
|