irb 1.7.1 → 1.13.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.document +1 -1
  3. data/Gemfile +10 -1
  4. data/README.md +265 -20
  5. data/Rakefile +13 -10
  6. data/doc/irb/irb.rd.ja +1 -3
  7. data/irb.gemspec +2 -1
  8. data/lib/irb/cmd/nop.rb +3 -52
  9. data/lib/irb/color.rb +4 -2
  10. data/lib/irb/command/backtrace.rb +17 -0
  11. data/lib/irb/command/base.rb +62 -0
  12. data/lib/irb/command/break.rb +17 -0
  13. data/lib/irb/command/catch.rb +17 -0
  14. data/lib/irb/command/chws.rb +40 -0
  15. data/lib/irb/command/context.rb +16 -0
  16. data/lib/irb/{cmd → command}/continue.rb +3 -3
  17. data/lib/irb/command/debug.rb +71 -0
  18. data/lib/irb/{cmd → command}/delete.rb +3 -3
  19. data/lib/irb/command/disable_irb.rb +19 -0
  20. data/lib/irb/command/edit.rb +63 -0
  21. data/lib/irb/command/exit.rb +18 -0
  22. data/lib/irb/{cmd → command}/finish.rb +3 -3
  23. data/lib/irb/command/force_exit.rb +18 -0
  24. data/lib/irb/command/help.rb +83 -0
  25. data/lib/irb/command/history.rb +45 -0
  26. data/lib/irb/command/info.rb +17 -0
  27. data/lib/irb/command/internal_helpers.rb +27 -0
  28. data/lib/irb/{cmd → command}/irb_info.rb +7 -7
  29. data/lib/irb/{cmd → command}/load.rb +23 -8
  30. data/lib/irb/{cmd → command}/ls.rb +42 -19
  31. data/lib/irb/{cmd → command}/measure.rb +18 -17
  32. data/lib/irb/{cmd → command}/next.rb +3 -3
  33. data/lib/irb/command/pushws.rb +65 -0
  34. data/lib/irb/command/show_doc.rb +51 -0
  35. data/lib/irb/command/show_source.rb +74 -0
  36. data/lib/irb/{cmd → command}/step.rb +3 -3
  37. data/lib/irb/command/subirb.rb +123 -0
  38. data/lib/irb/{cmd → command}/whereami.rb +3 -5
  39. data/lib/irb/command.rb +23 -0
  40. data/lib/irb/completion.rb +133 -102
  41. data/lib/irb/context.rb +182 -66
  42. data/lib/irb/debug/ui.rb +103 -0
  43. data/lib/irb/{cmd/debug.rb → debug.rb} +53 -59
  44. data/lib/irb/default_commands.rb +265 -0
  45. data/lib/irb/easter-egg.rb +16 -6
  46. data/lib/irb/ext/change-ws.rb +6 -8
  47. data/lib/irb/ext/{history.rb → eval_history.rb} +7 -7
  48. data/lib/irb/ext/loader.rb +4 -4
  49. data/lib/irb/ext/multi-irb.rb +5 -5
  50. data/lib/irb/ext/tracer.rb +12 -51
  51. data/lib/irb/ext/use-loader.rb +6 -8
  52. data/lib/irb/ext/workspaces.rb +10 -34
  53. data/lib/irb/frame.rb +1 -1
  54. data/lib/irb/help.rb +3 -3
  55. data/lib/irb/helper_method/base.rb +16 -0
  56. data/lib/irb/helper_method/conf.rb +11 -0
  57. data/lib/irb/helper_method.rb +29 -0
  58. data/lib/irb/{ext/save-history.rb → history.rb} +20 -58
  59. data/lib/irb/init.rb +154 -58
  60. data/lib/irb/input-method.rb +238 -203
  61. data/lib/irb/inspector.rb +3 -3
  62. data/lib/irb/lc/error.rb +1 -11
  63. data/lib/irb/lc/help-message +4 -0
  64. data/lib/irb/lc/ja/error.rb +1 -11
  65. data/lib/irb/lc/ja/help-message +13 -0
  66. data/lib/irb/locale.rb +2 -2
  67. data/lib/irb/nesting_parser.rb +13 -3
  68. data/lib/irb/notifier.rb +1 -1
  69. data/lib/irb/output-method.rb +2 -8
  70. data/lib/irb/pager.rb +91 -0
  71. data/lib/irb/ruby-lex.rb +391 -471
  72. data/lib/irb/ruby_logo.aa +43 -0
  73. data/lib/irb/source_finder.rb +139 -0
  74. data/lib/irb/statement.rb +80 -0
  75. data/lib/irb/version.rb +3 -3
  76. data/lib/irb/workspace.rb +24 -4
  77. data/lib/irb/ws-for-case-2.rb +1 -1
  78. data/lib/irb/xmp.rb +3 -3
  79. data/lib/irb.rb +1232 -604
  80. data/man/irb.1 +7 -0
  81. metadata +60 -32
  82. data/lib/irb/cmd/backtrace.rb +0 -21
  83. data/lib/irb/cmd/break.rb +0 -21
  84. data/lib/irb/cmd/catch.rb +0 -21
  85. data/lib/irb/cmd/chws.rb +0 -36
  86. data/lib/irb/cmd/edit.rb +0 -61
  87. data/lib/irb/cmd/help.rb +0 -23
  88. data/lib/irb/cmd/info.rb +0 -21
  89. data/lib/irb/cmd/pushws.rb +0 -45
  90. data/lib/irb/cmd/show_cmds.rb +0 -39
  91. data/lib/irb/cmd/show_doc.rb +0 -48
  92. data/lib/irb/cmd/show_source.rb +0 -113
  93. data/lib/irb/cmd/subirb.rb +0 -66
  94. data/lib/irb/extend-command.rb +0 -356
  95. data/lib/irb/src_encoding.rb +0 -7
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  #
3
3
  # irb/completion.rb -
