irb 1.8.2 → 1.9.0

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