irb 1.0.0 → 1.4.1

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.document +4 -0
  3. data/Gemfile +10 -2
  4. data/LICENSE.txt +3 -3
  5. data/README.md +3 -3
  6. data/Rakefile +17 -1
  7. data/doc/irb/irb-tools.rd.ja +184 -0
  8. data/doc/irb/irb.rd.ja +427 -0
  9. data/irb.gemspec +18 -4
  10. data/lib/irb/cmd/fork.rb +2 -4
  11. data/lib/irb/cmd/help.rb +10 -5
  12. data/lib/irb/cmd/info.rb +32 -0
  13. data/lib/irb/cmd/ls.rb +101 -0
  14. data/lib/irb/cmd/measure.rb +43 -0
  15. data/lib/irb/cmd/nop.rb +10 -4
  16. data/lib/irb/cmd/pushws.rb +0 -1
  17. data/lib/irb/cmd/show_source.rb +93 -0
  18. data/lib/irb/cmd/whereami.rb +20 -0
  19. data/lib/irb/color.rb +246 -0
  20. data/lib/irb/color_printer.rb +47 -0
  21. data/lib/irb/completion.rb +254 -55
  22. data/lib/irb/context.rb +165 -72
  23. data/lib/irb/easter-egg.rb +138 -0
  24. data/lib/irb/ext/change-ws.rb +0 -1
  25. data/lib/irb/ext/history.rb +47 -11
  26. data/lib/irb/ext/loader.rb +46 -20
  27. data/lib/irb/ext/multi-irb.rb +7 -7
  28. data/lib/irb/ext/save-history.rb +36 -11
  29. data/lib/irb/ext/tracer.rb +14 -2
  30. data/lib/irb/ext/use-loader.rb +4 -3
  31. data/lib/irb/ext/workspaces.rb +0 -1
  32. data/lib/irb/extend-command.rb +113 -63
  33. data/lib/irb/frame.rb +12 -7
  34. data/lib/irb/help.rb +0 -1
  35. data/lib/irb/init.rb +146 -26
  36. data/lib/irb/input-method.rb +287 -9
  37. data/lib/irb/inspector.rb +15 -11
  38. data/lib/irb/lc/error.rb +55 -16
  39. data/lib/irb/lc/help-message +25 -13
  40. data/lib/irb/lc/ja/error.rb +55 -14
  41. data/lib/irb/lc/ja/help-message +11 -6
  42. data/lib/irb/locale.rb +13 -4
  43. data/lib/irb/notifier.rb +12 -8
  44. data/lib/irb/output-method.rb +6 -6
  45. data/lib/irb/ruby-lex.rb +673 -992
  46. data/lib/irb/ruby_logo.aa +37 -0
  47. data/lib/irb/version.rb +2 -2
  48. data/lib/irb/workspace.rb +65 -21
  49. data/lib/irb/xmp.rb +1 -1
  50. data/lib/irb.rb +276 -96
  51. data/man/irb.1 +229 -0
  52. metadata +25 -31
  53. data/.gitignore +0 -9
  54. data/.travis.yml +0 -6
  55. data/lib/irb/lc/.document +0 -4
  56. data/lib/irb/ruby-token.rb +0 -267
  57. data/lib/irb/slex.rb +0 -282
data/lib/irb.rb CHANGED
@@ -9,17 +9,20 @@
9
9
  #
10
10
  #
11
11
  #
12
- require "e2mmap"
12
+ require "ripper"
13
+ require "reline"
13
14
 
14
- require "irb/init"
15
- require "irb/context"
16
- require "irb/extend-command"
15
+ require_relative "irb/init"
16
+ require_relative "irb/context"
17
+ require_relative "irb/extend-command"
17
18
 
18
- require "irb/ruby-lex"
19
- require "irb/input-method"
20
- require "irb/locale"
19
+ require_relative "irb/ruby-lex"
20
+ require_relative "irb/input-method"
21
+ require_relative "irb/locale"
22
+ require_relative "irb/color"
21
23
 