4
4
  # by Keiju ISHITSUKA(keiju@ishitsuka.com)
@@ -8,30 +8,7 @@
8
8
  require_relative 'ruby-lex'
9
9
 
10
10
  module IRB
11
- module InputCompletor # :nodoc:
12
- using Module.new {
13
- refine ::Binding do
14
- def eval_methods
15
- ::Kernel.instance_method(:methods).bind(eval("self")).call
16
- end
17
-
18
- def eval_private_methods
19
- ::Kernel.instance_method(:private_methods).bind(eval("self")).call
20
- end
21
-
22
- def eval_instance_variables
23
- ::Kernel.instance_method(:instance_variables).bind(eval("self")).call
24
- end
25
-
26
- def eval_global_variables
27
- ::Kernel.instance_method(:global_variables).bind(eval("self")).call
28
- end
29
-
30
- def eval_class_constants
31
- ::Module.instance_method(:constants).bind(eval("self.class")).call
32
- end
33
- end
34
- }
11
+ class BaseCompletor # :nodoc:
35
12
 
36
13
  # Set of reserved words used by Ruby, you should not use these for
37
14
  # constants or variables
@@ -56,7 +33,13 @@ module IRB
56
33
  yield
57
34
  ]
58
35
 
59
- BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
36
+ def completion_candidates(preposing, target, postposing, bind:)
37
+ raise NotImplementedError
38
+ end
39
+
40
+ def doc_namespace(preposing, matched, postposing, bind:)
41
+ raise NotImplementedError
42
+ end
60
43
 
61
44
  GEM_PATHS =
62
45
  if defined?(Gem::Specification)
@@ -73,7 +56,7 @@ module IRB
73
56
  []
74
57
  end.freeze
75
58
 
76
- def self.retrieve_gem_and_system_load_path
59
+ def retrieve_gem_and_system_load_path
77
60
  candidates = (GEM_PATHS | $LOAD_PATH)
78
61
  candidates.map do |p|
79
62
  if p.respond_to?(:to_path)
@@ -84,8 +67,8 @@ module IRB
84
67
  end.compact.sort
85
68
  end
86
69
 
87
- def self.retrieve_files_to_require_from_load_path
88
- @@files_from_load_path ||=
70
+ def retrieve_files_to_require_from_load_path
71
+ @files_from_load_path ||=
89
72
  (
90
73
  shortest = []
91
74
  rest = retrieve_gem_and_system_load_path.each_with_object([]) { |path, result|
@@ -103,13 +86,74 @@ module IRB
103
86
  )
104
87
  end
105
88
 
106
- def self.retrieve_files_to_require_relative_from_current_dir
107
- @@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
89
+ def command_completions(preposing, target)
90
+ if preposing.empty? && !target.empty?
91
+ IRB::Command.command_names.select { _1.start_with?(target) }
92
+ else
93
+ []
94
+ end
95
+ end
96
+
97
+ def retrieve_files_to_require_relative_from_current_dir
98
+ @files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
108
99
  path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
109
100
  }
