Module: IRB::InputCompletor

Defined in:
lib/irb/completion.rb

Overview

:nodoc:

Constant Summary collapse

ReservedWords =

Set of reserved words used by Ruby, you should not use these for constants or variables

%w[
  BEGIN END
  alias and
  begin break
  case class
  def defined do
  else elsif end ensure
  false for
  if in
  module
  next nil not
  or
  redo rescue retry return
  self super
  then true
  undef unless until
  when while
  yield
]
CompletionProc =
proc { |input|
  bind = IRB.conf[:MAIN_CONTEXT].workspace.binding

  case input
  when /^((["'`]).*\2)\.([^.]*)$/
    # String
    receiver = $1
    message = Regexp.quote($3)

    candidates = String.instance_methods.collect{|m| m.to_s}
    select_message(receiver, message, candidates)

  when /^(\/[^\/]*\/)\.([^.]*)$/
    # Regexp
    receiver = $1
    message = Regexp.quote($2)

    candidates = Regexp.instance_methods.collect{|m| m.to_s}
    select_message(receiver, message, candidates)

  when /^([^\]]*\])\.([^.]*)$/
    # Array
    receiver = $1
    message = Regexp.quote($2)

    candidates = Array.instance_methods.collect{|m| m.to_s}
    select_message(receiver, message, candidates)

  when /^([^\}]*\})\.([^.]*)$/
    # Proc or Hash
    receiver = $1
    message = Regexp.quote($2)

    candidates = Proc.instance_methods.collect{|m| m.to_s}
    candidates |= Hash.instance_methods.collect{|m| m.to_s}
    select_message(receiver, message, candidates)

  when /^(:[^:.]*)$/
    # Symbol
    if Symbol.respond_to?(:all_symbols)
      sym = $1
      candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name}
      candidates.grep(/^#{Regexp.quote(sym)}/)
    else
      []
    end

  when /^::([A-Z][^:\.\(]*)$/
    # Absolute Constant or class methods
    receiver = $1
    candidates = Object.constants.collect{|m| m.to_s}
    candidates.grep(/^#{receiver}/).collect{|e| "::" + e}

  when /^([A-Z].*)::([^:.]*)$/
    # Constant or class methods
    receiver = $1
    message = Regexp.quote($2)
    begin
      candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
      candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
    rescue Exception
      candidates = []
    end
    select_message(receiver, message, candidates, "::")

  when /^(:[^:.]+)(\.|::)([^.]*)$/
    # Symbol
    receiver = $1
    sep = $2
    message = Regexp.quote($3)

    candidates = Symbol.instance_methods.collect{|m| m.to_s}
    select_message(receiver, message, candidates, sep)

  when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)(\.|::)([^.]*)$/
    # Numeric
    receiver = $1
    sep = $5
    message = Regexp.quote($6)

    begin
      candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
    rescue Exception
      candidates = []
    end
    select_message(receiver, message, candidates, sep)

  when /^(-?0x[0-9a-fA-F_]+)(\.|::)([^.]*)$/
    # Numeric(0xFFFF)
    receiver = $1
    sep = $2
    message = Regexp.quote($3)

    begin
      candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
    rescue Exception
      candidates = []
    end
    select_message(receiver, message, candidates, sep)

  when /^(\$[^.]*)$/
    # global var
    regmessage = Regexp.new(Regexp.quote($1))
    candidates = global_variables.collect{|m| m.to_s}.grep(regmessage)

  when /^([^."].*)(\.|::)([^.]*)$/
    # variable.func or func.func
    receiver = $1
    sep = $2
    message = Regexp.quote($3)

    gv = eval("global_variables", bind).collect{|m| m.to_s}
    lv = eval("local_variables", bind).collect{|m| m.to_s}
    iv = eval("instance_variables", bind).collect{|m| m.to_s}
    cv = eval("self.class.constants", bind).collect{|m| m.to_s}

    if (gv | lv | iv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
      # foo.func and foo is var. OR
      # foo::func and foo is var. OR
      # foo::Const and foo is var. OR
      # Foo::Bar.func
      begin
        candidates = []
        rec = eval(receiver, bind)
        if sep == "::" and rec.kind_of?(Module)
          candidates = rec.constants.collect{|m| m.to_s}
        end
        candidates |= rec.methods.collect{|m| m.to_s}
      rescue Exception
        candidates = []
      end
    else
      # func1.func2
      candidates = []
      to_ignore = ignored_modules
      ObjectSpace.each_object(Module){|m|
        next if (to_ignore.include?(m) rescue true)
        candidates.concat m.instance_methods(false).collect{|x| x.to_s}
      }
      candidates.sort!
      candidates.uniq!
    end
    select_message(receiver, message, candidates, sep)

  when /^\.([^.]*)$/
    # unknown(maybe String)

    receiver = ""
    message = Regexp.quote($1)

    candidates = String.instance_methods(true).collect{|m| m.to_s}
    select_message(receiver, message, candidates)

  else
    candidates = eval("methods | private_methods | local_variables | instance_variables | self.class.constants", bind).collect{|m| m.to_s}

    (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/)
  end
}
Operators =

Set of available operators in Ruby

%w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]

Class Method Summary collapse

Class Method Details

.ignored_modulesObject



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/irb/completion.rb', line 213

def self.ignored_modules
  # We could cache the result, but this is very fast already.
  # By using this approach, we avoid Module#name calls, which are
  # relatively slow when there are a lot of anonymous modules defined.
  s = {}

  scanner = lambda do |m|
    next if s.include?(m) # IRB::ExtendCommandBundle::EXCB recurses.
    s[m] = true
    m.constants(false).each do |c|
      value = m.const_get(c)
      scanner.call(value) if value.is_a?(Module)
    end
  end

  %i(IRB SLex RubyLex RubyToken).each do |sym|
    next unless Object.const_defined?(sym)
    scanner.call(Object.const_get(sym))
  end

  s.delete(IRB::Context) if defined?(IRB::Context)

  s
end

.select_message(receiver, message, candidates, sep = ".") ⇒ Object



201
202
203
204
205
206
207
208
209
210
211
# File 'lib/irb/completion.rb', line 201

def self.select_message(receiver, message, candidates, sep = ".")
  candidates.grep(/^#{message}/).collect do |e|
    case e
    when /^[a-zA-Z_]/
      receiver + sep + e
    when /^[0-9]/
    when *Operators
      #receiver + " " + e
    end
  end
end