22
- require "irb/version"
24
+ require_relative "irb/version"
25
+ require_relative "irb/easter-egg"
23
26
 
24
27
  # IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby
25
28
  # expressions read from the standard input.
@@ -43,8 +46,8 @@ require "irb/version"
43
46
  # irb(main):006:1> end
44
47
  # #=> nil
45
48
  #
46
- # The Readline extension module can be used with irb. Use of Readline is
47
- # default if it's installed.
49
+ # The singleline editor module or multiline editor module can be used with irb.
50
+ # Use of multiline editor is default if it's installed.
48
51
  #
49
52
  # == Command line options
50
53
  #
@@ -57,24 +60,45 @@ require "irb/version"
57
60
  # -E enc Same as `ruby -E`
58
61
  # -w Same as `ruby -w`
59
62
  # -W[level=2] Same as `ruby -W`
60
- # --inspect Use `inspect' for output (default except for bc mode)
63
+ # --context-mode n Set n[0-4] to method to create Binding Object,
64
+ # when new workspace was created
65
+ # --extra-doc-dir Add an extra doc dir for the doc dialog
66
+ # --echo Show result (default)
67
+ # --noecho Don't show result
68
+ # --echo-on-assignment
69
+ # Show result on assignment
70
+ # --noecho-on-assignment
71
+ # Don't show result on assignment
72
+ # --truncate-echo-on-assignment
73
+ # Show truncated result on assignment (default)
74
+ # --inspect Use `inspect' for output
61
75
  # --noinspect Don't use inspect for output
62
- # --readline Use Readline extension module
63
- # --noreadline Don't use Readline extension module
64
- # --prompt prompt-mode
65
- # --prompt-mode prompt-mode
76
+ # --multiline Use multiline editor module
77
+ # --nomultiline Don't use multiline editor module
78
+ # --singleline Use singleline editor module
79
+ # --nosingleline Don't use singleline editor module
80
+ # --colorize Use colorization
81
+ # --nocolorize Don't use colorization
82
+ # --autocomplete Use autocompletion
83
+ # --noautocomplete Don't use autocompletion
84
+ # --prompt prompt-mode/--prompt-mode prompt-mode
66
85
  # Switch prompt mode. Pre-defined prompt modes are
67
86
  # `default', `simple', `xmp' and `inf-ruby'
68
87
  # --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
69
- # Suppresses --readline.
70
- # --simple-prompt Simple prompt mode
88
+ # Suppresses --multiline and --singleline.
89
+ # --sample-book-mode/--simple-prompt
90
+ # Simple prompt mode
71
91
  # --noprompt No prompt mode
92
+ # --single-irb Share self with sub-irb.
72
93
  # --tracer Display trace for each execution of commands.
73
94
  # --back-trace-limit n
74
95
  # Display backtrace top n and tail n. The default
75
96
  # value is 16.
76
- # --irb_debug n Set internal debug level to n (not for popular use)
77
- # -v, --version Print the version of irb
97
+ # --verbose Show details
98
+ # --noverbose Don't show details
99
+ # -v, --version Print the version of irb
100
+ # -h, --help Print help
101
+ # -- Separate options of irb from the list of command-line args
78
102
  #
79
103
  # == Configuration
80
104
  #
@@ -95,19 +119,21 @@ require "irb/version"
95
119
  # IRB.conf[:IRB_RC] = nil
96
120
  # IRB.conf[:BACK_TRACE_LIMIT]=16
97
121
  # IRB.conf[:USE_LOADER] = false
98
- # IRB.conf[:USE_READLINE] = nil
122
+ # IRB.conf[:USE_MULTILINE] = nil
123
+ # IRB.conf[:USE_SINGLELINE] = nil
124
+ # IRB.conf[:USE_COLORIZE] = true
99
125
  # IRB.conf[:USE_TRACER] = false
126
+ # IRB.conf[:USE_AUTOCOMPLETE] = true
100
127
  # IRB.conf[:IGNORE_SIGINT] = true
101
128
  # IRB.conf[:IGNORE_EOF] = false
102
129
  # IRB.conf[:PROMPT_MODE] = :DEFAULT
