irb 1.8.1 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|