irb 1.8.2 → 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.
@@ -0,0 +1,426 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'methods'
4
+
5
+ module IRB
6
+ module TypeCompletion
7
+ module Types
8
+ OBJECT_TO_TYPE_SAMPLE_SIZE = 50
9
+
10
+ singleton_class.attr_reader :rbs_builder, :rbs_load_error
11
+
12
+ def self.preload_in_thread
13
+ return if @preload_started
14
+
15
+ @preload_started = true
16
+ Thread.new do
17
+ load_rbs_builder
18
+ end
19
+ end
20
+
21
+ def self.load_rbs_builder
22
+ require 'rbs'
23
+ require 'rbs/cli'
24
+ loader = RBS::CLI::LibraryOptions.new.loader
25
+ loader.add path: Pathname('sig')
26
+ @rbs_builder = RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names
27
+ rescue LoadError, StandardError => e
28
+ @rbs_load_error = e
29
+ nil
30
+ end
31
+
32
+ def self.class_name_of(klass)
33
+ klass = klass.superclass if klass.singleton_class?
34
+ Methods::MODULE_NAME_METHOD.bind_call klass
35
+ end
36
+
37
+ def self.rbs_search_method(klass, method_name, singleton)
38
+ klass.ancestors.each do |ancestor|
39
+ name = class_name_of ancestor
40
+ next unless name && rbs_builder
41
+ type_name = RBS::TypeName(name).absolute!
42
+ definition = (singleton ? rbs_builder.build_singleton(type_name) : rbs_builder.build_instance(type_name)) rescue nil
43
+ method = definition.methods[method_name] if definition
44
+ return method if method
45
+ end
46
+ nil
47
+ end
48
+
49
+ def self.method_return_type(type, method_name)
50
+ receivers = type.types.map do |t|
51
+ case t
52
+ in SingletonType
53
+ [t, t.module_or_class, true]
54
+ in InstanceType
55
+ [t, t.klass, false]
56
+ end
57
+ end
58
+ types = receivers.flat_map do |receiver_type, klass, singleton|
59
+ method = rbs_search_method klass, method_name, singleton
60
+ next [] unless method
61
+ method.method_types.map do |method|
62
+ from_rbs_type(method.type.return_type, receiver_type, {})
63
+ end
64
+ end
65
+ UnionType[*types]
66
+ end
67
+
68
+ def self.rbs_methods(type, method_name, args_types, kwargs_type, has_block)
69
+ return [] unless rbs_builder
70
+
71
+ receivers = type.types.map do |t|
72
+ case t
73
+ in SingletonType
74
+ [t, t.module_or_class, true]
75
+ in InstanceType
76
+ [t, t.klass, false]
77
+ end
78
+ end
79
+ has_splat = args_types.include?(nil)
80
+ methods_with_score = receivers.flat_map do |receiver_type, klass, singleton|
81
+ method = rbs_search_method klass, method_name, singleton
82
+ next [] unless method
83
+ method.method_types.map do |method_type|
84
+ score = 0
85
+ score += 2 if !!method_type.block == has_block
86
+ reqs = method_type.type.required_positionals
87
+ opts = method_type.type.optional_positionals
88
+ rest = method_type.type.rest_positionals
89
+ trailings = method_type.type.trailing_positionals
90
+ keyreqs = method_type.type.required_keywords
91
+ keyopts = method_type.type.optional_keywords
92
+ keyrest = method_type.type.rest_keywords
93
+ args = args_types
94
+ if kwargs_type&.any? && keyreqs.empty? && keyopts.empty? && keyrest.nil?
95
+ kw_value_type = UnionType[*kwargs_type.values]
96
+ args += [InstanceType.new(Hash, K: SYMBOL, V: kw_value_type)]
97
+ end
98
+ if has_splat
99
+ score += 1 if args.count(&:itself) <= reqs.size + opts.size + trailings.size
100
+ elsif reqs.size + trailings.size <= args.size && (rest || args.size <= reqs.size + opts.size + trailings.size)
101
+ score += 2
102
+ centers = args[reqs.size...-trailings.size]
103
+ given = args.first(reqs.size) + centers.take(opts.size) + args.last(trailings.size)
104
+ expected = (reqs + opts.take(centers.size) + trailings).map(&:type)
105
+ if rest
106
+ given << UnionType[*centers.drop(opts.size)]
107
+ expected << rest.type
108
+ end
109
+ if given.any?
110
+ score += given.zip(expected).count do |t, e|
111
+ e = from_rbs_type e, receiver_type
112
+ intersect?(t, e) || (intersect?(STRING, e) && t.methods.include?(:to_str)) || (intersect?(INTEGER, e) && t.methods.include?(:to_int)) || (intersect?(ARRAY, e) && t.methods.include?(:to_ary))
113
+ end.fdiv(given.size)
114
+ end
115
+ end
116
+ [[method_type, given || [], expected || []], score]
117
+ end
118
+ end
119
+ max_score = methods_with_score.map(&:last).max
120
+ methods_with_score.select { _2 == max_score }.map(&:first)
121
+ end
122
+
123
+ def self.intersect?(a, b)
124
+ atypes = a.types.group_by(&:class)
125
+ btypes = b.types.group_by(&:class)
126
+ if atypes[SingletonType] && btypes[SingletonType]
127
+ aa, bb = [atypes, btypes].map {|types| types[SingletonType].map(&:module_or_class) }
128
+ return true if (aa & bb).any?
129
+ end
130
+
131
+ aa, bb = [atypes, btypes].map {|types| (types[InstanceType] || []).map(&:klass) }
132
+ (aa.flat_map(&:ancestors) & bb).any?
133
+ end
134
+
135
+ def self.type_from_object(object)
136
+ case object
137
+ when Array
138
+ InstanceType.new Array, { Elem: union_type_from_objects(object) }
139
+ when Hash
140
+ InstanceType.new Hash, { K: union_type_from_objects(object.keys), V: union_type_from_objects(object.values) }
141
+ when Module
142
+ SingletonType.new object
143
+ else
144
+ klass = Methods::OBJECT_SINGLETON_CLASS_METHOD.bind_call(object) rescue Methods::OBJECT_CLASS_METHOD.bind_call(object)
145
+ InstanceType.new klass
146
+ end
147
+ end
148
+
149
+ def self.union_type_from_objects(objects)
150
+ values = objects.size <= OBJECT_TO_TYPE_SAMPLE_SIZE ? objects : objects.sample(OBJECT_TO_TYPE_SAMPLE_SIZE)
151
+ klasses = values.map { Methods::OBJECT_CLASS_METHOD.bind_call(_1) }
152
+ UnionType[*klasses.uniq.map { InstanceType.new _1 }]
153
+ end
154
+
155
+ class SingletonType
156
+ attr_reader :module_or_class
157
+ def initialize(module_or_class)
158
+ @module_or_class = module_or_class
159
+ end
160
+ def transform() = yield(self)
161
+ def methods() = @module_or_class.methods
162
+ def all_methods() = methods | Kernel.methods
163
+ def constants() = @module_or_class.constants
164
+ def types() = [self]
165
+ def nillable?() = false
166
+ def nonnillable() = self
167
+ def inspect
168
+ "#{module_or_class}.itself"
169
+ end
170
+ end
171
+
172
+ class InstanceType
173
+ attr_reader :klass, :params
174
+ def initialize(klass, params = {})
175
+ @klass = klass
176
+ @params = params
177
+ end
178
+ def transform() = yield(self)
179
+ def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
180
+ def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
181
+ def constants() = []
182
+ def types() = [self]
183
+ def nillable?() = (@klass == NilClass)
184
+ def nonnillable() = self
185
+ def rbs_methods
186
+ name = Types.class_name_of(@klass)
187
+ return {} unless name && Types.rbs_builder
188
+
189
+ type_name = RBS::TypeName(name).absolute!
190
+ Types.rbs_builder.build_instance(type_name).methods rescue {}
191
+ end
192
+ def inspect
193
+ if params.empty?
194
+ inspect_without_params
195
+ else
196
+ params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
197
+ "#{inspect_without_params}#{params_string}"
198
+ end
199
+ end
200
+ def inspect_without_params
201
+ if klass == NilClass
202
+ 'nil'
203
+ elsif klass == TrueClass
204
+ 'true'
205
+ elsif klass == FalseClass
206
+ 'false'
207
+ else
208
+ klass.singleton_class? ? klass.superclass.to_s : klass.to_s
209
+ end
210
+ end
211
+ end
212
+
213
+ NIL = InstanceType.new NilClass
214
+ OBJECT = InstanceType.new Object
215
+ TRUE = InstanceType.new TrueClass
216
+ FALSE = InstanceType.new FalseClass
217
+ SYMBOL = InstanceType.new Symbol
218
+ STRING = InstanceType.new String
219
+ INTEGER = InstanceType.new Integer
220
+ RANGE = InstanceType.new Range
221
+ REGEXP = InstanceType.new Regexp
222
+ FLOAT = InstanceType.new Float
223
+ RATIONAL = InstanceType.new Rational
224
+ COMPLEX = InstanceType.new Complex
225
+ ARRAY = InstanceType.new Array
226
+ HASH = InstanceType.new Hash
227
+ CLASS = InstanceType.new Class
228
+ MODULE = InstanceType.new Module
229
+ PROC = InstanceType.new Proc
230
+
231
+ class UnionType
232
+ attr_reader :types
233
+
234
+ def initialize(*types)
235
+ @types = []
236
+ singletons = []
237
+ instances = {}
238
+ collect = -> type do
239
+ case type
240
+ in UnionType
241
+ type.types.each(&collect)
242
+ in InstanceType
243
+ params = (instances[type.klass] ||= {})
244
+ type.params.each do |k, v|
245
+ (params[k] ||= []) << v
246
+ end
247
+ in SingletonType
248
+ singletons << type
249
+ end
250
+ end
251
+ types.each(&collect)
252
+ @types = singletons.uniq + instances.map do |klass, params|
253
+ InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
254
+ end
255
+ end
256
+
257
+ def transform(&block)
258
+ UnionType[*types.map(&block)]
259
+ end
260
+
261
+ def nillable?
262
+ types.any?(&:nillable?)
263
+ end
264
+
265
+ def nonnillable
266
+ UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
267
+ end
268
+
269
+ def self.[](*types)
270
+ type = new(*types)
271
+ if type.types.empty?
272
+ OBJECT
273
+ elsif type.types.size == 1
274
+ type.types.first
275
+ else
276
+ type
277
+ end
278
+ end
279
+
280
+ def methods() = @types.flat_map(&:methods).uniq
281
+ def all_methods() = @types.flat_map(&:all_methods).uniq
282
+ def constants() = @types.flat_map(&:constants).uniq
283
+ def inspect() = @types.map(&:inspect).join(' | ')
284
+ end
285
+
286
+ BOOLEAN = UnionType[TRUE, FALSE]
287
+
288
+ def self.array_of(*types)
289
+ type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
290
+ InstanceType.new Array, Elem: type
291
+ end
292
+
293
+ def self.from_rbs_type(return_type, self_type, extra_vars = {})
294
+ case return_type
295
+ when RBS::Types::Bases::Self
296
+ self_type
297
+ when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
298
+ NIL
299
+ when RBS::Types::Bases::Any, RBS::Types::Bases::Void
300
+ OBJECT
301
+ when RBS::Types::Bases::Class
302
+ self_type.transform do |type|
303
+ case type
304
+ in SingletonType
305
+ InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
306
+ in InstanceType
307
+ SingletonType.new type.klass
308
+ end
309
+ end
310
+ UnionType[*types]
311
+ when RBS::Types::Bases::Bool
312
+ BOOLEAN
313
+ when RBS::Types::Bases::Instance
314
+ self_type.transform do |type|
315
+ if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
316
+ InstanceType.new type.module_or_class
317
+ else
318
+ OBJECT
319
+ end
320
+ end
321
+ when RBS::Types::Union
322
+ UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
323
+ when RBS::Types::Proc
324
+ PROC
325
+ when RBS::Types::Tuple
326
+ elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
327
+ InstanceType.new Array, Elem: elem
328
+ when RBS::Types::Record
329
+ InstanceType.new Hash, K: SYMBOL, V: OBJECT
330
+ when RBS::Types::Literal
331
+ InstanceType.new return_type.literal.class
332
+ when RBS::Types::Variable
333
+ if extra_vars.key? return_type.name
334
+ extra_vars[return_type.name]
335
+ elsif self_type.is_a? InstanceType
336
+ self_type.params[return_type.name] || OBJECT
337
+ elsif self_type.is_a? UnionType
338
+ types = self_type.types.filter_map do |t|
339
+ t.params[return_type.name] if t.is_a? InstanceType
340
+ end
341
+ UnionType[*types]
342
+ else
343
+ OBJECT
344
+ end
345
+ when RBS::Types::Optional
346
+ UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
347
+ when RBS::Types::Alias
348
+ case return_type.name.name
349
+ when :int
350
+ INTEGER
351
+ when :boolish
352
+ BOOLEAN
353
+ when :string
354
+ STRING
355
+ else
356
+ # TODO: ???
357
+ OBJECT
358
+ end
359
+ when RBS::Types::Interface
360
+ # unimplemented
361
+ OBJECT
362
+ when RBS::Types::ClassInstance
363
+ klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
364
+ if return_type.args
365
+ args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
366
+ names = rbs_builder.build_singleton(return_type.name).type_params
367
+ params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
368
+ end
369
+ InstanceType.new klass, params || {}
370
+ end
371
+ end
372
+
373
+ def self.method_return_bottom?(method)
374
+ method.type.return_type.is_a? RBS::Types::Bases::Bottom
375
+ end
376
+
377
+ def self.match_free_variables(vars, types, values)
378
+ accumulator = {}
379
+ types.zip values do |t, v|
380
+ _match_free_variable(vars, t, v, accumulator) if v
381
+ end
382
+ accumulator.transform_values { UnionType[*_1] }
383
+ end
384
+
385
+ def self._match_free_variable(vars, rbs_type, value, accumulator)
386
+ case [rbs_type, value]
387
+ in [RBS::Types::Variable,]
388
+ (accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
389
+ in [RBS::Types::ClassInstance, InstanceType]
390
+ names = rbs_builder.build_singleton(rbs_type.name).type_params
391
+ names.zip(rbs_type.args).each do |name, arg|
392
+ v = value.params[name]
393
+ _match_free_variable vars, arg, v, accumulator if v
394
+ end
395
+ in [RBS::Types::Tuple, InstanceType] if value.klass == Array
396
+ v = value.params[:Elem]
397
+ rbs_type.types.each do |t|
398
+ _match_free_variable vars, t, v, accumulator
399
+ end
400
+ in [RBS::Types::Record, InstanceType] if value.klass == Hash
401
+ # TODO
402
+ in [RBS::Types::Interface,]
403
+ definition = rbs_builder.build_interface rbs_type.name
404
+ convert = {}
405
+ definition.type_params.zip(rbs_type.args).each do |from, arg|
406
+ convert[from] = arg.name if arg.is_a? RBS::Types::Variable
407
+ end
408
+ return if convert.empty?
409
+ ac = {}
410
+ definition.methods.each do |method_name, method|
411
+ return_type = method_return_type value, method_name
412
+ method.defs.each do |method_def|
413
+ interface_return_type = method_def.type.type.return_type
414
+ _match_free_variable convert, interface_return_type, return_type, ac
415
+ end
416
+ end
417
+ convert.each do |from, to|
418
+ values = ac[from]
419
+ (accumulator[to] ||= []).concat values if values
420
+ end
421
+ else
422
+ end
423
+ end
424
+ end
425
+ end
426
+ end
data/lib/irb/version.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  #
6
6
 
7
7
  module IRB # :nodoc:
8
- VERSION = "1.8.2"
8
+ VERSION = "1.9.0"
9
9
  @RELEASE_VERSION = VERSION
10
- @LAST_UPDATE_DATE = "2023-10-12"
10
+ @LAST_UPDATE_DATE = "2023-11-11"
11
11
  end
data/lib/irb.rb CHANGED
@@ -140,6 +140,10 @@ require_relative "irb/debug"
140
140
  #
141
141
  # IRB.conf[:USE_AUTOCOMPLETE] = false
142
142
  #
143
+ # To enable enhanced completion using type information, add the following to your +.irbrc+:
144
+ #
145
+ # IRB.conf[:COMPLETOR] = :type
146
+ #
143
147
  # === History
144
148
  #
145
149
  # By default, irb will store the last 1000 commands you used in
@@ -367,24 +371,6 @@ module IRB
367
371
  # An exception raised by IRB.irb_abort
368
372
  class Abort < Exception;end
369
373
 
370
- @CONF = {}
371
- # Displays current configuration.
372
- #
373
- # Modifying the configuration is achieved by sending a message to IRB.conf.
374
- #
375
- # See IRB@Configuration for more information.
376
- def IRB.conf
377
- @CONF
378
- end
379
-
380
- # Returns the current version of IRB, including release version and last
381
- # updated date.
382
- def IRB.version
383
- if v = @CONF[:VERSION] then return v end
384
-
385
- @CONF[:VERSION] = format("irb %s (%s)", @RELEASE_VERSION, @LAST_UPDATE_DATE)
386
- end
387
-
388
374
  # The current IRB::Context of the session, see IRB.conf
389
375
  #
390
376
  # irb
@@ -431,6 +417,11 @@ module IRB
431
417
  PROMPT_MAIN_TRUNCATE_OMISSION = '...'.freeze
432
418
  CONTROL_CHARACTERS_PATTERN = "\x00-\x1F".freeze
433
419
 
420
+ # Returns the current context of this irb session
421
+ attr_reader :context
422
+ # The lexer used by this irb session
423
+ attr_accessor :scanner
424
+
434
425
  # Creates a new irb session
435
426
  def initialize(workspace = nil, input_method = nil)
436
427
  @context = Context.new(self, workspace, input_method)
@@ -509,41 +500,6 @@ module IRB
509
500
  end
510
501
  end
511
502
 
512
- # Returns the current context of this irb session
513
- attr_reader :context
514
- # The lexer used by this irb session
515
- attr_accessor :scanner
516
-
517
- private def generate_prompt(opens, continue, line_offset)
518
- ltype = @scanner.ltype_from_open_tokens(opens)
519
- indent = @scanner.calc_indent_level(opens)
520
- continue = opens.any? || continue
521
- line_no = @line_no + line_offset
522
-
523
- if ltype
524
- f = @context.prompt_s
525
- elsif continue
526
- f = @context.prompt_c
527
- else
528
- f = @context.prompt_i
529
- end
530
- f = "" unless f
531
- if @context.prompting?
532
- p = format_prompt(f, ltype, indent, line_no)
533
- else
534
- p = ""
535
- end
536
- if @context.auto_indent_mode and !@context.io.respond_to?(:auto_indent)
537
- unless ltype
538
- prompt_i = @context.prompt_i.nil? ? "" : @context.prompt_i
539
- ind = format_prompt(prompt_i, ltype, indent, line_no)[/.*\z/].size +
540
- indent * 2 - p.size
541
- p += " " * ind if ind > 0
542
- end
543
- end
544
- p
545
- end
546
-
547
503
  # Evaluates input for this session.
548
504
  def eval_input
549
505
  configure_io
@@ -835,16 +791,6 @@ module IRB
835
791
  end
836
792
  end
837
793
 
838
- # Evaluates the given block using the given +context+ as the Context.
839
- def suspend_context(context)
840
- @context, back_context = context, @context
841
- begin
842
- yield back_context
843
- ensure
844
- @context = back_context
845
- end
846
- end
847
-
848
794
  # Handler for the signal SIGINT, see Kernel#trap for more information.
849
795
  def signal_handle
850
796
  unless @context.ignore_sigint?
@@ -880,52 +826,6 @@ module IRB
880
826
  end
881
827
  end
882
828
 
883
- private def truncate_prompt_main(str) # :nodoc:
884
- str = str.tr(CONTROL_CHARACTERS_PATTERN, ' ')
885
- if str.size <= PROMPT_MAIN_TRUNCATE_LENGTH
886
- str
887
- else
888
- str[0, PROMPT_MAIN_TRUNCATE_LENGTH - PROMPT_MAIN_TRUNCATE_OMISSION.size] + PROMPT_MAIN_TRUNCATE_OMISSION
889
- end
890
- end
891
-
892
- private def format_prompt(format, ltype, indent, line_no) # :nodoc:
893
- format.gsub(/%([0-9]+)?([a-zA-Z])/) do
894
- case $2
895
- when "N"
896
- @context.irb_name
897
- when "m"
898
- truncate_prompt_main(@context.main.to_s)
899
- when "M"
900
- truncate_prompt_main(@context.main.inspect)
901
- when "l"
902
- ltype
903
- when "i"
904
- if indent < 0
905
- if $1
906
- "-".rjust($1.to_i)
907
- else
908
- "-"
909
- end
910
- else
911
- if $1
912
- format("%" + $1 + "d", indent)
913
- else
914
- indent.to_s
915
- end
916
- end
917
- when "n"
918
- if $1
919
- format("%" + $1 + "d", line_no)
920
- else
921
- line_no.to_s
922
- end
923
- when "%"
924
- "%"
925
- end
926
- end
927
- end
928
-
929
829
  def output_value(omit = false) # :nodoc:
930
830
  str = @context.inspect_last_value
931
831
  multiline_p = str.include?("\n")
@@ -978,28 +878,84 @@ module IRB
978
878
  end
979
879
  format("#<%s: %s>", self.class, ary.join(", "))
980
880
  end
981
- end
982
881
 
983
- def @CONF.inspect
984
- IRB.version unless self[:VERSION]
985
-
986
- array = []
987
- for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
988
- case k
989
- when :MAIN_CONTEXT, :__TMP__EHV__
990
- array.push format("CONF[:%s]=...myself...", k.id2name)
991
- when :PROMPT
992
- s = v.collect{
993
- |kk, vv|
994
- ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
995
- format(":%s=>{%s}", kk.id2name, ss.join(", "))
996
- }
997
- array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
882
+ private
883
+
884
+ def generate_prompt(opens, continue, line_offset)
885
+ ltype = @scanner.ltype_from_open_tokens(opens)
886
+ indent = @scanner.calc_indent_level(opens)
887
+ continue = opens.any? || continue
888
+ line_no = @line_no + line_offset
889
+
890
+ if ltype
891
+ f = @context.prompt_s
892
+ elsif continue
893
+ f = @context.prompt_c
894
+ else
895
+ f = @context.prompt_i
896
+ end
897
+ f = "" unless f
898
+ if @context.prompting?
899
+ p = format_prompt(f, ltype, indent, line_no)
900
+ else
901
+ p = ""
902
+ end
903
+ if @context.auto_indent_mode and !@context.io.respond_to?(:auto_indent)
904
+ unless ltype
905
+ prompt_i = @context.prompt_i.nil? ? "" : @context.prompt_i
906
+ ind = format_prompt(prompt_i, ltype, indent, line_no)[/.*\z/].size +
907
+ indent * 2 - p.size
908
+ p += " " * ind if ind > 0
909
+ end
910
+ end
911
+ p
912
+ end
913
+
914
+ def truncate_prompt_main(str) # :nodoc:
915
+ str = str.tr(CONTROL_CHARACTERS_PATTERN, ' ')
916
+ if str.size <= PROMPT_MAIN_TRUNCATE_LENGTH
917
+ str
998
918
  else
999
- array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
919
+ str[0, PROMPT_MAIN_TRUNCATE_LENGTH - PROMPT_MAIN_TRUNCATE_OMISSION.size] + PROMPT_MAIN_TRUNCATE_OMISSION
920
+ end
921
+ end
922
+
923
+ def format_prompt(format, ltype, indent, line_no) # :nodoc:
924
+ format.gsub(/%([0-9]+)?([a-zA-Z])/) do
925
+ case $2
926
+ when "N"
927
+ @context.irb_name
928
+ when "m"
929
+ truncate_prompt_main(@context.main.to_s)
930
+ when "M"
931
+ truncate_prompt_main(@context.main.inspect)
932
+ when "l"
933
+ ltype
934
+ when "i"
935
+ if indent < 0
936
+ if $1
937
+ "-".rjust($1.to_i)
938
+ else
939
+ "-"
940
+ end
941
+ else
942
+ if $1
943
+ format("%" + $1 + "d", indent)
944
+ else
945
+ indent.to_s
946
+ end
947
+ end
948
+ when "n"
949
+ if $1
950
+ format("%" + $1 + "d", line_no)
951
+ else
952
+ line_no.to_s
953
+ end
954
+ when "%"
955
+ "%"
956
+ end
1000
957
  end
1001
958
  end
1002
- array.join("\n")
1003
959
  end
1004
960
  end
1005
961
 
data/man/irb.1 CHANGED
@@ -140,6 +140,13 @@ Use autocompletion.
140
140
  Don't use autocompletion.
141
141
  .Pp
142
142
  .Pp
143
+ .It Fl -regexp-completor
144
+ Use regexp based completion.
145
+ .Pp
146
+ .It Fl -type-completor
147
+ Use type based completion.
148
+ .Pp
149
+ .Pp
143
150
  .It Fl -verbose
144
151
  Show details.
145
152
  .Pp