103
130
  # IRB.conf[:PROMPT] = {...}
104
- # IRB.conf[:DEBUG_LEVEL]=0
105
131
  #
106
132
  # === Auto indentation
107
133
  #
108
- # To enable auto-indent mode in irb, add the following to your +.irbrc+:
134
+ # To disable auto-indent mode in irb, add the following to your +.irbrc+:
109
135
  #
110
- # IRB.conf[:AUTO_INDENT] = true
136
+ # IRB.conf[:AUTO_INDENT] = false
111
137
  #
112
138
  # === Autocompletion
113
139
  #
@@ -117,16 +143,23 @@ require "irb/version"
117
143
  #
118
144
  # === History
119
145
  #
120
- # By default, irb disables history and will not store any commands you used.
146
+ # By default, irb will store the last 1000 commands you used in
147
+ # <code>IRB.conf[:HISTORY_FILE]</code> (<code>~/.irb_history</code> by default).
121
148
  #
122
- # If you want to enable history, add the following to your +.irbrc+:
149
+ # If you want to disable history, add the following to your +.irbrc+:
123
150
  #
124
- # IRB.conf[:SAVE_HISTORY] = 1000
125
- #
126
- # This will now store the last 1000 commands in <code>~/.irb_history</code>.
151
+ # IRB.conf[:SAVE_HISTORY] = nil
127
152
  #
128
153
  # See IRB::Context#save_history= for more information.
129
154
  #
155
+ # The history of _results_ of commands evaluated is not stored by default,
156
+ # but can be turned on to be stored with this +.irbrc+ setting:
157
+ #
158
+ # IRB.conf[:EVAL_HISTORY] = <number>
159
+ #
160
+ # See IRB::Context#eval_history= and History class. The history of command
161
+ # results is not permanently saved in any file.
162
+ #
130
163
  # == Customizing the IRB Prompt
131
164
  #
132
165
  # In order to customize the prompt, you can change the following Hash:
@@ -136,7 +169,7 @@ require "irb/version"
136
169
  # This example can be used in your +.irbrc+
137
170
  #
138
171
  # IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
139
- # :AUTO_INDENT => true, # enables auto-indent mode
172
+ # :AUTO_INDENT => false, # disables auto-indent mode
140
173
  # :PROMPT_I => ">> ", # simple prompt
141
174
  # :PROMPT_S => nil, # prompt for continuated strings
142
175
  # :PROMPT_C => nil, # prompt for continuated statement
@@ -165,6 +198,7 @@ require "irb/version"
165
198
  #
166
199
  # IRB.conf[:PROMPT_MODE][:DEFAULT] = {
167
200
  # :PROMPT_I => "%N(%m):%03n:%i> ",
201
+ # :PROMPT_N => "%N(%m):%03n:%i> ",
168
202
  # :PROMPT_S => "%N(%m):%03n:%i%l ",
169
203
  # :PROMPT_C => "%N(%m):%03n:%i* ",
170
204
  # :RETURN => "%s\n" # used to printf
@@ -257,7 +291,7 @@ require "irb/version"
257
291
  # On the other hand, each conf in IRB@Command+line+options is used to
258
292
  # individually configure IRB.irb.
259
293
  #
260
- # If a proc is set for IRB.conf[:IRB_RC], its will be invoked after execution
294
+ # If a proc is set for <code>IRB.conf[:IRB_RC]</code>, its will be invoked after execution
261
295
  # of that proc with the context of the current session as its argument. Each
262
296
  # session can be configured using this mechanism.
263
297
  #
@@ -268,7 +302,9 @@ require "irb/version"
268
302
  # <code>_</code>::
269
303
  # The value command executed, as a local variable
270
304
  # <code>__</code>::
271
- # The history of evaluated commands
305
+ # The history of evaluated commands. Available only if
306
+ # <code>IRB.conf[:EVAL_HISTORY]</code> is not +nil+ (which is the default).
307
+ # See also IRB::Context#eval_history= and IRB::History.
272
308
  # <code>__[line_no]</code>::
