irb 1.8.3 → 1.13.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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/.document +1 -1
  3. data/Gemfile +9 -1
  4. data/README.md +149 -25
  5. data/Rakefile +13 -3
  6. data/irb.gemspec +2 -2
  7. data/lib/irb/cmd/nop.rb +3 -52
  8. data/lib/irb/color.rb +2 -2
  9. data/lib/irb/command/backtrace.rb +17 -0
  10. data/lib/irb/command/base.rb +62 -0
  11. data/lib/irb/command/break.rb +17 -0
  12. data/lib/irb/command/catch.rb +17 -0
  13. data/lib/irb/command/chws.rb +40 -0
  14. data/lib/irb/command/context.rb +16 -0
  15. data/lib/irb/{cmd → command}/continue.rb +3 -3
  16. data/lib/irb/{cmd → command}/debug.rb +11 -20
  17. data/lib/irb/{cmd → command}/delete.rb +3 -3
  18. data/lib/irb/command/disable_irb.rb +19 -0
  19. data/lib/irb/command/edit.rb +63 -0
  20. data/lib/irb/command/exit.rb +18 -0
  21. data/lib/irb/{cmd → command}/finish.rb +3 -3
  22. data/lib/irb/command/force_exit.rb +18 -0
  23. data/lib/irb/command/help.rb +83 -0
  24. data/lib/irb/command/history.rb +45 -0
  25. data/lib/irb/command/info.rb +17 -0
  26. data/lib/irb/command/internal_helpers.rb +27 -0
  27. data/lib/irb/{cmd → command}/irb_info.rb +7 -7
  28. data/lib/irb/{cmd → command}/load.rb +23 -8
  29. data/lib/irb/{cmd → command}/ls.rb +30 -14
  30. data/lib/irb/{cmd → command}/measure.rb +18 -17
  31. data/lib/irb/{cmd → command}/next.rb +3 -3
  32. data/lib/irb/command/pushws.rb +65 -0
  33. data/lib/irb/command/show_doc.rb +51 -0
  34. data/lib/irb/command/show_source.rb +74 -0
  35. data/lib/irb/{cmd → command}/step.rb +3 -3
  36. data/lib/irb/{cmd → command}/subirb.rb +31 -17
  37. data/lib/irb/{cmd → command}/whereami.rb +3 -5
  38. data/lib/irb/command.rb +23 -0
  39. data/lib/irb/completion.rb +74 -31
  40. data/lib/irb/context.rb +144 -57
  41. data/lib/irb/debug.rb +18 -0
  42. data/lib/irb/default_commands.rb +260 -0
  43. data/lib/irb/easter-egg.rb +16 -6
  44. data/lib/irb/ext/change-ws.rb +6 -8
  45. data/lib/irb/ext/eval_history.rb +3 -3
  46. data/lib/irb/ext/loader.rb +4 -4
  47. data/lib/irb/ext/multi-irb.rb +5 -5
  48. data/lib/irb/ext/tracer.rb +12 -51
  49. data/lib/irb/ext/use-loader.rb +6 -8
  50. data/lib/irb/ext/workspaces.rb +10 -34
  51. data/lib/irb/frame.rb +1 -1
  52. data/lib/irb/help.rb +3 -3
  53. data/lib/irb/helper_method/base.rb +16 -0
  54. data/lib/irb/helper_method/conf.rb +11 -0
  55. data/lib/irb/helper_method.rb +29 -0
  56. data/lib/irb/history.rb +15 -4
  57. data/lib/irb/init.rb +119 -52
  58. data/lib/irb/input-method.rb +77 -27
  59. data/lib/irb/inspector.rb +3 -3
  60. data/lib/irb/lc/error.rb +1 -11
  61. data/lib/irb/lc/help-message +4 -0
  62. data/lib/irb/lc/ja/error.rb +1 -11
  63. data/lib/irb/lc/ja/help-message +13 -0
  64. data/lib/irb/locale.rb +2 -2
  65. data/lib/irb/nesting_parser.rb +13 -3
  66. data/lib/irb/notifier.rb +1 -1
  67. data/lib/irb/output-method.rb +2 -8
  68. data/lib/irb/pager.rb +16 -11
  69. data/lib/irb/ruby-lex.rb +2 -2
  70. data/lib/irb/ruby_logo.aa +43 -0
  71. data/lib/irb/source_finder.rb +112 -37
  72. data/lib/irb/statement.rb +24 -24
  73. data/lib/irb/version.rb +3 -3
  74. data/lib/irb/workspace.rb +22 -6
  75. data/lib/irb/ws-for-case-2.rb +1 -1
  76. data/lib/irb/xmp.rb +3 -3
  77. data/lib/irb.rb +1071 -556
  78. data/man/irb.1 +7 -0
  79. metadata +41 -31
  80. data/lib/irb/cmd/backtrace.rb +0 -21
  81. data/lib/irb/cmd/break.rb +0 -21
  82. data/lib/irb/cmd/catch.rb +0 -21
  83. data/lib/irb/cmd/chws.rb +0 -36
  84. data/lib/irb/cmd/edit.rb +0 -60
  85. data/lib/irb/cmd/help.rb +0 -23
  86. data/lib/irb/cmd/info.rb +0 -21
  87. data/lib/irb/cmd/pushws.rb +0 -45
  88. data/lib/irb/cmd/show_cmds.rb +0 -53
  89. data/lib/irb/cmd/show_doc.rb +0 -48
  90. data/lib/irb/cmd/show_source.rb +0 -61
  91. data/lib/irb/extend-command.rb +0 -354