110
101
  end
102
+ end
103
+
104
+ class TypeCompletor < BaseCompletor # :nodoc:
105
+ def initialize(context)
106
+ @context = context
107
+ end
108
+
109
+ def inspect
110
+ ReplTypeCompletor.info
111
+ end
112
+
113
+ def completion_candidates(preposing, target, _postposing, bind:)
114
+ commands = command_completions(preposing, target)
115
+ result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)
116
+ return commands unless result
117
+
118
+ commands | result.completion_candidates.map { target + _1 }
119
+ end
120
+
121
+ def doc_namespace(preposing, matched, _postposing, bind:)
122
+ result = ReplTypeCompletor.analyze(preposing + matched, binding: bind, filename: @context.irb_path)
123
+ result&.doc_namespace('')
124
+ end
125
+ end
126
+
127
+ class RegexpCompletor < BaseCompletor # :nodoc:
128
+ using Module.new {
129
+ refine ::Binding do
130
+ def eval_methods
131
+ ::Kernel.instance_method(:methods).bind(eval("self")).call
132
+ end
133
+
134
+ def eval_private_methods
135
+ ::Kernel.instance_method(:private_methods).bind(eval("self")).call
136
+ end
137
+
138
+ def eval_instance_variables
139
+ ::Kernel.instance_method(:instance_variables).bind(eval("self")).call
140
+ end
141
+
142
+ def eval_global_variables
143
+ ::Kernel.instance_method(:global_variables).bind(eval("self")).call
144
+ end
145
+
146
+ def eval_class_constants
147
+ ::Module.instance_method(:constants).bind(eval("self.class")).call
148
+ end
149
+ end
150
+ }
151
+
152
+ def inspect
153
+ 'RegexpCompletor'
154
+ end
111
155
 
112
- CompletionRequireProc = lambda { |target, preposing = nil, postposing = nil|
156
+ def complete_require_path(target, preposing, postposing)
113
157
  if target =~ /\A(['"])([^'"]+)\Z/
114
158
  quote = $1
115
159
  actual_target = $2
@@ -124,39 +168,38 @@ module IRB
124
168
  break
125
169
  end
126
170
  end
127
- result = []
128
- if tok && tok.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
129
- case tok.tok
130
- when 'require'
131
- result = retrieve_files_to_require_from_load_path.select { |path|
132
- path.start_with?(actual_target)
133
- }.map { |path|
134
- quote + path
135
- }
136
- when 'require_relative'
137
- result = retrieve_files_to_require_relative_from_current_dir.select { |path|
138
- path.start_with?(actual_target)
139
- }.map { |path|
140
- quote + path
141
- }
142
- end
171
+ return unless tok&.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
172
+
173
+ case tok.tok
174
+ when 'require'
175
+ retrieve_files_to_require_from_load_path.select { |path|
176
+ path.start_with?(actual_target)
177
+ }.map { |path|
178
+ quote + path
179
+ }
180
+ when 'require_relative'
181
+ retrieve_files_to_require_relative_from_current_dir.select { |path|
182
+ path.start_with?(actual_target)
183
+ }.map { |path|
184
+ quote + path
185
+ }
143
186
  end
144
- result
145
- }
187
+ end
146
188
 
147
- CompletionProc = lambda { |target, preposing = nil, postposing = nil|
189
+ def completion_candidates(preposing, target, postposing, bind:)
148
190
  if preposing && postposing
149
- result = CompletionRequireProc.(target, preposing, postposing)
150
- unless result
151
- result = retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
152
- end
153
- result
154
- else
155
- retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
191
+ result = complete_require_path(target, preposing, postposing)
192
+ return result if result
156
193
  end
157
- }
194
+ commands = command_completions(preposing || '', target)
195
+ commands | retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
196
+ end
197
+
198
+ def doc_namespace(_preposing, matched, _postposing, bind:)
199
+ retrieve_completion_data(matched, bind: bind, doc_namespace: true)
200
+ end
158
201
 
159
- def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
202
+ def retrieve_completion_data(input, bind:, doc_namespace:)
160
203
  case input
161
204
  # this regexp only matches the closing character because of irb's Reline.completer_quote_characters setting
162
205
  # details are described in: https://github.com/ruby/irb/pull/523
@@ -199,16 +242,16 @@ module IRB
199
242
  end
200
243
 
201
244
  when /^([^\}]*\})\.([^.]*)$/