273
309
  # Returns the evaluation value at the given line number, +line_no+.
274
310
  # If +line_no+ is a negative, the return value +line_no+ many lines before
@@ -304,7 +340,7 @@ require "irb/version"
304
340
  # # check if Foo#foo is available
305
341
  # irb(main):005:0> Foo.instance_methods #=> [:foo, ...]
306
342
  #
307
- # # change the active sesssion
343
+ # # change the active session
308
344
  # irb(main):006:0> fg 2
309
345
  # # define Foo#bar in the context of Foo
310
346
  # irb.2(Foo):005:0> def bar
@@ -383,7 +419,7 @@ module IRB
383
419
  irb.run(@CONF)
384
420
  end
385
421
 
386
- # Calls each event hook of IRB.conf[:AT_EXIT] when the current session quits.
422
+ # Calls each event hook of <code>IRB.conf[:AT_EXIT]</code> when the current session quits.
387
423
  def IRB.irb_at_exit
388
424
  @CONF[:AT_EXIT].each{|hook| hook.call}
389
425
  end
@@ -405,21 +441,48 @@ module IRB
405
441
  end
406
442
 
407
443
  class Irb
444
+ ASSIGNMENT_NODE_TYPES = [
445
+ # Local, instance, global, class, constant, instance, and index assignment:
446
+ # "foo = bar",
447
+ # "@foo = bar",
448
+ # "$foo = bar",
449
+ # "@@foo = bar",
450
+ # "::Foo = bar",
451
+ # "a::Foo = bar",
452
+ # "Foo = bar"
453
+ # "foo.bar = 1"
454
+ # "foo[1] = bar"
455
+ :assign,
456
+
457
+ # Operation assignment:
458
+ # "foo += bar"
459
+ # "foo -= bar"
460
+ # "foo ||= bar"
461
+ # "foo &&= bar"
462
+ :opassign,
463
+
464
+ # Multiple assignment:
465
+ # "foo, bar = 1, 2
466
+ :massign,
467
+ ]
468
+ # Note: instance and index assignment expressions could also be written like:
469
+ # "foo.bar=(1)" and "foo.[]=(1, bar)", when expressed that way, the former
470
+ # be parsed as :assign and echo will be suppressed, but the latter is
471
+ # parsed as a :method_add_arg and the output won't be suppressed
472
+
408
473
  # Creates a new irb session
409
- def initialize(workspace = nil, input_method = nil, output_method = nil)
410
- @context = Context.new(self, workspace, input_method, output_method)
474
+ def initialize(workspace = nil, input_method = nil)
475
+ @context = Context.new(self, workspace, input_method)
411
476
  @context.main.extend ExtendCommandBundle
412
477
  @signal_status = :IN_IRB
413
-
414
478
  @scanner = RubyLex.new
415
- @scanner.exception_on_syntax_error = false
416
479
  end
417
480
 
418
481
  def run(conf = IRB.conf)
419
482
  conf[:IRB_RC].call(context) if conf[:IRB_RC]
420
483
  conf[:MAIN_CONTEXT] = context
421
484
 
422
- trap("SIGINT") do
485
+ prev_trap = trap("SIGINT") do
423
486
  signal_handle
424
487
  end
425
488
 
@@ -428,6 +491,7 @@ module IRB
428
491
  eval_input
429
492
  end
430
493
  ensure
494
+ trap("SIGINT", prev_trap)
431
495
  conf[:AT_EXIT].each{|hook| hook.call}
432
496
  end
433
497
  end
@@ -458,17 +522,19 @@ module IRB
458
522
  else
459
523
  @context.io.prompt = p = ""
460
524
  end
461
- if @context.auto_indent_mode
525
+ if @context.auto_indent_mode and !@context.io.respond_to?(:auto_indent)
462
526
  unless ltype
463
- ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size +
527
+ prompt_i = @context.prompt_i.nil? ? "" : @context.prompt_i
528
+ ind = prompt(prompt_i, ltype, indent, line_no)[/.*\z/].size +
464
529
  indent * 2 - p.size
465
530
  ind += 2 if continue
