Mercurial > vim
annotate runtime/autoload/rubycomplete.vim @ 12770:89889fea43e0
Added tag v8.0.1262 for changeset 083ae2cfcc5b13d3438d6d0489865aa3612d8c75
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 04 Nov 2017 21:00:06 +0100 |
parents | 57b2b8268d3a |
children | f0f06837a699 |
rev | line source |
---|---|
831 | 1 " Vim completion script |
852 | 2 " Language: Ruby |
3 " Maintainer: Mark Guzman <segfault@hasno.info> | |
4869 | 4 " URL: https://github.com/vim-ruby/vim-ruby |
852 | 5 " Release Coordinator: Doug Kearns <dougkearns@gmail.com> |
2225 | 6 " Maintainer Version: 0.8.1 |
831 | 7 " ---------------------------------------------------------------------------- |
8 " | |
9 " Ruby IRB/Complete author: Keiju ISHITSUKA(keiju@ishitsuka.com) | |
10 " ---------------------------------------------------------------------------- | |
11 | |
840 | 12 " {{{ requirement checks |
4869 | 13 |
14 function! s:ErrMsg(msg) | |
15 echohl ErrorMsg | |
16 echo a:msg | |
17 echohl None | |
18 endfunction | |
19 | |
831 | 20 if !has('ruby') |
4869 | 21 call s:ErrMsg( "Error: Rubycomplete requires vim compiled with +ruby" ) |
22 call s:ErrMsg( "Error: falling back to syntax completion" ) | |
1121 | 23 " lets fall back to syntax completion |
24 setlocal omnifunc=syntaxcomplete#Complete | |
831 | 25 finish |
26 endif | |
27 | |
28 if version < 700 | |
4869 | 29 call s:ErrMsg( "Error: Required vim >= 7.0" ) |
831 | 30 finish |
31 endif | |
840 | 32 " }}} requirement checks |
831 | 33 |
1121 | 34 " {{{ configuration failsafe initialization |
840 | 35 if !exists("g:rubycomplete_rails") |
36 let g:rubycomplete_rails = 0 | |
37 endif | |
838 | 38 |
840 | 39 if !exists("g:rubycomplete_classes_in_global") |
40 let g:rubycomplete_classes_in_global = 0 | |
41 endif | |
42 | |
1121 | 43 if !exists("g:rubycomplete_buffer_loading") |
1619 | 44 let g:rubycomplete_buffer_loading = 0 |
1121 | 45 endif |
46 | |
47 if !exists("g:rubycomplete_include_object") | |
48 let g:rubycomplete_include_object = 0 | |
49 endif | |
50 | |
51 if !exists("g:rubycomplete_include_objectspace") | |
52 let g:rubycomplete_include_objectspace = 0 | |
53 endif | |
54 " }}} configuration failsafe initialization | |
55 | |
840 | 56 " {{{ vim-side support functions |
1121 | 57 let s:rubycomplete_debug = 0 |
58 | |
59 function! s:dprint(msg) | |
60 if s:rubycomplete_debug == 1 | |
61 echom a:msg | |
62 endif | |
63 endfunction | |
64 | |
65 function! s:GetBufferRubyModule(name, ...) | |
66 if a:0 == 1 | |
67 let [snum,enum] = s:GetBufferRubyEntity(a:name, "module", a:1) | |
68 else | |
69 let [snum,enum] = s:GetBufferRubyEntity(a:name, "module") | |
70 endif | |
838 | 71 return snum . '..' . enum |
72 endfunction | |
73 | |
1121 | 74 function! s:GetBufferRubyClass(name, ...) |
75 if a:0 >= 1 | |
76 let [snum,enum] = s:GetBufferRubyEntity(a:name, "class", a:1) | |
77 else | |
78 let [snum,enum] = s:GetBufferRubyEntity(a:name, "class") | |
79 endif | |
80 return snum . '..' . enum | |
81 endfunction | |
82 | |
83 function! s:GetBufferRubySingletonMethods(name) | |
838 | 84 endfunction |
85 | |
1121 | 86 function! s:GetBufferRubyEntity( name, type, ... ) |
87 let lastpos = getpos(".") | |
88 let lastline = lastpos | |
89 if (a:0 >= 1) | |
90 let lastline = [ 0, a:1, 0, 0 ] | |
91 call cursor( a:1, 0 ) | |
92 endif | |
93 | |
838 | 94 let stopline = 1 |
1121 | 95 |
10048
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
96 let crex = '^\s*\<' . a:type . '\>\s*\<' . escape(a:name, '*') . '\>\s*\(<\s*.*\s*\)\?' |
1121 | 97 let [lnum,lcol] = searchpos( crex, 'w' ) |
98 "let [lnum,lcol] = searchpairpos( crex . '\zs', '', '\(end\|}\)', 'w' ) | |
99 | |
838 | 100 if lnum == 0 && lcol == 0 |
1121 | 101 call cursor(lastpos[1], lastpos[2]) |
838 | 102 return [0,0] |
103 endif | |
104 | |
1121 | 105 let curpos = getpos(".") |
106 let [enum,ecol] = searchpairpos( crex, '', '\(end\|}\)', 'wr' ) | |
107 call cursor(lastpos[1], lastpos[2]) | |
108 | |
838 | 109 if lnum > enum |
1121 | 110 return [0,0] |
838 | 111 endif |
112 " we found a the class def | |
113 return [lnum,enum] | |
114 endfunction | |
115 | |
1121 | 116 function! s:IsInClassDef() |
117 return s:IsPosInClassDef( line('.') ) | |
118 endfunction | |
119 | |
120 function! s:IsPosInClassDef(pos) | |
121 let [snum,enum] = s:GetBufferRubyEntity( '.*', "class" ) | |
838 | 122 let ret = 'nil' |
123 | |
1121 | 124 if snum < a:pos && a:pos < enum |
838 | 125 let ret = snum . '..' . enum |
126 endif | |
127 | |
128 return ret | |
129 endfunction | |
130 | |
1121 | 131 function! s:GetRubyVarType(v) |
852 | 132 let stopline = 1 |
133 let vtp = '' | |
134 let pos = getpos('.') | |
4869 | 135 let sstr = '^\s*#\s*@var\s*'.escape(a:v, '*').'\>\s\+[^ \t]\+\s*$' |
1121 | 136 let [lnum,lcol] = searchpos(sstr,'nb',stopline) |
852 | 137 if lnum != 0 && lcol != 0 |
138 call setpos('.',pos) | |
139 let str = getline(lnum) | |
1121 | 140 let vtp = substitute(str,sstr,'\1','') |
852 | 141 return vtp |
142 endif | |
143 call setpos('.',pos) | |
1121 | 144 let ctors = '\(now\|new\|open\|get_instance' |
145 if exists('g:rubycomplete_rails') && g:rubycomplete_rails == 1 && s:rubycomplete_rails_loaded == 1 | |
146 let ctors = ctors.'\|find\|create' | |
843 | 147 else |
148 endif | |
1121 | 149 let ctors = ctors.'\)' |
843 | 150 |
1121 | 151 let fstr = '=\s*\([^ \t]\+.' . ctors .'\>\|[\[{"''/]\|%[xwQqr][(\[{@]\|[A-Za-z0-9@:\-()\.]\+...\?\|lambda\|&\)' |
10048
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
152 let sstr = ''.escape(a:v, '*').'\>\s*[+\-*/]*'.fstr |
1121 | 153 let [lnum,lcol] = searchpos(sstr,'nb',stopline) |
852 | 154 if lnum != 0 && lcol != 0 |
1121 | 155 let str = matchstr(getline(lnum),fstr,lcol) |
852 | 156 let str = substitute(str,'^=\s*','','') |
1121 | 157 |
852 | 158 call setpos('.',pos) |
1121 | 159 if str == '"' || str == '''' || stridx(tolower(str), '%q[') != -1 |
852 | 160 return 'String' |
1121 | 161 elseif str == '[' || stridx(str, '%w[') != -1 |
852 | 162 return 'Array' |
163 elseif str == '{' | |
164 return 'Hash' | |
838 | 165 elseif str == '/' || str == '%r{' |
166 return 'Regexp' | |
852 | 167 elseif strlen(str) >= 4 && stridx(str,'..') != -1 |
168 return 'Range' | |
1121 | 169 elseif stridx(str, 'lambda') != -1 || str == '&' |
170 return 'Proc' | |
852 | 171 elseif strlen(str) > 4 |
831 | 172 let l = stridx(str,'.') |
852 | 173 return str[0:l-1] |
174 end | |
175 return '' | |
176 endif | |
177 call setpos('.',pos) | |
831 | 178 return '' |
838 | 179 endfunction |
831 | 180 |
840 | 181 "}}} vim-side support functions |
182 | |
1121 | 183 "{{{ vim-side completion function |
184 function! rubycomplete#Init() | |
185 execute "ruby VimRubyCompletion.preload_rails" | |
186 endfunction | |
187 | |
831 | 188 function! rubycomplete#Complete(findstart, base) |
189 "findstart = 1 when we need to get the text length | |
190 if a:findstart | |
191 let line = getline('.') | |
192 let idx = col('.') | |
193 while idx > 0 | |
194 let idx -= 1 | |
195 let c = line[idx-1] | |
196 if c =~ '\w' | |
197 continue | |
198 elseif ! c =~ '\.' | |
10272
57b2b8268d3a
commit https://github.com/vim/vim/commit/4575876dc865d4160f20d61bd822fbe7cafbec41
Christian Brabandt <cb@256bit.org>
parents:
10048
diff
changeset
|
199 let idx = -1 |
831 | 200 break |
201 else | |
202 break | |
203 endif | |
204 endwhile | |
205 | |
206 return idx | |
207 "findstart = 0 when we need to return the list of completions | |
208 else | |
852 | 209 let g:rubycomplete_completions = [] |
1121 | 210 execute "ruby VimRubyCompletion.get_completions('" . a:base . "')" |
838 | 211 return g:rubycomplete_completions |
831 | 212 endif |
213 endfunction | |
1121 | 214 "}}} vim-side completion function |
831 | 215 |
1121 | 216 "{{{ ruby-side code |
831 | 217 function! s:DefRuby() |
218 ruby << RUBYEOF | |
840 | 219 # {{{ ruby completion |
838 | 220 |
1121 | 221 begin |
222 require 'rubygems' # let's assume this is safe...? | |
223 rescue Exception | |
224 #ignore? | |
838 | 225 end |
1121 | 226 class VimRubyCompletion |
227 # {{{ constants | |
228 @@debug = false | |
229 @@ReservedWords = [ | |
230 "BEGIN", "END", | |
231 "alias", "and", | |
232 "begin", "break", | |
233 "case", "class", | |
234 "def", "defined", "do", | |
235 "else", "elsif", "end", "ensure", | |
236 "false", "for", | |
237 "if", "in", | |
238 "module", | |
239 "next", "nil", "not", | |
240 "or", | |
241 "redo", "rescue", "retry", "return", | |
242 "self", "super", | |
243 "then", "true", | |
244 "undef", "unless", "until", | |
245 "when", "while", | |
246 "yield", | |
247 ] | |
838 | 248 |
1121 | 249 @@Operators = [ "%", "&", "*", "**", "+", "-", "/", |
250 "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>", | |
251 "[]", "[]=", "^", ] | |
252 # }}} constants | |
831 | 253 |
1121 | 254 # {{{ buffer analysis magic |
255 def load_requires | |
256 buf = VIM::Buffer.current | |
257 enum = buf.line_number | |
258 nums = Range.new( 1, enum ) | |
259 nums.each do |x| | |
852 | 260 ln = buf[x] |
1121 | 261 begin |
262 eval( "require %s" % $1 ) if /.*require\s*(.*)$/.match( ln ) | |
263 rescue Exception | |
264 #ignore? | |
265 end | |
831 | 266 end |
838 | 267 end |
852 | 268 |
10048
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
269 def load_gems |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
270 fpath = VIM::evaluate("get(g:, 'rubycomplete_gemfile_path', 'Gemfile')") |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
271 return unless File.file?(fpath) && File.readable?(fpath) |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
272 want_bundler = VIM::evaluate("get(g:, 'rubycomplete_use_bundler')") |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
273 parse_file = !want_bundler |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
274 begin |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
275 require 'bundler' |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
276 Bundler.setup |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
277 Bundler.require |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
278 rescue Exception |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
279 parse_file = true |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
280 end |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
281 if parse_file |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
282 File.new(fpath).each_line do |line| |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
283 begin |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
284 require $1 if /\s*gem\s*['"]([^'"]+)/.match(line) |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
285 rescue Exception |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
286 end |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
287 end |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
288 end |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
289 end |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
290 |
1121 | 291 def load_buffer_class(name) |
292 dprint "load_buffer_class(%s) START" % name | |
293 classdef = get_buffer_entity(name, 's:GetBufferRubyClass("%s")') | |
294 return if classdef == nil | |
295 | |
296 pare = /^\s*class\s*(.*)\s*<\s*(.*)\s*\n/.match( classdef ) | |
297 load_buffer_class( $2 ) if pare != nil && $2 != name # load parent class if needed | |
298 | |
4869 | 299 mixre = /.*\n\s*(include|prepend)\s*(.*)\s*\n/.match( classdef ) |
1121 | 300 load_buffer_module( $2 ) if mixre != nil && $2 != name # load mixins if needed |
301 | |
302 begin | |
303 eval classdef | |
304 rescue Exception | |
305 VIM::evaluate( "s:ErrMsg( 'Problem loading class \"%s\", was it already completed?' )" % name ) | |
306 end | |
307 dprint "load_buffer_class(%s) END" % name | |
308 end | |
838 | 309 |
1121 | 310 def load_buffer_module(name) |
311 dprint "load_buffer_module(%s) START" % name | |
312 classdef = get_buffer_entity(name, 's:GetBufferRubyModule("%s")') | |
313 return if classdef == nil | |
314 | |
315 begin | |
316 eval classdef | |
317 rescue Exception | |
318 VIM::evaluate( "s:ErrMsg( 'Problem loading module \"%s\", was it already completed?' )" % name ) | |
319 end | |
320 dprint "load_buffer_module(%s) END" % name | |
852 | 321 end |
1121 | 322 |
323 def get_buffer_entity(name, vimfun) | |
324 loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading") | |
1668 | 325 return nil if loading_allowed.to_i.zero? |
1121 | 326 return nil if /(\"|\')+/.match( name ) |
327 buf = VIM::Buffer.current | |
328 nums = eval( VIM::evaluate( vimfun % name ) ) | |
329 return nil if nums == nil | |
330 return nil if nums.min == nums.max && nums.min == 0 | |
852 | 331 |
1121 | 332 dprint "get_buffer_entity START" |
333 visited = [] | |
334 clscnt = 0 | |
335 bufname = VIM::Buffer.current.name | |
336 classdef = "" | |
337 cur_line = VIM::Buffer.current.line_number | |
338 while (nums != nil && !(nums.min == 0 && nums.max == 0) ) | |
339 dprint "visited: %s" % visited.to_s | |
340 break if visited.index( nums ) | |
341 visited << nums | |
342 | |
343 nums.each do |x| | |
344 if x != cur_line | |
345 next if x == 0 | |
346 ln = buf[x] | |
347 if /^\s*(module|class|def|include)\s+/.match(ln) | |
348 clscnt += 1 if $1 == "class" | |
2225 | 349 #dprint "\$1$1 |
1121 | 350 classdef += "%s\n" % ln |
351 classdef += "end\n" if /def\s+/.match(ln) | |
352 dprint ln | |
353 end | |
354 end | |
355 end | |
840 | 356 |
1121 | 357 nm = "%s(::.*)*\", %s, \"" % [ name, nums.last ] |
358 nums = eval( VIM::evaluate( vimfun % nm ) ) | |
359 dprint "nm: \"%s\"" % nm | |
360 dprint "vimfun: %s" % (vimfun % nm) | |
361 dprint "got nums: %s" % nums.to_s | |
362 end | |
363 if classdef.length > 1 | |
364 classdef += "end\n"*clscnt | |
365 # classdef = "class %s\n%s\nend\n" % [ bufname.gsub( /\/|\\/, "_" ), classdef ] | |
366 end | |
840 | 367 |
1121 | 368 dprint "get_buffer_entity END" |
369 dprint "classdef====start" | |
370 lns = classdef.split( "\n" ) | |
371 lns.each { |x| dprint x } | |
372 dprint "classdef====end" | |
373 return classdef | |
374 end | |
375 | |
376 def get_var_type( receiver ) | |
377 if /(\"|\')+/.match( receiver ) | |
378 "String" | |
379 else | |
380 VIM::evaluate("s:GetRubyVarType('%s')" % receiver) | |
840 | 381 end |
382 end | |
383 | |
1121 | 384 def dprint( txt ) |
385 print txt if @@debug | |
386 end | |
387 | |
4869 | 388 def escape_vim_singlequote_string(str) |
389 str.to_s.gsub(/'/,"\\'") | |
390 end | |
391 | |
1121 | 392 def get_buffer_entity_list( type ) |
393 # this will be a little expensive. | |
394 loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading") | |
395 allow_aggressive_load = VIM::evaluate("exists('g:rubycomplete_classes_in_global') && g:rubycomplete_classes_in_global") | |
1668 | 396 return [] if allow_aggressive_load.to_i.zero? || loading_allowed.to_i.zero? |
1121 | 397 |
398 buf = VIM::Buffer.current | |
399 eob = buf.length | |
400 ret = [] | |
401 rg = 1..eob | |
402 re = eval( "/^\s*%s\s*([A-Za-z0-9_:-]*)(\s*<\s*([A-Za-z0-9_:-]*))?\s*/" % type ) | |
840 | 403 |
1121 | 404 rg.each do |x| |
405 if re.match( buf[x] ) | |
406 next if type == "def" && eval( VIM::evaluate("s:IsPosInClassDef(%s)" % x) ) != nil | |
407 ret.push $1 | |
408 end | |
409 end | |
410 | |
411 return ret | |
412 end | |
413 | |
414 def get_buffer_modules | |
415 return get_buffer_entity_list( "modules" ) | |
416 end | |
417 | |
418 def get_buffer_methods | |
419 return get_buffer_entity_list( "def" ) | |
420 end | |
421 | |
422 def get_buffer_classes | |
423 return get_buffer_entity_list( "class" ) | |
424 end | |
425 | |
426 | |
427 def load_rails | |
428 allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails") | |
1668 | 429 return if allow_rails.to_i.zero? |
852 | 430 |
1121 | 431 buf_path = VIM::evaluate('expand("%:p")') |
432 file_name = VIM::evaluate('expand("%:t")') | |
433 vim_dir = VIM::evaluate('getcwd()') | |
434 file_dir = buf_path.gsub( file_name, '' ) | |
435 file_dir.gsub!( /\\/, "/" ) | |
436 vim_dir.gsub!( /\\/, "/" ) | |
437 vim_dir << "/" | |
438 dirs = [ vim_dir, file_dir ] | |
439 sdirs = [ "", "./", "../", "../../", "../../../", "../../../../" ] | |
440 rails_base = nil | |
441 | |
442 dirs.each do |dir| | |
443 sdirs.each do |sub| | |
444 trail = "%s%s" % [ dir, sub ] | |
445 tcfg = "%sconfig" % trail | |
446 | |
447 if File.exists?( tcfg ) | |
448 rails_base = trail | |
449 break | |
450 end | |
451 end | |
452 break if rails_base | |
453 end | |
838 | 454 |
1121 | 455 return if rails_base == nil |
456 $:.push rails_base unless $:.index( rails_base ) | |
457 | |
458 rails_config = rails_base + "config/" | |
459 rails_lib = rails_base + "lib/" | |
460 $:.push rails_config unless $:.index( rails_config ) | |
461 $:.push rails_lib unless $:.index( rails_lib ) | |
462 | |
463 bootfile = rails_config + "boot.rb" | |
464 envfile = rails_config + "environment.rb" | |
465 if File.exists?( bootfile ) && File.exists?( envfile ) | |
466 begin | |
467 require bootfile | |
468 require envfile | |
469 begin | |
470 require 'console_app' | |
471 require 'console_with_helpers' | |
472 rescue Exception | |
473 dprint "Rails 1.1+ Error %s" % $! | |
474 # assume 1.0 | |
475 end | |
476 #eval( "Rails::Initializer.run" ) #not necessary? | |
477 VIM::command('let s:rubycomplete_rails_loaded = 1') | |
478 dprint "rails loaded" | |
479 rescue Exception | |
480 dprint "Rails Error %s" % $! | |
481 VIM::evaluate( "s:ErrMsg('Error loading rails environment')" ) | |
482 end | |
838 | 483 end |
484 end | |
852 | 485 |
1121 | 486 def get_rails_helpers |
487 allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails") | |
488 rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded') | |
1668 | 489 return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero? |
1121 | 490 |
491 buf_path = VIM::evaluate('expand("%:p")') | |
492 buf_path.gsub!( /\\/, "/" ) | |
493 path_elm = buf_path.split( "/" ) | |
494 dprint "buf_path: %s" % buf_path | |
495 types = [ "app", "db", "lib", "test", "components", "script" ] | |
496 | |
497 i = nil | |
498 ret = [] | |
499 type = nil | |
500 types.each do |t| | |
501 i = path_elm.index( t ) | |
502 break if i | |
503 end | |
504 type = path_elm[i] | |
505 type.downcase! | |
843 | 506 |
1121 | 507 dprint "type: %s" % type |
508 case type | |
509 when "app" | |
510 i += 1 | |
511 subtype = path_elm[i] | |
512 subtype.downcase! | |
513 | |
514 dprint "subtype: %s" % subtype | |
515 case subtype | |
516 when "views" | |
517 ret += ActionView::Base.instance_methods | |
518 ret += ActionView::Base.methods | |
519 when "controllers" | |
520 ret += ActionController::Base.instance_methods | |
521 ret += ActionController::Base.methods | |
522 when "models" | |
523 ret += ActiveRecord::Base.instance_methods | |
524 ret += ActiveRecord::Base.methods | |
525 end | |
526 | |
527 when "db" | |
528 ret += ActiveRecord::ConnectionAdapters::SchemaStatements.instance_methods | |
529 ret += ActiveRecord::ConnectionAdapters::SchemaStatements.methods | |
852 | 530 end |
1121 | 531 |
532 | |
533 return ret | |
840 | 534 end |
1121 | 535 |
536 def add_rails_columns( cls ) | |
537 allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails") | |
538 rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded') | |
1668 | 539 return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero? |
838 | 540 |
1121 | 541 begin |
542 eval( "#{cls}.establish_connection" ) | |
543 return [] unless eval( "#{cls}.ancestors.include?(ActiveRecord::Base).to_s" ) | |
544 col = eval( "#{cls}.column_names" ) | |
545 return col if col | |
546 rescue | |
547 dprint "add_rails_columns err: (cls: %s) %s" % [ cls, $! ] | |
548 return [] | |
549 end | |
550 return [] | |
551 end | |
552 | |
553 def clean_sel(sel, msg) | |
4869 | 554 ret = sel.reject{|x|x.nil?}.uniq |
555 ret = ret.grep(/^#{Regexp.quote(msg)}/) if msg != nil | |
556 ret | |
1121 | 557 end |
558 | |
559 def get_rails_view_methods | |
560 allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails") | |
561 rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded') | |
1668 | 562 return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero? |
1121 | 563 |
564 buf_path = VIM::evaluate('expand("%:p")') | |
565 buf_path.gsub!( /\\/, "/" ) | |
566 pelm = buf_path.split( "/" ) | |
567 idx = pelm.index( "views" ) | |
568 | |
569 return [] unless idx | |
570 idx += 1 | |
831 | 571 |
1121 | 572 clspl = pelm[idx].camelize.pluralize |
573 cls = clspl.singularize | |
574 | |
575 ret = [] | |
576 begin | |
577 ret += eval( "#{cls}.instance_methods" ) | |
578 ret += eval( "#{clspl}Helper.instance_methods" ) | |
579 rescue Exception | |
580 dprint "Error: Unable to load rails view helpers for %s: %s" % [ cls, $! ] | |
581 end | |
582 | |
583 return ret | |
584 end | |
585 # }}} buffer analysis magic | |
838 | 586 |
1121 | 587 # {{{ main completion code |
588 def self.preload_rails | |
589 a = VimRubyCompletion.new | |
590 require 'Thread' | |
591 Thread.new(a) do |b| | |
592 begin | |
593 b.load_rails | |
594 rescue | |
595 end | |
596 end | |
597 a.load_rails | |
598 rescue | |
599 end | |
852 | 600 |
1121 | 601 def self.get_completions(base) |
602 b = VimRubyCompletion.new | |
603 b.get_completions base | |
838 | 604 end |
852 | 605 |
1121 | 606 def get_completions(base) |
607 loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading") | |
1668 | 608 if loading_allowed.to_i == 1 |
1121 | 609 load_requires |
610 load_rails | |
611 end | |
612 | |
10048
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
613 want_gems = VIM::evaluate("get(g:, 'rubycomplete_load_gemfile')") |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
614 load_gems unless want_gems.to_i.zero? |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
615 |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
616 |
1121 | 617 input = VIM::Buffer.current.line |
618 cpos = VIM::Window.current.cursor[1] - 1 | |
619 input = input[0..cpos] | |
620 input += base | |
621 input.sub!(/.*[ \t\n\"\\'`><=;|&{(]/, '') # Readline.basic_word_break_characters | |
622 input.sub!(/self\./, '') | |
623 input.sub!(/.*((\.\.[\[(]?)|([\[(]))/, '') | |
624 | |
625 dprint 'input %s' % input | |
626 message = nil | |
627 receiver = nil | |
628 methods = [] | |
629 variables = [] | |
630 classes = [] | |
631 constants = [] | |
632 | |
633 case input | |
634 when /^(\/[^\/]*\/)\.([^.]*)$/ # Regexp | |
635 receiver = $1 | |
636 message = Regexp.quote($2) | |
637 methods = Regexp.instance_methods(true) | |
638 | |
639 when /^([^\]]*\])\.([^.]*)$/ # Array | |
640 receiver = $1 | |
641 message = Regexp.quote($2) | |
642 methods = Array.instance_methods(true) | |
852 | 643 |
1121 | 644 when /^([^\}]*\})\.([^.]*)$/ # Proc or Hash |
645 receiver = $1 | |
646 message = Regexp.quote($2) | |
647 methods = Proc.instance_methods(true) | Hash.instance_methods(true) | |
648 | |
649 when /^(:[^:.]*)$/ # Symbol | |
650 dprint "symbol" | |
651 if Symbol.respond_to?(:all_symbols) | |
652 receiver = $1 | |
653 message = $1.sub( /:/, '' ) | |
654 methods = Symbol.all_symbols.collect{|s| s.id2name} | |
655 methods.delete_if { |c| c.match( /'/ ) } | |
656 end | |
657 | |
658 when /^::([A-Z][^:\.\(]*)$/ # Absolute Constant or class methods | |
659 dprint "const or cls" | |
660 receiver = $1 | |
661 methods = Object.constants | |
662 methods.grep(/^#{receiver}/).collect{|e| "::" + e} | |
831 | 663 |
2225 | 664 when /^(((::)?[A-Z][^:.\(]*)+?)::?([^:.]*)$/ # Constant or class methods |
1121 | 665 receiver = $1 |
666 message = Regexp.quote($4) | |
667 dprint "const or cls 2 [recv: \'%s\', msg: \'%s\']" % [ receiver, message ] | |
668 load_buffer_class( receiver ) | |
669 begin | |
670 classes = eval("#{receiver}.constants") | |
671 #methods = eval("#{receiver}.methods") | |
672 rescue Exception | |
673 dprint "exception: %s" % $! | |
674 methods = [] | |
675 end | |
676 methods.grep(/^#{message}/).collect{|e| receiver + "::" + e} | |
677 | |
678 when /^(:[^:.]+)\.([^.]*)$/ # Symbol | |
679 dprint "symbol" | |
680 receiver = $1 | |
681 message = Regexp.quote($2) | |
682 methods = Symbol.instance_methods(true) | |
838 | 683 |
1121 | 684 when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/ # Numeric |
685 dprint "numeric" | |
686 receiver = $1 | |
687 message = Regexp.quote($4) | |
688 begin | |
689 methods = eval(receiver).methods | |
690 rescue Exception | |
691 methods = [] | |
692 end | |
693 | |
694 when /^(\$[^.]*)$/ #global | |
695 dprint "global" | |
696 methods = global_variables.grep(Regexp.new(Regexp.quote($1))) | |
697 | |
2225 | 698 when /^((\.?[^.]+)+?)\.([^.]*)$/ # variable |
1121 | 699 dprint "variable" |
700 receiver = $1 | |
701 message = Regexp.quote($3) | |
702 load_buffer_class( receiver ) | |
703 | |
704 cv = eval("self.class.constants") | |
705 vartype = get_var_type( receiver ) | |
706 dprint "vartype: %s" % vartype | |
10048
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
707 |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
708 invalid_vartype = ['', "gets"] |
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
709 if !invalid_vartype.include?(vartype) |
1121 | 710 load_buffer_class( vartype ) |
838 | 711 |
1121 | 712 begin |
713 methods = eval("#{vartype}.instance_methods") | |
714 variables = eval("#{vartype}.instance_variables") | |
715 rescue Exception | |
716 dprint "load_buffer_class err: %s" % $! | |
717 end | |
718 elsif (cv).include?(receiver) | |
719 # foo.func and foo is local var. | |
720 methods = eval("#{receiver}.methods") | |
721 vartype = receiver | |
722 elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver | |
723 vartype = receiver | |
724 # Foo::Bar.func | |
725 begin | |
726 methods = eval("#{receiver}.methods") | |
727 rescue Exception | |
728 end | |
729 else | |
730 # func1.func2 | |
731 ObjectSpace.each_object(Module){|m| | |
732 next if m.name != "IRB::Context" and | |
733 /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name | |
734 methods.concat m.instance_methods(false) | |
735 } | |
736 end | |
10048
43efa4f5a8ea
commit https://github.com/vim/vim/commit/89bcfda6834aba724d12554a34b9ed49f5789fd5
Christian Brabandt <cb@256bit.org>
parents:
4869
diff
changeset
|
737 variables += add_rails_columns( "#{vartype}" ) if vartype && !invalid_vartype.include?(vartype) |
831 | 738 |
1121 | 739 when /^\(?\s*[A-Za-z0-9:^@.%\/+*\(\)]+\.\.\.?[A-Za-z0-9:^@.%\/+*\(\)]+\s*\)?\.([^.]*)/ |
740 message = $1 | |
741 methods = Range.instance_methods(true) | |
742 | |
743 when /^\.([^.]*)$/ # unknown(maybe String) | |
744 message = Regexp.quote($1) | |
745 methods = String.instance_methods(true) | |
746 | |
747 else | |
748 dprint "default/other" | |
749 inclass = eval( VIM::evaluate("s:IsInClassDef()") ) | |
750 | |
751 if inclass != nil | |
752 dprint "inclass" | |
753 classdef = "%s\n" % VIM::Buffer.current[ inclass.min ] | |
754 found = /^\s*class\s*([A-Za-z0-9_-]*)(\s*<\s*([A-Za-z0-9_:-]*))?\s*\n$/.match( classdef ) | |
755 | |
756 if found != nil | |
757 receiver = $1 | |
758 message = input | |
759 load_buffer_class( receiver ) | |
760 begin | |
761 methods = eval( "#{receiver}.instance_methods" ) | |
762 variables += add_rails_columns( "#{receiver}" ) | |
763 rescue Exception | |
764 found = nil | |
765 end | |
766 end | |
838 | 767 end |
831 | 768 |
1121 | 769 if inclass == nil || found == nil |
770 dprint "inclass == nil" | |
771 methods = get_buffer_methods | |
772 methods += get_rails_view_methods | |
831 | 773 |
1121 | 774 cls_const = Class.constants |
775 constants = cls_const.select { |c| /^[A-Z_-]+$/.match( c ) } | |
776 classes = eval("self.class.constants") - constants | |
777 classes += get_buffer_classes | |
778 classes += get_buffer_modules | |
831 | 779 |
1121 | 780 include_objectspace = VIM::evaluate("exists('g:rubycomplete_include_objectspace') && g:rubycomplete_include_objectspace") |
781 ObjectSpace.each_object(Class) { |cls| classes << cls.to_s } if include_objectspace == "1" | |
782 message = receiver = input | |
838 | 783 end |
784 | |
1121 | 785 methods += get_rails_helpers |
786 methods += Kernel.public_methods | |
838 | 787 end |
852 | 788 |
1121 | 789 |
790 include_object = VIM::evaluate("exists('g:rubycomplete_include_object') && g:rubycomplete_include_object") | |
791 methods = clean_sel( methods, message ) | |
792 methods = (methods-Object.instance_methods) if include_object == "0" | |
793 rbcmeth = (VimRubyCompletion.instance_methods-Object.instance_methods) # lets remove those rubycomplete methods | |
794 methods = (methods-rbcmeth) | |
795 | |
796 variables = clean_sel( variables, message ) | |
797 classes = clean_sel( classes, message ) - ["VimRubyCompletion"] | |
798 constants = clean_sel( constants, message ) | |
799 | |
800 valid = [] | |
4869 | 801 valid += methods.collect { |m| { :name => m.to_s, :type => 'm' } } |
802 valid += variables.collect { |v| { :name => v.to_s, :type => 'v' } } | |
803 valid += classes.collect { |c| { :name => c.to_s, :type => 't' } } | |
804 valid += constants.collect { |d| { :name => d.to_s, :type => 'd' } } | |
1121 | 805 valid.sort! { |x,y| x[:name] <=> y[:name] } |
806 | |
807 outp = "" | |
808 | |
809 rg = 0..valid.length | |
810 rg.step(150) do |x| | |
811 stpos = 0+x | |
812 enpos = 150+x | |
4869 | 813 valid[stpos..enpos].each { |c| outp += "{'word':'%s','item':'%s','kind':'%s'}," % [ c[:name], c[:name], c[:type] ].map{|x|escape_vim_singlequote_string(x)} } |
1121 | 814 outp.sub!(/,$/, '') |
815 | |
816 VIM::command("call extend(g:rubycomplete_completions, [%s])" % outp) | |
817 outp = "" | |
831 | 818 end |
838 | 819 end |
1121 | 820 # }}} main completion code |
838 | 821 |
1121 | 822 end # VimRubyCompletion |
840 | 823 # }}} ruby completion |
831 | 824 RUBYEOF |
825 endfunction | |
826 | |
1121 | 827 let s:rubycomplete_rails_loaded = 0 |
838 | 828 |
831 | 829 call s:DefRuby() |
1121 | 830 "}}} ruby-side code |
831 | |
832 | |
833 " vim:tw=78:sw=4:ts=8:et:fdm=marker:ft=vim:norl: |