202
- # Proc or Hash
245
+ # Hash or Proc
203
246
  receiver = $1
204
247
  message = $2
205
248
 
206
249
  if doc_namespace
207
- ["Proc.#{message}", "Hash.#{message}"]
250
+ ["Hash.#{message}", "Proc.#{message}"]
208
251
  else
209
- proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
210
252
  hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
211
- select_message(receiver, message, proc_candidates | hash_candidates)
253
+ proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
254
+ select_message(receiver, message, hash_candidates | proc_candidates)
212
255
  end
213
256
 
214
257
  when /^(:[^:.]+)$/
@@ -356,7 +399,7 @@ module IRB
356
399
 
357
400
  if doc_namespace
358
401
  rec_class = rec.is_a?(Module) ? rec : rec.class
359
- "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}"
402
+ "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}" rescue nil
360
403
  else
361
404
  select_message(receiver, message, candidates, sep)
362
405
  end
@@ -374,13 +417,19 @@ module IRB
374
417
  else
375
418
  select_message(receiver, message, candidates.sort)
376
419
  end
377
-
420
+ when /^\s*$/
421
+ # empty input
422
+ if doc_namespace
423
+ nil
424
+ else
425
+ []
426
+ end
378
427
  else
379
428
  if doc_namespace
380
429
  vars = (bind.local_variables | bind.eval_instance_variables).collect{|m| m.to_s}
381
430
  perfect_match_var = vars.find{|m| m.to_s == input}
382
431
  if perfect_match_var
383
- eval("#{perfect_match_var}.class.name", bind)
432
+ eval("#{perfect_match_var}.class.name", bind) rescue nil
384
433
  else
385
434
  candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
386
435
  candidates |= ReservedWords
@@ -394,44 +443,10 @@ module IRB
394
443
  end
395
444
  end
396
445
 
397
- PerfectMatchedProc = ->(matched, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding) {
398
- begin
399
- require 'rdoc'
400
- rescue LoadError
401
- return
402
- end
403
-
404
- RDocRIDriver ||= RDoc::RI::Driver.new
405
-
406
- if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
407
- IRB.__send__(:easter_egg)
408
- return
409
- end
410
-
411
- namespace = retrieve_completion_data(matched, bind: bind, doc_namespace: true)
412
- return unless namespace
413
-
414
- if namespace.is_a?(Array)
415
- out = RDoc::Markup::Document.new
416
- namespace.each do |m|
417
- begin
418
- RDocRIDriver.add_method(out, m)
419
- rescue RDoc::RI::Driver::NotFoundError
420
- end
421
- end
422
- RDocRIDriver.display(out)
423
- else
424
- begin
425
- RDocRIDriver.display_names([namespace])
426
- rescue RDoc::RI::Driver::NotFoundError
427
- end
428
- end
429
- }
430
-
431
446
  # Set of available operators in Ruby
432
447
  Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
433
448
 
434
- def self.select_message(receiver, message, candidates, sep = ".")
449
+ def select_message(receiver, message, candidates, sep = ".")
435
450
  candidates.grep(/^#{Regexp.quote(message)}/).collect do |e|
436
451
  case e
437
452
  when /^[a-zA-Z_]/
@@ -443,4 +458,20 @@ module IRB
443
458
  end
444
459
  end
445
460
  end
461
+
462
+ module InputCompletor
463
+ class << self
464
+ private def regexp_completor
465
+ @regexp_completor ||= RegexpCompletor.new
466
+ end
467
+
468
+ def retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
469
+ regexp_completor.retrieve_completion_data(input, bind: bind, doc_namespace: doc_namespace)
470
+ end
471
+ end
472
+ CompletionProc = ->(target, preposing = nil, postposing = nil) {
473
+ regexp_completor.completion_candidates(preposing, target, postposing, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding)
474
+ }
475
+ end
476
+ deprecate_constant :InputCompletor
446
477
  end