data/lib/irb/context.rb CHANGED
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #
3
3
  # irb/context.rb - irb context
4
4
  # by Keiju ISHITSUKA(keiju@ruby-lang.org)
@@ -22,10 +22,11 @@ module IRB
22
22
  # +other+:: uses this as InputMethod
23
23
  def initialize(irb, workspace = nil, input_method = nil)
24
24
  @irb = irb
25
+ @workspace_stack = []
25
26
  if workspace
26
- @workspace = workspace
27
+ @workspace_stack << workspace
27
28
  else
28
- @workspace = WorkSpace.new
29
+ @workspace_stack << WorkSpace.new
29
30
  end
30
31
  @thread = Thread.current
31
32
 
@@ -61,7 +62,7 @@ module IRB
61
62
  @io = nil
62
63
 
63
64
  self.inspect_mode = IRB.conf[:INSPECT_MODE]
64
- self.use_tracer = IRB.conf[:USE_TRACER] if IRB.conf[:USE_TRACER]
65
+ self.use_tracer = IRB.conf[:USE_TRACER]
65
66
  self.use_loader = IRB.conf[:USE_LOADER] if IRB.conf[:USE_LOADER]
66
67
  self.eval_history = IRB.conf[:EVAL_HISTORY] if IRB.conf[:EVAL_HISTORY]
67
68
 
@@ -77,28 +78,28 @@ module IRB
77
78
  else
78
79
  @irb_name = IRB.conf[:IRB_NAME]+"#"+IRB.JobManager.n_jobs.to_s
79
80
  end
80
- @irb_path = "(" + @irb_name + ")"
81
+ self.irb_path = "(" + @irb_name + ")"
81
82
 
82
83
  case input_method
83
84
  when nil
84
85
  @io = nil
85
86
  case use_multiline?
86
87
  when nil
87
- if STDIN.tty? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline?
88
+ if term_interactive? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline?
88
89
  # Both of multiline mode and singleline mode aren't specified.
89
- @io = RelineInputMethod.new
90
+ @io = RelineInputMethod.new(build_completor)
90
91
  else
91
92
  @io = nil
92
93
  end
93
94
  when false
94
95
  @io = nil
95
96
  when true
96
- @io = RelineInputMethod.new
97
+ @io = RelineInputMethod.new(build_completor)
97
98
  end
98
99
  unless @io
99
100
  case use_singleline?
100
101
  when nil
