831
|
1 " Vim completion script
|
|
2 " Language: Ruby
|
|
3 " Maintainer: Mark Guzman ( segfault AT hasno DOT info )
|
|
4 " Info: $Id$
|
|
5 " URL: http://vim-ruby.rubyforge.org
|
|
6 " Anon CVS: See above site
|
|
7 " Release Coordinator: Doug Kearns <dougkearns@gmail.com>
|
|
8 " ----------------------------------------------------------------------------
|
|
9 "
|
|
10 " Ruby IRB/Complete author: Keiju ISHITSUKA(keiju@ishitsuka.com)
|
|
11 " ----------------------------------------------------------------------------
|
|
12
|
|
13 if !has('ruby')
|
|
14 echo "Error: Required vim compiled with +ruby"
|
|
15 finish
|
|
16 endif
|
|
17
|
|
18 if version < 700
|
|
19 echo "Error: Required vim >= 7.0"
|
|
20 finish
|
|
21 endif
|
|
22
|
|
23 func! GetRubyVarType(v)
|
|
24 let stopline = 1
|
|
25 let vtp = ''
|
|
26 let pos = getpos('.')
|
|
27 let [lnum,lcol] = searchpos('^\s*#\s*@var\s*'.a:v.'\>\s\+[^ \t]\+\s*$','nb',stopline)
|
|
28 if lnum != 0 && lcol != 0
|
|
29 call setpos('.',pos)
|
|
30 let str = getline(lnum)
|
|
31 let vtp = substitute(str,'^\s*#\s*@var\s*'.a:v.'\>\s\+\([^ \t]\+\)\s*$','\1','')
|
|
32 return vtp
|
|
33 endif
|
|
34 call setpos('.',pos)
|
|
35 let [lnum,lcol] = searchpos(''.a:v.'\>\s*[+\-*/]*=\s*\([^ \t]\+.\(now\|new\|open\|get_instance\)\>\|[\[{"'']\)','nb',stopline)
|
|
36 if lnum != 0 && lcol != 0
|
|
37 let str = matchstr(getline(lnum),'=\s*\([^ \t]\+.\(now\|new\|open\|get_instance\)\>\|[\[{"'']\)',lcol)
|
|
38 let str = substitute(str,'^=\s*','','')
|
|
39 call setpos('.',pos)
|
|
40 if str == '"' || str == ''''
|
|
41 return 'String'
|
|
42 elseif str == '['
|
|
43 return 'Array'
|
|
44 elseif str == '{'
|
|
45 return 'Hash'
|
|
46 elseif strlen(str) > 4
|
|
47 let l = stridx(str,'.')
|
|
48 return str[0:l-1]
|
|
49 end
|
|
50 return ''
|
|
51 endif
|
|
52 call setpos('.',pos)
|
|
53 return ''
|
|
54 endf
|
|
55
|
|
56 function! rubycomplete#Complete(findstart, base)
|
|
57 "findstart = 1 when we need to get the text length
|
|
58 if a:findstart
|
|
59 let line = getline('.')
|
|
60 let idx = col('.')
|
|
61 while idx > 0
|
|
62 let idx -= 1
|
|
63 let c = line[idx-1]
|
|
64 if c =~ '\w'
|
|
65 continue
|
|
66 elseif ! c =~ '\.'
|
|
67 idx = -1
|
|
68 break
|
|
69 else
|
|
70 break
|
|
71 endif
|
|
72 endwhile
|
|
73
|
|
74 return idx
|
|
75 "findstart = 0 when we need to return the list of completions
|
|
76 else
|
|
77 execute "ruby get_completions('" . a:base . "')"
|
|
78 return g:rbcomplete_completions
|
|
79 endif
|
|
80 endfunction
|
|
81
|
|
82
|
|
83 function! s:DefRuby()
|
|
84 ruby << RUBYEOF
|
|
85 ReservedWords = [
|
|
86 "BEGIN", "END",
|
|
87 "alias", "and",
|
|
88 "begin", "break",
|
|
89 "case", "class",
|
|
90 "def", "defined", "do",
|
|
91 "else", "elsif", "end", "ensure",
|
|
92 "false", "for",
|
|
93 "if", "in",
|
|
94 "module",
|
|
95 "next", "nil", "not",
|
|
96 "or",
|
|
97 "redo", "rescue", "retry", "return",
|
|
98 "self", "super",
|
|
99 "then", "true",
|
|
100 "undef", "unless", "until",
|
|
101 "when", "while",
|
|
102 "yield",
|
|
103 ]
|
|
104
|
|
105 Operators = [ "%", "&", "*", "**", "+", "-", "/",
|
|
106 "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
|
|
107 "[]", "[]=", "^", ]
|
|
108
|
|
109 def identify_type(var)
|
|
110 @buf = VIM::Buffer.current
|
|
111 enum = @buf.line_number
|
|
112 snum = (enum-10).abs
|
|
113 nums = Range.new( snum, enum )
|
|
114 regxs = '/.*(%s)\s*=(.*)/' % var
|
|
115 regx = Regexp.new( regxs )
|
|
116 nums.each do |x|
|
|
117 ln = @buf[x]
|
|
118 #print $~ if regx.match( ln )
|
|
119 end
|
|
120 end
|
|
121
|
|
122 def load_requires
|
|
123 @buf = VIM::Buffer.current
|
|
124 enum = @buf.line_number
|
|
125 nums = Range.new( 1, enum )
|
|
126 nums.each do |x|
|
|
127 ln = @buf[x]
|
|
128 begin
|
|
129 eval( "require %s" % $1 ) if /.*require\s*(.*)$/.match( ln )
|
|
130 rescue Exception
|
|
131 #ignore?
|
|
132 end
|
|
133 end
|
|
134 end
|
|
135
|
|
136 def get_completions(base)
|
|
137 load_requires
|
|
138 input = VIM::evaluate('expand("<cWORD>")')
|
|
139 input += base
|
|
140 message = nil
|
|
141
|
|
142
|
|
143 case input
|
|
144 when /^(\/[^\/]*\/)\.([^.]*)$/
|
|
145 # Regexp
|
|
146 receiver = $1
|
|
147 message = Regexp.quote($2)
|
|
148
|
|
149 candidates = Regexp.instance_methods(true)
|
|
150 select_message(receiver, message, candidates)
|
|
151
|
|
152 when /^([^\]]*\])\.([^.]*)$/
|
|
153 # Array
|
|
154 receiver = $1
|
|
155 message = Regexp.quote($2)
|
|
156
|
|
157 candidates = Array.instance_methods(true)
|
|
158 select_message(receiver, message, candidates)
|
|
159
|
|
160 when /^([^\}]*\})\.([^.]*)$/
|
|
161 # Proc or Hash
|
|
162 receiver = $1
|
|
163 message = Regexp.quote($2)
|
|
164
|
|
165 candidates = Proc.instance_methods(true) | Hash.instance_methods(true)
|
|
166 select_message(receiver, message, candidates)
|
|
167
|
|
168 when /^(:[^:.]*)$/
|
|
169 # Symbol
|
|
170 if Symbol.respond_to?(:all_symbols)
|
|
171 sym = $1
|
|
172 candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name}
|
|
173 candidates.grep(/^#{sym}/)
|
|
174 else
|
|
175 []
|
|
176 end
|
|
177
|
|
178 when /^::([A-Z][^:\.\(]*)$/
|
|
179 # Absolute Constant or class methods
|
|
180 receiver = $1
|
|
181 candidates = Object.constants
|
|
182 candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
|
|
183
|
|
184 when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/
|
|
185 # Constant or class methods
|
|
186 receiver = $1
|
|
187 message = Regexp.quote($4)
|
|
188 begin
|
|
189 candidates = eval("#{receiver}.constants | #{receiver}.methods")
|
|
190 rescue Exception
|
|
191 candidates = []
|
|
192 end
|
|
193 candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
|
|
194
|
|
195 when /^(:[^:.]+)\.([^.]*)$/
|
|
196 # Symbol
|
|
197 receiver = $1
|
|
198 message = Regexp.quote($2)
|
|
199
|
|
200 candidates = Symbol.instance_methods(true)
|
|
201 select_message(receiver, message, candidates)
|
|
202
|
|
203 when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/
|
|
204 # Numeric
|
|
205 receiver = $1
|
|
206 message = Regexp.quote($4)
|
|
207
|
|
208 begin
|
|
209 candidates = eval(receiver).methods
|
|
210 rescue Exception
|
|
211 candidates
|
|
212 end
|
|
213 select_message(receiver, message, candidates)
|
|
214
|
|
215 when /^(\$[^.]*)$/
|
|
216 candidates = global_variables.grep(Regexp.new(Regexp.quote($1)))
|
|
217
|
|
218 # when /^(\$?(\.?[^.]+)+)\.([^.]*)$/
|
|
219 when /^((\.?[^.]+)+)\.([^.]*)$/
|
|
220 # variable
|
|
221 receiver = $1
|
|
222 message = Regexp.quote($3)
|
|
223
|
|
224 cv = eval("self.class.constants")
|
|
225
|
|
226 vartype = VIM::evaluate("GetRubyVarType('%s')" % receiver)
|
|
227 if vartype != ''
|
|
228 candidates = eval("#{vartype}.instance_methods")
|
|
229 elsif (cv).include?(receiver)
|
|
230 # foo.func and foo is local var.
|
|
231 candidates = eval("#{receiver}.methods")
|
|
232 elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
|
|
233 # Foo::Bar.func
|
|
234 begin
|
|
235 candidates = eval("#{receiver}.methods")
|
|
236 rescue Exception
|
|
237 candidates = []
|
|
238 end
|
|
239 else
|
|
240 # func1.func2
|
|
241 candidates = []
|
|
242 ObjectSpace.each_object(Module){|m|
|
|
243 next if m.name != "IRB::Context" and
|
|
244 /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name
|
|
245 candidates.concat m.instance_methods(false)
|
|
246 }
|
|
247 candidates.sort!
|
|
248 candidates.uniq!
|
|
249 end
|
|
250 #identify_type( receiver )
|
|
251 select_message(receiver, message, candidates)
|
|
252
|
|
253 #when /^((\.?[^.]+)+)\.([^.]*)\(\s*\)*$/
|
|
254 #function call
|
|
255 #obj = $1
|
|
256 #func = $3
|
|
257
|
|
258 when /^\.([^.]*)$/
|
|
259 # unknown(maybe String)
|
|
260
|
|
261 receiver = ""
|
|
262 message = Regexp.quote($1)
|
|
263
|
|
264 candidates = String.instance_methods(true)
|
|
265 select_message(receiver, message, candidates)
|
|
266
|
|
267 else
|
|
268 candidates = eval("self.class.constants")
|
|
269
|
|
270 (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/)
|
|
271 end
|
|
272
|
|
273 #print candidates
|
|
274 if message != nil && message.length > 0
|
|
275 rexp = '^%s' % message.downcase
|
|
276 candidates.delete_if do |c|
|
|
277 c.downcase.match( rexp )
|
|
278 $~ == nil
|
|
279 end
|
|
280 end
|
|
281
|
|
282 outp = ""
|
|
283 # tags = VIM::evaluate("taglist('^%s$')" %
|
|
284 (candidates-Object.instance_methods).each { |c| outp += "{'word':'%s','item':'%s'}," % [ c, c ] }
|
|
285 outp.sub!(/,$/, '')
|
|
286 VIM::command("let g:rbcomplete_completions = [%s]" % outp)
|
|
287 end
|
|
288
|
|
289
|
|
290 def select_message(receiver, message, candidates)
|
|
291 candidates.grep(/^#{message}/).collect do |e|
|
|
292 case e
|
|
293 when /^[a-zA-Z_]/
|
|
294 receiver + "." + e
|
|
295 when /^[0-9]/
|
|
296 when *Operators
|
|
297 #receiver + " " + e
|
|
298 end
|
|
299 end
|
|
300 candidates.delete_if { |x| x == nil }
|
|
301 candidates.uniq!
|
|
302 candidates.sort!
|
|
303 end
|
|
304 RUBYEOF
|
|
305 endfunction
|
|
306
|
|
307 call s:DefRuby()
|
|
308 " vim: set et ts=4:
|