466
531
  @context.io.prompt = p + " " * ind if ind > 0
467
532
  end
468
533
  end
534
+ @context.io.prompt
469
535
  end
470
536
 
471
- @scanner.set_input(@context.io) do
537
+ @scanner.set_input(@context.io, context: @context) do
472
538
  signal_status(:IN_INPUT) do
473
539
  if l = @context.io.gets
474
540
  print l if @context.verbose?
@@ -479,19 +545,46 @@ module IRB
479
545
  printf "Use \"exit\" to leave %s\n", @context.ap_name
480
546
  end
481
547
  else
482
- print "\n"
548
+ print "\n" if @context.prompting?
483
549
  end
484
550
  end
485
551
  l
486
552
  end
487
553
  end
488
554
 
555
+ @scanner.set_auto_indent(@context) if @context.auto_indent_mode
556
+
489
557
  @scanner.each_top_level_statement do |line, line_no|
490
558
  signal_status(:IN_EVAL) do
491
559
  begin
492
- line.untaint
493
- @context.evaluate(line, line_no, exception: exc)
494
- output_value if @context.echo?
560
+ line.untaint if RUBY_VERSION < '2.7'
561
+ if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
562
+ IRB.set_measure_callback
563
+ end
564
+ if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
565
+ result = nil
566
+ last_proc = proc{ result = @context.evaluate(line, line_no, exception: exc) }
567
+ IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) { |chain, item|
568
+ _name, callback, arg = item
569
+ proc {
570
+ callback.(@context, line, line_no, arg, exception: exc) do
571
+ chain.call
572
+ end
573
+ }
574
+ }.call
575
+ @context.set_last_value(result)
576
+ else
577
+ @context.evaluate(line, line_no, exception: exc)
578
+ end
579
+ if @context.echo?
580
+ if assignment_expression?(line)
581
+ if @context.echo_on_assignment?
582
+ output_value(@context.echo_on_assignment? == :truncate)
583
+ end
584
+ else
585
+ output_value
586
+ end
587
+ end
495
588
  rescue Interrupt => exc
496
589
  rescue SystemExit, SignalException
497
590
  raise
@@ -501,61 +594,91 @@ module IRB
501
594
  next
502
595
  end
503
596
  handle_exception(exc)
597
+ @context.workspace.local_variable_set(:_, exc)
598
+ exc = nil
504
599
  end
505
600
  end
506
601
  end
507
602
 
603
+ def convert_invalid_byte_sequence(str, enc)
604
+ str.force_encoding(enc)
605
+ str.scrub { |c|
606
+ c.bytes.map{ |b| "\\x#{b.to_s(16).upcase}" }.join
607
+ }
608
+ end
609
+
610
+ def encode_with_invalid_byte_sequence(str, enc)
611
+ conv = Encoding::Converter.new(str.encoding, enc)
612
+ dst = String.new
613
+ begin
614
+ ret = conv.primitive_convert(str, dst)
615
+ case ret
616
+ when :invalid_byte_sequence
617
+ conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
618
+ redo
619
+ when :undefined_conversion
620
+ c = conv.primitive_errinfo[3].dup.force_encoding(conv.primitive_errinfo[1])
621
+ conv.insert_output(c.dump[1..-2])
622
+ redo
623
+ when :incomplete_input
624
+ conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
625
+ when :finished
626
+ end
627
+ break
628
+ end while nil
629
+ dst
630
+ end
631
+
508
632
  def handle_exception(exc)
509
- if exc.backtrace && exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
510
- !(SyntaxError === exc)
633
+ if exc.backtrace && exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
634
+ !(SyntaxError === exc) && !(EncodingError === exc)
635
+ # The backtrace of invalid encoding hash (ex. {"\xAE": 1}) raises EncodingError without lineno.
511
636
  irb_bug = true
512
637
  else
513
638
  irb_bug = false
514
639
  end
515
640
 