101
- if (defined?(ReadlineInputMethod) && STDIN.tty? &&
102
+ if (defined?(ReadlineInputMethod) && term_interactive? &&
102
103
  IRB.conf[:PROMPT_MODE] != :INF_RUBY)
103
104
  @io = ReadlineInputMethod.new
104
105
  else
@@ -121,11 +122,11 @@ module IRB
121
122
  when '-'
122
123
  @io = FileInputMethod.new($stdin)
123
124
  @irb_name = '-'
124
- @irb_path = '-'
125
+ self.irb_path = '-'
125
126
  when String
126
127
  @io = FileInputMethod.new(input_method)
127
128
  @irb_name = File.basename(input_method)
128
- @irb_path = input_method
129
+ self.irb_path = input_method
129
130
  else
130
131
  @io = input_method
131
132
  end
@@ -146,7 +147,74 @@ module IRB
146
147
  @newline_before_multiline_output = true
147
148
  end
148
149
 
149
- @command_aliases = IRB.conf[:COMMAND_ALIASES]
150
+ @user_aliases = IRB.conf[:COMMAND_ALIASES].dup
151
+ @command_aliases = @user_aliases.merge(KEYWORD_ALIASES)
152
+ end
153
+
154
+ private def term_interactive?
155
+ return true if ENV['TEST_IRB_FORCE_INTERACTIVE']
156
+ STDIN.tty? && ENV['TERM'] != 'dumb'
157
+ end
158
+
159
+ # because all input will eventually be evaluated as Ruby code,
160
+ # command names that conflict with Ruby keywords need special workaround
161
+ # we can remove them once we implemented a better command system for IRB
162
+ KEYWORD_ALIASES = {
163
+ :break => :irb_break,
164
+ :catch => :irb_catch,
165
+ :next => :irb_next,
166
+ }.freeze
167
+
168
+ private_constant :KEYWORD_ALIASES
169
+
170
+ def use_tracer=(val)
171
+ require_relative "ext/tracer" if val
172
+ IRB.conf[:USE_TRACER] = val
173
+ end
174
+
175
+ def eval_history=(val)
176
+ self.class.remove_method(__method__)
177
+ require_relative "ext/eval_history"
178
+ __send__(__method__, val)
179
+ end
180
+
181
+ def use_loader=(val)
182
+ self.class.remove_method(__method__)
183
+ require_relative "ext/use-loader"
184
+ __send__(__method__, val)
185
+ end
186
+
187
+ private def build_completor
188
+ completor_type = IRB.conf[:COMPLETOR]
189
+ case completor_type
190
+ when :regexp
191
+ return RegexpCompletor.new
192
+ when :type
193
+ completor = build_type_completor
194
+ return completor if completor
195
+ else
196
+ warn "Invalid value for IRB.conf[:COMPLETOR]: #{completor_type}"
197
+ end
198
+ # Fallback to RegexpCompletor
199
+ RegexpCompletor.new
200
+ end
201
+
202
+ private def build_type_completor
203
+ if RUBY_ENGINE == 'truffleruby'
204
+ # Avoid SyntaxError. truffleruby does not support endless method definition yet.
205
+ warn 'TypeCompletor is not supported on TruffleRuby yet'
206
+ return
207
+ end
208
+
209
+ begin
210
+ require 'repl_type_completor'
211
+ rescue LoadError => e
212
+ warn "TypeCompletor requires `gem repl_type_completor`: #{e.message}"
213
+ return
214
+ end
215
+
216
+ ReplTypeCompletor.preload_rbs
217
+ TypeCompletor.new(self)
150
218
  end
151
219
 
152
220
  def save_history=(val)
@@ -167,15 +235,24 @@ module IRB
167
235
  IRB.conf[:HISTORY_FILE] = hist
168
236
  end
169
237
 
238
+ # Workspace in the current context.
239
+ def workspace
240
+ @workspace_stack.last
241
+ end
242
+
243
+ # Replace the current workspace with the given +workspace+.
244
+ def replace_workspace(workspace)
245
+ @workspace_stack.pop
246
+ @workspace_stack.push(workspace)
247
+ end
248
+
170
249
  # The top-level workspace, see WorkSpace#main
171
250
  def main
172
- @workspace.main
251
+ workspace.main
173
252
  end
174
253
 
175
254
  # The toplevel workspace, see #home_workspace
176
255
  attr_reader :workspace_home
177
- # WorkSpace in the current context.
178
- attr_accessor :workspace
179
256
  # The current thread in this context.
180
257
  attr_reader :thread
181
258
  # The current input method.
@@ -196,9 +273,27 @@ module IRB
196
273
  # Can be either name from <code>IRB.conf[:IRB_NAME]</code>, or the number of
197
274
  # the current job set by JobManager, such as <code>irb#2</code>
198
275
  attr_accessor :irb_name
199
- # Can be either the #irb_name surrounded by parenthesis, or the
200
- # +input_method+ passed to Context.new
201
- attr_accessor :irb_path
276
+
277
+ # Can be one of the following:
278
+ # - the #irb_name surrounded by parenthesis
279
+ # - the +input_method+ passed to Context.new
280
+ # - the file path of the current IRB context in a binding.irb session
281
+ attr_reader :irb_path
282
+
283
+ # Sets @irb_path to the given +path+ as well as @eval_path
284
+ # @eval_path is used for evaluating code in the context of IRB session
285
+ # It's the same as irb_path, but with the IRB name postfix
286
+ # This makes sure users can distinguish the methods defined in the IRB session
287
+ # from the methods defined in the current file's context, especially with binding.irb
288
+ def irb_path=(path)
289
+ @irb_path = path
290
+
291
+ if File.exist?(path)
292
+ @eval_path = "#{path}(#{IRB.conf[:IRB_NAME]})"
293
+ else
294
+ @eval_path = path
295
+ end
296
+ end
202
297
 
203
298
  # Whether multiline editor mode is enabled or not.
204
299
  #
@@ -219,15 +314,15 @@ module IRB
219
314
  attr_reader :prompt_mode
220
315
  # Standard IRB prompt.
221
316
  #
222
- # See IRB@Customizing+the+IRB+Prompt for more information.
317
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
223
318
  attr_accessor :prompt_i
224
319
  # IRB prompt for continuated strings.
225
320
  #
226
- # See IRB@Customizing+the+IRB+Prompt for more information.
321
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
227
322
  attr_accessor :prompt_s
228
323
  # IRB prompt for continuated statement. (e.g. immediately after an +if+)
229
324
  #
230
- # See IRB@Customizing+the+IRB+Prompt for more information.
325
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
231
326
  attr_accessor :prompt_c
232
327
 
233
328
  # TODO: Remove this when developing v2.0
@@ -349,8 +444,6 @@ module IRB
349
444
  # The default value is 16.
350
445
  #
351
446
  # Can also be set using the +--back-trace-limit+ command line option.
352
- #
353
- # See IRB@Command+line+options for more command line options.
354
447
  attr_accessor :back_trace_limit
355
448
 
356
449
  # User-defined IRB command aliases
@@ -401,9 +494,7 @@ module IRB
401
494
  # StdioInputMethod or RelineInputMethod or ReadlineInputMethod, see #io
402
495
  # for more information.
403
496
  def prompting?
404
- verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) ||
405
- @io.kind_of?(RelineInputMethod) ||
406
- (defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod)))
497
+ verbose? || @io.prompting?
407
498
  end
