1 | #
|
---|
2 | # irb/completor.rb -
|
---|
3 | # $Release Version: 0.9$
|
---|
4 | # $Revision: 11708 $
|
---|
5 | # $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
|
---|
6 | # by Keiju ISHITSUKA([email protected])
|
---|
7 | # From Original Idea of [email protected]
|
---|
8 | #
|
---|
9 |
|
---|
10 | require "readline"
|
---|
11 |
|
---|
12 | module IRB
|
---|
13 | module InputCompletor
|
---|
14 |
|
---|
15 | @RCS_ID='-$Id: completion.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
|
---|
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[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
|
---|
103 | # Numeric
|
---|
104 | receiver = $1
|
---|
105 | message = Regexp.quote($5)
|
---|
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 /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
|
---|
115 | # Numeric(0xFFFF)
|
---|
116 | receiver = $1
|
---|
117 | message = Regexp.quote($2)
|
---|
118 |
|
---|
119 | begin
|
---|
120 | candidates = eval(receiver, bind).methods
|
---|
121 | rescue Exception
|
---|
122 | candidates = []
|
---|
123 | end
|
---|
124 | select_message(receiver, message, candidates)
|
---|
125 |
|
---|
126 | when /^(\$[^.]*)$/
|
---|
127 | candidates = global_variables.grep(Regexp.new(Regexp.quote($1)))
|
---|
128 |
|
---|
129 | # when /^(\$?(\.?[^.]+)+)\.([^.]*)$/
|
---|
130 | when /^((\.?[^.]+)+)\.([^.]*)$/
|
---|
131 | # variable
|
---|
132 | receiver = $1
|
---|
133 | message = Regexp.quote($3)
|
---|
134 |
|
---|
135 | gv = eval("global_variables", bind)
|
---|
136 | lv = eval("local_variables", bind)
|
---|
137 | cv = eval("self.class.constants", bind)
|
---|
138 |
|
---|
139 | if (gv | lv | cv).include?(receiver)
|
---|
140 | # foo.func and foo is local var.
|
---|
141 | candidates = eval("#{receiver}.methods", bind)
|
---|
142 | elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
|
---|
143 | # Foo::Bar.func
|
---|
144 | begin
|
---|
145 | candidates = eval("#{receiver}.methods", bind)
|
---|
146 | rescue Exception
|
---|
147 | candidates = []
|
---|
148 | end
|
---|
149 | else
|
---|
150 | # func1.func2
|
---|
151 | candidates = []
|
---|
152 | ObjectSpace.each_object(Module){|m|
|
---|
153 | begin
|
---|
154 | name = m.name
|
---|
155 | rescue Exception
|
---|
156 | name = ""
|
---|
157 | end
|
---|
158 | next if name != "IRB::Context" and
|
---|
159 | /^(IRB|SLex|RubyLex|RubyToken)/ =~ name
|
---|
160 | candidates.concat m.instance_methods(false)
|
---|
161 | }
|
---|
162 | candidates.sort!
|
---|
163 | candidates.uniq!
|
---|
164 | end
|
---|
165 | select_message(receiver, message, candidates)
|
---|
166 |
|
---|
167 | when /^\.([^.]*)$/
|
---|
168 | # unknown(maybe String)
|
---|
169 |
|
---|
170 | receiver = ""
|
---|
171 | message = Regexp.quote($1)
|
---|
172 |
|
---|
173 | candidates = String.instance_methods(true)
|
---|
174 | select_message(receiver, message, candidates)
|
---|
175 |
|
---|
176 | else
|
---|
177 | candidates = eval("methods | private_methods | local_variables | self.class.constants", bind)
|
---|
178 |
|
---|
179 | (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/)
|
---|
180 | end
|
---|
181 | }
|
---|
182 |
|
---|
183 | Operators = ["%", "&", "*", "**", "+", "-", "/",
|
---|
184 | "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
|
---|
185 | "[]", "[]=", "^",]
|
---|
186 |
|
---|
187 | def self.select_message(receiver, message, candidates)
|
---|
188 | candidates.grep(/^#{message}/).collect do |e|
|
---|
189 | case e
|
---|
190 | when /^[a-zA-Z_]/
|
---|
191 | receiver + "." + e
|
---|
192 | when /^[0-9]/
|
---|
193 | when *Operators
|
---|
194 | #receiver + " " + e
|
---|
195 | end
|
---|
196 | end
|
---|
197 | end
|
---|
198 | end
|
---|
199 | end
|
---|
200 |
|
---|
201 | if Readline.respond_to?("basic_word_break_characters=")
|
---|
202 | Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{("
|
---|
203 | end
|
---|
204 | Readline.completion_append_character = nil
|
---|
205 | Readline.completion_proc = IRB::InputCompletor::CompletionProc
|
---|