516
- if STDOUT.tty?
517
- attr = ATTR_TTY
518
- print "#{attr[1]}Traceback#{attr[]} (most recent call last):\n"
519
- else
520
- attr = ATTR_PLAIN
521
- end
522
- messages = []
523
- lasts = []
524
- levels = 0
525
641
  if exc.backtrace
526
- count = 0
527
- exc.backtrace.each do |m|
528
- m = @context.workspace.filter_backtrace(m) or next unless irb_bug
529
- count += 1
530
- if attr == ATTR_TTY
531
- m = sprintf("%9d: from %s", count, m)
642
+ order = nil
643
+ if '2.5.0' == RUBY_VERSION
644
+ # Exception#full_message doesn't have keyword arguments.
645
+ message = exc.full_message # the same of (highlight: true, order: bottom)
646
+ order = :bottom
647
+ elsif '2.5.1' <= RUBY_VERSION && RUBY_VERSION < '3.0.0'
648
+ if STDOUT.tty?
649
+ message = exc.full_message(order: :bottom)
650
+ order = :bottom
532
651
  else
533
- m = "\tfrom #{m}"
534
- end
535
- if messages.size < @context.back_trace_limit
536
- messages.push(m)
537
- elsif lasts.size < @context.back_trace_limit
538
- lasts.push(m).shift
539
- levels += 1
652
+ message = exc.full_message(order: :top)
653
+ order = :top
540
654
  end
655
+ else # '3.0.0' <= RUBY_VERSION
656
+ message = exc.full_message(order: :top)
657
+ order = :top
541
658
  end
542
- end
543
- if attr == ATTR_TTY
544
- unless lasts.empty?
545
- puts lasts.reverse
546
- printf "... %d levels...\n", levels if levels > 0
547
- end
548
- puts messages.reverse
549
- end
550
- m = exc.to_s.split(/\n/)
551
- print "#{attr[1]}#{exc.class} (#{attr[4]}#{m.shift}#{attr[0, 1]})#{attr[]}\n"
552
- puts m.map {|s| "#{attr[1]}#{s}#{attr[]}\n"}
553
- if attr == ATTR_PLAIN
554
- puts messages
555
- unless lasts.empty?
556
- puts lasts
557
- printf "... %d levels...\n", levels if levels > 0
558
- end
659
+ message = convert_invalid_byte_sequence(message, exc.message.encoding)
660
+ message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s)
661
+ message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
662
+ case order
663
+ when :top
664
+ lines = m.split("\n")
665
+ when :bottom
666
+ lines = m.split("\n").reverse
667
+ end
668
+ unless irb_bug
669
+ lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact
670
+ if lines.size > @context.back_trace_limit
671
+ omit = lines.size - @context.back_trace_limit
672
+ lines = lines[0..(@context.back_trace_limit - 1)]
673
+ lines << "\t... %d levels..." % omit
674
+ end
675
+ end
676
+ lines = lines.reverse if order == :bottom
677
+ lines.map{ |l| l + "\n" }.join
678
+ }
679
+ # The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
680
+ message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
681
+ puts message
559
682
  end
560
683
  print "Maybe IRB bug!\n" if irb_bug
561
684
  end
@@ -663,10 +786,18 @@ module IRB
663
786
  when "l"
664
787
  ltype
665
788
  when "i"
666
- if $1
667
- format("%" + $1 + "d", indent)
789
+ if indent < 0
790
+ if $1
791
+ "-".rjust($1.to_i)
792
+ else
793
+ "-"
794
+ end
668
795
  else
669
- indent.to_s
796
+ if $1
797
+ format("%" + $1 + "d", indent)
798
+ else
799
+ indent.to_s
800
+ end
670
801
  end
671
802
  when "n"
672
803
  if $1
@@ -681,8 +812,40 @@ module IRB
681
812
  p
682
813
  end
683
814
 