408
499
 
409
500
  # The return value of the last statement evaluated.
@@ -413,12 +504,12 @@ module IRB
413
504
  # to #last_value.
414
505
  def set_last_value(value)
415
506
  @last_value = value
416
- @workspace.local_variable_set :_, value
507
+ workspace.local_variable_set :_, value
417
508
  end
418
509
 
419
510
  # Sets the +mode+ of the prompt in this context.
420
511
  #
421
- # See IRB@Customizing+the+IRB+Prompt for more information.
512
+ # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
422
513
  def prompt_mode=(mode)
423
514
  @prompt_mode = mode
424
515
  pconf = IRB.conf[:PROMPT][mode]
@@ -456,8 +547,6 @@ module IRB
456
547
  #
457
548
  # Can also be set using the +--inspect+ and +--noinspect+ command line
458
549
  # options.
459
- #
460
- # See IRB@Command+line+options for more command line options.
461
550
  def inspect_mode=(opt)
462
551
 
463
552
  if i = Inspector::INSPECTORS[opt]
@@ -501,45 +590,55 @@ module IRB
501
590
  @inspect_mode
502
591
  end
503
592
 
504
- def evaluate(line, line_no) # :nodoc:
593
+ def evaluate(statement, line_no) # :nodoc:
505
594
  @line_no = line_no
