DebugClients/Ruby/Completer.rb

changeset 4553
a6b2acd1a355
parent 4552
b1ea4ea0190e
child 4554
f3428ddd577c
equal deleted inserted replaced
4552:b1ea4ea0190e 4553:a6b2acd1a355
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2005 - 2015 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 =begin edoc
7 File implementing a command line completer class.
8 =end
9
10 #
11 # This code is mostly based on the completer found in irb of the Ruby package
12 # Original copyright
13 # by Keiju ISHITSUKA(keiju@ishitsuka.com)
14 # From Original Idea of shugo@ruby-lang.org
15 #
16
17 class Completer
18 =begin edoc
19 Class implementing a command completer.
20 =end
21 ReservedWords = [
22 "BEGIN", "END",
23 "alias", "and",
24 "begin", "break",
25 "case", "class",
26 "def", "defined", "do",
27 "else", "elsif", "end", "ensure",
28 "false", "for",
29 "if", "in",
30 "module",
31 "next", "nil", "not",
32 "or",
33 "redo", "rescue", "retry", "return",
34 "self", "super",
35 "then", "true",
36 "undef", "unless", "until",
37 "when", "while",
38 "yield",
39 ]
40
41 def initialize(binding)
42 =begin edoc
43 constructor
44
45 @param binding binding object used to determine the possible completions
46 =end
47 @binding = binding
48 end
49
50 def complete(input)
51 =begin edoc
52 Public method to select the possible completions
53
54 @param input text to be completed (String)
55 @return list of possible completions (Array)
56 =end
57 case input
58 when /^((["'`]).*\2)\.([^.]*)$/
59 # String
60 receiver = $1
61 message = $3
62
63 candidates = String.instance_methods.collect{|m| m.to_s}
64 select_message(receiver, message, candidates)
65
66 when /^(\/[^\/]*\/)\.([^.]*)$/
67 # Regexp
68 receiver = $1
69 message = Regexp.quote($2)
70
71 candidates = Regexp.instance_methods.collect{|m| m.to_s}
72 select_message(receiver, message, candidates)
73
74 when /^([^\]]*\])\.([^.]*)$/
75 # Array
76 receiver = $1
77 message = Regexp.quote($2)
78
79 candidates = Array.instance_methods.collect{|m| m.to_s}
80 select_message(receiver, message, candidates)
81
82 when /^([^\}]*\})\.([^.]*)$/
83 # Proc or Hash
84 receiver = $1
85 message = Regexp.quote($2)
86
87 candidates = Proc.instance_methods.collect{|m| m.to_s}
88 candidates |= Hash.instance_methods.collect{|m| m.to_s}
89 select_message(receiver, message, candidates)
90
91 when /^(:[^:.]*)$/
92 # Symbol
93 if Symbol.respond_to?(:all_symbols)
94 sym = $1
95 candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name}
96 candidates.grep(/^#{sym}/)
97 else
98 []
99 end
100
101 when /^::([A-Z][^:\.\(]*)$/
102 # Absolute Constant or class methods
103 receiver = $1
104 candidates = Object.constants.collect{|m| m.to_s}
105 candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
106
107 when /^([A-Z].*)::([^:.]*)$/
108 # Constant or class methods
109 receiver = $1
110 message = Regexp.quote($4)
111 begin
112 candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
113 candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
114 rescue Exception
115 candidates = []
116 end
117 select_message(receiver, message, candidates, "::")
118
119 when /^(:[^:.]+)(\.|::)([^.]*)$/
120 # Symbol
121 receiver = $1
122 sep = $2
123 message = Regexp.quote($3)
124
125 candidates = Symbol.instance_methods.collect{|m| m.to_s}
126 select_message(receiver, message, candidates, sep)
127
128 when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)(\.|::)([^.]*)$/
129 # Numeric
130 receiver = $1
131 sep = $5
132 message = Regexp.quote($6)
133
134 begin
135 candidates = eval(receiver, @binding).methods.collect{|m| m.to_s}
136 rescue Exception
137 candidates
138 end
139 select_message(receiver, message, candidates, sep)
140
141 when /^(-?0x[0-9a-fA-F_]+)(\.|::)([^.]*)$/
142 # Numeric(0xFFFF)
143 receiver = $1
144 sep = $2
145 message = Regexp.quote($3)
146
147 begin
148 candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
149 rescue Exception
150 candidates = []
151 end
152 select_message(receiver, message, candidates, sep)
153
154 when /^(\$[^.]*)$/
155 # Global variable
156 candidates = global_variables.grep(Regexp.new(Regexp.quote($1)))
157
158 when /^([^."].*)(\.|::)([^.]*)$/
159 # variable.func or func.func
160 receiver = $1
161 sep = $2
162 message = Regexp.quote($3)
163
164 gv = eval("global_variables", @binding).collect{|m| m.to_s}
165 lv = eval("local_variables", @binding).collect{|m| m.to_s}
166 cv = eval("self.class.constants", @binding).collect{|m| m.to_s}
167
168 if (gv | lv | cv).include?(receiver) or \
169 /^[A-Z]/ =~ receiver && /\./ !~ receiver
170 # foo.func and foo is var. OR
171 # foo::func and foo is var. OR
172 # foo::Const and foo is var. OR
173 # Foo::Bar.func
174 begin
175 candidates = []
176 rec = eval(receiver, bind)
177 if sep == "::" and rec.kind_of?(Module)
178 candidates = rec.constants.collect{|m| m.to_s}
179 end
180 candidates |= rec.methods.collect{|m| m.to_s}
181 rescue Exception
182 candidates = []
183 end
184 else
185 # func1.func2
186 candidates = []
187 ObjectSpace.each_object(Module){|m|
188 begin
189 name = m.name
190 rescue Exception
191 name = ""
192 end
193 begin
194 next if m.name != "IRB::Context" and
195 /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name
196 rescue Exception
197 next
198 end
199 candidates.concat m.instance_methods(false).collect{|x| x.to_s}
200 }
201 candidates.sort!
202 candidates.uniq!
203 end
204 select_message(receiver, message, candidates, sep)
205
206 when /^\.([^.]*)$/
207 # unknown(maybe String)
208
209 receiver = ""
210 message = Regexp.quote($1)
211
212 candidates = String.instance_methods(true).collect{|m| m.to_s}
213 select_message(receiver, message, candidates)
214
215 else
216 candidates = eval(
217 "methods | private_methods | local_variables | self.class.constants",
218 @binding).collect{|m| m.to_s}
219
220 (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/)
221 end
222 end
223
224 Operators = ["%", "&", "*", "**", "+", "-", "/",
225 "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
226 "[]", "[]=", "^", "!", "!=", "!~"]
227
228 def select_message(receiver, message, candidates, sep = ".")
229 =begin edoc
230 Method used to pick completion candidates.
231
232 @param receiver object receiving the message
233 @param message message to be sent to object
234 @param candidates possible completion candidates
235 @param sep separater string
236 @return filtered list of candidates
237 =end
238 candidates.grep(/^#{message}/).collect do |e|
239 case e
240 when /^[a-zA-Z_]/
241 receiver + sep + e
242 when /^[0-9]/
243 when *Operators
244 #receiver + " " + e
245 end
246 end
247 end
248 end

eric ide

mercurial