684
- def output_value # :nodoc:
685
- printf @context.return_format, @context.inspect_last_value
815
+ def output_value(omit = false) # :nodoc:
816
+ str = @context.inspect_last_value
817
+ multiline_p = str.include?("\n")
818
+ if omit
819
+ winwidth = @context.io.winsize.last
820
+ if multiline_p
821
+ first_line = str.split("\n").first
822
+ result = @context.newline_before_multiline_output? ? (@context.return_format % first_line) : first_line
823
+ output_width = Reline::Unicode.calculate_width(result, true)
824
+ diff_size = output_width - Reline::Unicode.calculate_width(first_line, true)
825
+ if diff_size.positive? and output_width > winwidth
826
+ lines, _ = Reline::Unicode.split_by_width(first_line, winwidth - diff_size - 3)
827
+ str = "%s..." % lines.first
828
+ str += "\e[0m" if @context.use_colorize
829
+ multiline_p = false
830
+ else
831
+ str = str.gsub(/(\A.*?\n).*/m, "\\1...")
832
+ str += "\e[0m" if @context.use_colorize
833
+ end
834
+ else
835
+ output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
836
+ diff_size = output_width - Reline::Unicode.calculate_width(str, true)
837
+ if diff_size.positive? and output_width > winwidth
838
+ lines, _ = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3)
839
+ str = "%s..." % lines.first
840
+ str += "\e[0m" if @context.use_colorize
841
+ end
842
+ end
843
+ end
844
+ if multiline_p && @context.newline_before_multiline_output?
845
+ printf @context.return_format, "\n#{str}"
846
+ else
847
+ printf @context.return_format, str
848
+ end
686
849
  end
687
850
 
688
851
  # Outputs the local variables to this current session, including
@@ -702,6 +865,21 @@ module IRB
702
865
  format("#<%s: %s>", self.class, ary.join(", "))
703
866
  end
704
867
 
868
+ def assignment_expression?(line)
869
+ # Try to parse the line and check if the last of possibly multiple
870
+ # expressions is an assignment type.
871
+
872
+ # If the expression is invalid, Ripper.sexp should return nil which will
873
+ # result in false being returned. Any valid expression should return an
874
+ # s-expression where the second element of the top level array is an
875
+ # array of parsed expressions. The first element of each expression is the
876
+ # expression's type.
877
+ verbose, $VERBOSE = $VERBOSE, nil
878
+ result = ASSIGNMENT_NODE_TYPES.include?(Ripper.sexp(line)&.dig(1,-1,0))
879
+ $VERBOSE = verbose
880
+ result
881
+ end
882
+
705
883
  ATTR_TTY = "\e[%sm"
706
884
  def ATTR_TTY.[](*a) self % a.join(";"); end
707
885
  ATTR_PLAIN = ""
@@ -749,8 +927,8 @@ class Binding
749
927
  #
750
928
  # Potato.new
751
929
  #
752
- # Running +ruby potato.rb+ will open an IRB session where +binding.irb+ is
753
- # called, and you will see the following:
930
+ # Running <code>ruby potato.rb</code> will open an IRB session where
931
+ # +binding.irb+ is called, and you will see the following:
754
932
  #
755
933
  # $ ruby potato.rb
756
934
  #
@@ -780,7 +958,7 @@ class Binding
780
958
  # irb(#<Potato:0x00007feea1916670>):004:0> @cooked = true
781
959
  # => true
782
960
  #
783
- # You can exit the IRB session with the `exit` command. Note that exiting will
961
+ # You can exit the IRB session with the +exit+ command. Note that exiting will
784
962
  # resume execution where +binding.irb+ had paused it, as you can see from the
785
963
  # output printed to standard output in this example:
786
964
  #
@@ -790,9 +968,11 @@ class Binding
790
968
  #
791
969
  # See IRB@IRB+Usage for more information.
792
970
  def irb
793
- IRB.setup(eval("__FILE__"), argv: [])
971
+ IRB.setup(source_location[0], argv: [])
794
972
  workspace = IRB::WorkSpace.new(self)
795
973
  STDOUT.print(workspace.code_around_binding)
796
- IRB::Irb.new(workspace).run(IRB.conf)
974
+ binding_irb = IRB::Irb.new(workspace)
975
+ binding_irb.context.irb_path = File.expand_path(source_location[0])
976
+ binding_irb.run(IRB.conf)
797
977
  end
798
978
  end