506
- result = nil
507
595
 
596
+ case statement
597
+ when Statement::EmptyInput
598
+ return
599
+ when Statement::Expression
600
+ result = evaluate_expression(statement.code, line_no)
601
+ set_last_value(result)
602
+ when Statement::Command
603
+ statement.command_class.execute(self, statement.arg)
604
+ set_last_value(nil)
605
+ end
606
+
607
+ nil
608
+ end
609
+
610
+ def from_binding?
611
+ @irb.from_binding
612
+ end
613
+
614
+ def evaluate_expression(code, line_no) # :nodoc:
615
+ result = nil
508
616
  if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
509
617
  IRB.set_measure_callback
510
618
  end
511
619
 
512
620
  if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
513
621
  last_proc = proc do
514
- result = @workspace.evaluate(line, irb_path, line_no)
622
+ result = workspace.evaluate(code, @eval_path, line_no)
515
623
  end
516
624
  IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) do |chain, item|
517
625
  _name, callback, arg = item
518
626
  proc do
519
- callback.(self, line, line_no, arg) do
627
+ callback.(self, code, line_no, arg) do
520
628
  chain.call
521
629
  end
522
630
  end
523
631
  end.call
524
632
  else
525
- result = @workspace.evaluate(line, irb_path, line_no)
633
+ result = workspace.evaluate(code, @eval_path, line_no)
526
634
  end
527
-
528
- set_last_value(result)
635
+ result
529
636
  end
530
637
 
531
638
  def inspect_last_value # :nodoc:
532
639
  @inspect_method.inspect_value(@last_value)
533
640
  end
534
641
 
535
- alias __exit__ exit
536
- # Exits the current session, see IRB.irb_exit
537
- def exit(ret = 0)
538
- IRB.irb_exit(@irb, ret)
539
- rescue UncaughtThrowError
540
- super
541
- end
542
-
543
642
  NOPRINTING_IVARS = ["@last_value"] # :nodoc:
544
643
  NO_INSPECTING_IVARS = ["@irb", "@io"] # :nodoc:
545
644
  IDNAME_IVARS = ["@prompt_mode"] # :nodoc:
@@ -570,17 +669,5 @@ module IRB
570
669
  def local_variables # :nodoc:
571
670
  workspace.binding.local_variables
572
671
  end
573
-
574
- # Return true if it's aliased from the argument and it's not an identifier.
575
- def symbol_alias?(command)
576
- return nil if command.match?(/\A\w+\z/)
577
- command_aliases.key?(command.to_sym)
578
- end
579
-
580
- # Return true if the command supports transforming args
581
- def transform_args?(command)
582
- command = command_aliases.fetch(command.to_sym, command)
583
- ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
584
- end
585
672
  end
586
673
  end
data/lib/irb/debug.rb CHANGED
@@ -57,6 +57,24 @@ module IRB
57
57
  DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB)
58
58
  end
59
59
 
60
+ if !@output_modifier_defined && !DEBUGGER__::CONFIG[:no_hint]
61
+ irb_output_modifier_proc = Reline.output_modifier_proc
62
+
63
+ Reline.output_modifier_proc = proc do |output, complete:|
64
+ unless output.strip.empty?
65
+ cmd = output.split(/\s/, 2).first
66
+
67
+ if !complete && DEBUGGER__.commands.key?(cmd)
68
+ output = output.sub(/\n$/, " # debug command\n")
69
+ end
70
+ end
71
+
72
+ irb_output_modifier_proc.call(output, complete: complete)
73
+ end
74
+
75
+ @output_modifier_defined = true
76
+ end
77
+
60
78
  true
61
79
  end
62
80
 
