blob: 8def228edc082024dd0375781d213b90840bbe0f [file] [log] [blame]
Bram Moolenaarc6249bb2006-04-15 20:25:09 +00001" 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
13if !has('ruby')
14 echo "Error: Required vim compiled with +ruby"
15 finish
16endif
17
18if version < 700
19 echo "Error: Required vim >= 7.0"
20 finish
21endif
22
23func! 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 ''
54endf
55
56function! 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
80endfunction
81
82
83function! s:DefRuby()
84ruby << RUBYEOF
85ReservedWords = [
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
105Operators = [ "%", "&", "*", "**", "+", "-", "/",
106 "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
107 "[]", "[]=", "^", ]
108
109def 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
120end
121
122def 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
134end
135
136def 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)
287end
288
289
290def 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!
303end
304RUBYEOF
305endfunction
306
307call s:DefRuby()
308" vim: set et ts=4: