lib/irb/completion.rb


DEFINITIONS

This source file includes following functions.


   1  #
   2  #   irb/completor.rb - 
   3  #       $Release Version: 0.9$
   4  #       $Revision: 1.3 $
   5  #       $Date: 2002/07/09 11:17:16 $
   6  #       by Keiju ISHITSUKA(keiju@ishitsuka.com)
   7  #       From Original Idea of shugo@ruby-lang.org
   8  #
   9  
  10  require "readline"
  11  
  12  module IRB
  13    module InputCompletor
  14  
  15      @RCS_ID='-$Id: completion.rb,v 1.3 2002/07/09 11:17:16 keiju Exp $-'
  16  
  17      ReservedWords = [
  18        "BEGIN", "END",
  19        "alias", "and", 
  20        "begin", "break", 
  21        "case", "class",
  22        "def", "defined", "do",
  23        "else", "elsif", "end", "ensure",
  24        "false", "for", 
  25        "if", "in", 
  26        "module", 
  27        "next", "nil", "not",
  28        "or", 
  29        "redo", "rescue", "retry", "return",
  30        "self", "super",
  31        "then", "true",
  32        "undef", "unless", "until",
  33        "when", "while",
  34        "yield",
  35      ]
  36        
  37      CompletionProc = proc { |input|
  38        bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
  39        
  40  #      puts "input: #{input}"
  41  
  42        case input
  43        when /^(\/[^\/]*\/)\.([^.]*)$/
  44          # Regexp
  45          receiver = $1
  46          message = Regexp.quote($2)
  47  
  48          candidates = Regexp.instance_methods(true)
  49          select_message(receiver, message, candidates)
  50  
  51        when /^([^\]]*\])\.([^.]*)$/
  52          # Array
  53          receiver = $1
  54          message = Regexp.quote($2)
  55  
  56          candidates = Array.instance_methods(true)
  57          select_message(receiver, message, candidates)
  58  
  59        when /^([^\}]*\})\.([^.]*)$/
  60          # Proc or Hash
  61          receiver = $1
  62          message = Regexp.quote($2)
  63  
  64          candidates = Proc.instance_methods(true) | Hash.instance_methods(true)
  65          select_message(receiver, message, candidates)
  66          
  67        when /^(:[^:.]*)$/
  68          # Symbol
  69          if Symbol.respond_to?(:all_symbols)
  70            sym = $1
  71            candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name}
  72            candidates.grep(/^#{sym}/)
  73          else
  74            []
  75          end
  76  
  77        when /^::([A-Z][^:\.\(]*)$/
  78          # Absolute Constant or class methods
  79          receiver = $1
  80          candidates = Object.constants
  81          candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
  82  
  83        when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/
  84          # Constant or class methods
  85          receiver = $1
  86          message = Regexp.quote($4)
  87          begin
  88            candidates = eval("#{receiver}.constants | #{receiver}.methods", bind)
  89          rescue Exception
  90            candidates = []
  91          end
  92          candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
  93  
  94        when /^(:[^:.]+)\.([^.]*)$/
  95          # Symbol
  96          receiver = $1
  97          message = Regexp.quote($2)
  98  
  99          candidates = Symbol.instance_methods(true)
 100          select_message(receiver, message, candidates)
 101  
 102        when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/
 103          # Numeric
 104          receiver = $1
 105          message = Regexp.quote($4)
 106  
 107          begin
 108            candidates = eval(receiver, bind).methods
 109          rescue Exception
 110            candidates
 111          end
 112          select_message(receiver, message, candidates)
 113  
 114        when /^(\$[^.]*)$/
 115          candidates = global_variables.grep Regexp.new(Regexp.quote($1))
 116  
 117  #      when /^(\$?(\.?[^.]+)+)\.([^.]*)$/
 118        when /^((\.?[^.]+)+)\.([^.]*)$/
 119          # variable
 120          receiver = $1
 121          message = Regexp.quote($3)
 122  
 123          gv = eval "global_variables", bind
 124          lv = eval "local_variables", bind
 125          cv = eval "type.constants", bind
 126          
 127          if (gv | lv | cv).include?(receiver)
 128            # foo.func and foo is local var.
 129            candidates = eval("#{receiver}.methods", bind)
 130          elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
 131            # Foo::Bar.func
 132            begin
 133              candidates = eval("#{receiver}.methods", bind)
 134            rescue Exception
 135              candidates = []
 136            end
 137          else
 138            # func1.func2
 139            candidates = []
 140            ObjectSpace.each_object(Module){|m|
 141              next if m.name != "IRB::Context" and 
 142                /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name
 143              candidates.concat m.instance_methods
 144            }
 145            candidates.sort!
 146            candidates.uniq!
 147          end
 148          select_message(receiver, message, candidates)
 149  
 150        when /^\.([^.]*)$/
 151          # unknown(maybe String)
 152  
 153          receiver = ""
 154          message = Regexp.quote($1)
 155  
 156          candidates = String.instance_methods(true)
 157          select_message(receiver, message, candidates)
 158  
 159        else
 160          candidates = eval("methods | private_methods | local_variables | type.constants", bind)
 161                            
 162          (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/)
 163        end
 164      }
 165  
 166      Operators = ["%", "&", "*", "**", "+",  "-",  "/",
 167        "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
 168        "[]", "[]=", "^",]
 169  
 170      def self.select_message(receiver, message, candidates)
 171        candidates.grep(/^#{message}/).collect do |e|
 172          case e
 173          when /^[a-zA-Z_]/
 174            receiver + "." + e
 175          when /^[0-9]/
 176          when *Operators
 177            #receiver + " " + e
 178          end
 179        end
 180      end
 181    end
 182  end
 183  
 184  if Readline.respond_to?("basic_word_break_characters=")
 185    Readline.basic_word_break_characters= "\t\n\"\\'`><=;|&{("
 186  end
 187  Readline.completion_append_character = nil
 188  Readline.completion_proc = IRB::InputCompletor::CompletionProc