@@ -0,0 +1,260 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command"
4
+ require_relative "command/internal_helpers"
5
+ require_relative "command/context"
6
+ require_relative "command/exit"
7
+ require_relative "command/force_exit"
8
+ require_relative "command/chws"
9
+ require_relative "command/pushws"
10
+ require_relative "command/subirb"
11
+ require_relative "command/load"
12
+ require_relative "command/debug"
13
+ require_relative "command/edit"
14
+ require_relative "command/break"
15
+ require_relative "command/catch"
16
+ require_relative "command/next"
17
+ require_relative "command/delete"
18
+ require_relative "command/step"
19
+ require_relative "command/continue"
20
+ require_relative "command/finish"
21
+ require_relative "command/backtrace"
22
+ require_relative "command/info"
23
+ require_relative "command/help"
24
+ require_relative "command/show_doc"
25
+ require_relative "command/irb_info"
26
+ require_relative "command/ls"
27
+ require_relative "command/measure"
28
+ require_relative "command/show_source"
29
+ require_relative "command/whereami"
30
+ require_relative "command/history"
31
+
32
+ module IRB
33
+ module Command
34
+ NO_OVERRIDE = 0
35
+ OVERRIDE_PRIVATE_ONLY = 0x01
36
+ OVERRIDE_ALL = 0x02
37
+
38
+ class << self
39
+ # This API is for IRB's internal use only and may change at any time.
40
+ # Please do NOT use it.
41
+ def _register_with_aliases(name, command_class, *aliases)
42
+ @commands[name.to_sym] = [command_class, aliases]
43
+ end
44
+
45
+ def all_commands_info
46
+ user_aliases = IRB.CurrentContext.command_aliases.each_with_object({}) do |(alias_name, target), result|
47
+ result[target] ||= []
48
+ result[target] << alias_name
49
+ end
50
+
51
+ commands.map do |command_name, (command_class, aliases)|
52
+ aliases = aliases.map { |a| a.first }
53
+
54
+ if additional_aliases = user_aliases[command_name]
55
+ aliases += additional_aliases
56
+ end
57
+
58
+ display_name = aliases.shift || command_name
59
+ {
60
+ display_name: display_name,
61
+ description: command_class.description,
62
+ category: command_class.category
63
+ }
64
+ end
65
+ end
66
+
67
+ def command_override_policies
68
+ @@command_override_policies ||= commands.flat_map do |cmd_name, (cmd_class, aliases)|
69
+ [[cmd_name, OVERRIDE_ALL]] + aliases
70
+ end.to_h
71
+ end
72
+
73
+ def execute_as_command?(name, public_method:, private_method:)
74
+ case command_override_policies[name]
75
+ when OVERRIDE_ALL
76
+ true
77
+ when OVERRIDE_PRIVATE_ONLY
78
+ !public_method
79
+ when NO_OVERRIDE
80
+ !public_method && !private_method
81
+ end
82
+ end
83
+
84
+ def command_names
85
+ command_override_policies.keys.map(&:to_s)
86
+ end
87
+
88
+ # Convert a command name to its implementation class if such command exists
89
+ def load_command(command)
90
+ command = command.to_sym
91
+ commands.each do |command_name, (command_class, aliases)|
92
+ if command_name == command || aliases.any? { |alias_name, _| alias_name == command }
93
+ return command_class
94
+ end
95
+ end
96
+ nil
97
+ end
98
+ end
99
+
100
+ _register_with_aliases(:irb_context, Command::Context,
101
+ [:context, NO_OVERRIDE]
102
+ )
103
+
104
+ _register_with_aliases(:irb_exit, Command::Exit,
105
+ [:exit, OVERRIDE_PRIVATE_ONLY],
106
+ [:quit, OVERRIDE_PRIVATE_ONLY],
107
+ [:irb_quit, OVERRIDE_PRIVATE_ONLY]
108
+ )
109
+
110
+ _register_with_aliases(:irb_exit!, Command::ForceExit,
111
+ [:exit!, OVERRIDE_PRIVATE_ONLY]
112
+ )
113
+
114
+ _register_with_aliases(:irb_current_working_workspace, Command::CurrentWorkingWorkspace,
115
+ [:cwws, NO_OVERRIDE],
116
+ [:pwws, NO_OVERRIDE],
117
+ [:irb_print_working_workspace, OVERRIDE_ALL],
118
+ [:irb_cwws, OVERRIDE_ALL],
119
+ [:irb_pwws, OVERRIDE_ALL],
120
+ [:irb_current_working_binding, OVERRIDE_ALL],
121
+ [:irb_print_working_binding, OVERRIDE_ALL],
122
+ [:irb_cwb, OVERRIDE_ALL],
123
+ [:irb_pwb, OVERRIDE_ALL],
124
+ )
125
+
126
+ _register_with_aliases(:irb_change_workspace, Command::ChangeWorkspace,
127
+ [:chws, NO_OVERRIDE],
128
+ [:cws, NO_OVERRIDE],
129
+ [:irb_chws, OVERRIDE_ALL],
130
+ [:irb_cws, OVERRIDE_ALL],
131
+ [:irb_change_binding, OVERRIDE_ALL],
132
+ [:irb_cb, OVERRIDE_ALL],
133
+ [:cb, NO_OVERRIDE],
134
+ )
135
+
136
+ _register_with_aliases(:irb_workspaces, Command::Workspaces,
137
+ [:workspaces, NO_OVERRIDE],
138
+ [:irb_bindings, OVERRIDE_ALL],
139
+ [:bindings, NO_OVERRIDE],
140
+ )
141
+
142
+ _register_with_aliases(:irb_push_workspace, Command::PushWorkspace,
143
+ [:pushws, NO_OVERRIDE],
144
+ [:irb_pushws, OVERRIDE_ALL],
145
+ [:irb_push_binding, OVERRIDE_ALL],
146
+ [:irb_pushb, OVERRIDE_ALL],
147
+ [:pushb, NO_OVERRIDE],
148
+ )
149
+
150
+ _register_with_aliases(:irb_pop_workspace, Command::PopWorkspace,
151
+ [:popws, NO_OVERRIDE],
152
+ [:irb_popws, OVERRIDE_ALL],
153
+ [:irb_pop_binding, OVERRIDE_ALL],
154
+ [:irb_popb, OVERRIDE_ALL],
155
+ [:popb, NO_OVERRIDE],
156
+ )
157
+
158
+ _register_with_aliases(:irb_load, Command::Load)
159
+ _register_with_aliases(:irb_require, Command::Require)
160
+ _register_with_aliases(:irb_source, Command::Source,
161
+ [:source, NO_OVERRIDE]
162
+ )
163
+
164
+ _register_with_aliases(:irb, Command::IrbCommand)
165
+ _register_with_aliases(:irb_jobs, Command::Jobs,
166
+ [:jobs, NO_OVERRIDE]
167
+ )
168
+ _register_with_aliases(:irb_fg, Command::Foreground,
169
+ [:fg, NO_OVERRIDE]
170
+ )
171
+ _register_with_aliases(:irb_kill, Command::Kill,
172
+ [:kill, OVERRIDE_PRIVATE_ONLY]
173
+ )
174
+
175
+ _register_with_aliases(:irb_debug, Command::Debug,
176
+ [:debug, NO_OVERRIDE]
177
+ )
178
+ _register_with_aliases(:irb_edit, Command::Edit,
179
+ [:edit, NO_OVERRIDE]
180
+ )
181
+
182
+ _register_with_aliases(:irb_break, Command::Break)
183
+ _register_with_aliases(:irb_catch, Command::Catch)
184
+ _register_with_aliases(:irb_next, Command::Next)
185
+ _register_with_aliases(:irb_delete, Command::Delete,
186
+ [:delete, NO_OVERRIDE]
187
+ )
188
+
189
+ _register_with_aliases(:irb_step, Command::Step,
190
+ [:step, NO_OVERRIDE]
191
+ )
192
+ _register_with_aliases(:irb_continue, Command::Continue,
193
+ [:continue, NO_OVERRIDE]
194
+ )
195
+ _register_with_aliases(:irb_finish, Command::Finish,
196
+ [:finish, NO_OVERRIDE]
197
+ )
198
+ _register_with_aliases(:irb_backtrace, Command::Backtrace,
199
+ [:backtrace, NO_OVERRIDE],
200
+ [:bt, NO_OVERRIDE]
201
+ )
202
+
203
+ _register_with_aliases(:irb_debug_info, Command::Info,
204
+ [:info, NO_OVERRIDE]
205
+ )
206
+
207
+ _register_with_aliases(:irb_help, Command::Help,
208
+ [:help, NO_OVERRIDE],
209
+ [:show_cmds, NO_OVERRIDE]
210
+ )
211
+
212
+ _register_with_aliases(:irb_show_doc, Command::ShowDoc,
213
+ [:show_doc, NO_OVERRIDE]
214
+ )
215
+
216
+ _register_with_aliases(:irb_info, Command::IrbInfo)
217
+
218
+ _register_with_aliases(:irb_ls, Command::Ls,
219
+ [:ls, NO_OVERRIDE]
220
+ )
221
+
222
+ _register_with_aliases(:irb_measure, Command::Measure,
223
+ [:measure, NO_OVERRIDE]
224
+ )
225
+
226
+ _register_with_aliases(:irb_show_source, Command::ShowSource,
227
+ [:show_source, NO_OVERRIDE]
228
+ )
229
+
230
+ _register_with_aliases(:irb_whereami, Command::Whereami,
231
+ [:whereami, NO_OVERRIDE]
232
+ )
233
+
234
+ _register_with_aliases(:irb_history, Command::History,
235
+ [:history, NO_OVERRIDE],
236
+ [:hist, NO_OVERRIDE]
237
+ )
238
+ end
239
+
240
+ ExtendCommand = Command
241
+
242
+ # For backward compatibility, we need to keep this module:
243
+ # - As a container of helper methods
244
+ # - As a place to register commands with the deprecated def_extend_command method
245
+ module ExtendCommandBundle
246
+ # For backward compatibility
247
+ NO_OVERRIDE = Command::NO_OVERRIDE
248
+ OVERRIDE_PRIVATE_ONLY = Command::OVERRIDE_PRIVATE_ONLY
249
+ OVERRIDE_ALL = Command::OVERRIDE_ALL
250
+
251
+ # Deprecated. Doesn't have any effect.
252
+ @EXTEND_COMMANDS = []
253
+
254
+ # Drepcated. Use Command.regiser instead.
255
+ def self.def_extend_command(cmd_name, cmd_class, _, *aliases)
256
+ Command._register_with_aliases(cmd_name, cmd_class, *aliases)
257
+ Command.class_variable_set(:@@command_override_policies, nil)
258
+ end
259
+ end
260
+ end
@@ -98,18 +98,26 @@ module IRB
98
98
  end
99
99
  end
100
100
 
101
+ private def easter_egg_logo(type)
102
+ @easter_egg_logos ||= File.read(File.join(__dir__, 'ruby_logo.aa'), encoding: 'UTF-8:UTF-8')
103
+ .split(/TYPE: ([A-Z]+)\n/)[1..]
104
+ .each_slice(2)
105
+ .to_h
106
+ @easter_egg_logos[type.to_s.upcase]
107
+ end
108
+
101
109
  private def easter_egg(type = nil)
102
110
  type ||= [:logo, :dancing].sample
103
111
  case type
104
112
  when :logo
105
- File.open(File.join(__dir__, 'ruby_logo.aa')) do |f|
106
- require "rdoc"
107
- RDoc::RI::Driver.new.page do |io|
108
- IO.copy_stream(f, io)
109
- end
113
+ require "rdoc"
114
+ RDoc::RI::Driver.new.page do |io|
115
+ io.write easter_egg_logo(:large)
110
116
  end
111
117
  when :dancing
112
- begin
118
+ STDOUT.cooked do
119
+ interrupted = false
120
+ prev_trap = trap("SIGINT") { interrupted = true }
113
121
  canvas = Canvas.new(Reline.get_screen_size)
114
122
  Reline::IOGate.set_winch_handler do
115
123
  canvas = Canvas.new(Reline.get_screen_size)
@@ -125,10 +133,12 @@ module IRB
125
133
  buff[0, 20] = "\e[0mPress Ctrl+C to stop\e[31m\e[1m"
126
134
  print "\e[H" + buff
127
135
  sleep 0.05
136
+ break if interrupted
128
137
  end
129
138
  rescue Interrupt
130
139
  ensure
131
140
  print "\e[0m\e[?1049l"
141
+ trap("SIGINT", prev_trap)
132
142
  end
133
143
  end
134
144
  end