1c6249bb2SBram Moolenaar" Vim completion script
2c6249bb2SBram Moolenaar" Language:             Ruby
3fc1421ebSBram Moolenaar" Maintainer:           Mark Guzman <[email protected]>
4c6249bb2SBram Moolenaar" Info:                 $Id$
5c6249bb2SBram Moolenaar" URL:                  http://vim-ruby.rubyforge.org
6c6249bb2SBram Moolenaar" Anon CVS:             See above site
7c6249bb2SBram Moolenaar" Release Coordinator:  Doug Kearns <[email protected]>
8c6249bb2SBram Moolenaar" ----------------------------------------------------------------------------
9c6249bb2SBram Moolenaar"
10c6249bb2SBram Moolenaar" Ruby IRB/Complete author: Keiju ISHITSUKA([email protected])
11c6249bb2SBram Moolenaar" ----------------------------------------------------------------------------
12c6249bb2SBram Moolenaar
13eb3593b3SBram Moolenaar" {{{ requirement checks
14c6249bb2SBram Moolenaarif !has('ruby')
15fc1421ebSBram Moolenaar    echohl ErrorMsg
16c6249bb2SBram Moolenaar    echo "Error: Required vim compiled with +ruby"
17fc1421ebSBram Moolenaar    echohl None
18c6249bb2SBram Moolenaar    finish
19c6249bb2SBram Moolenaarendif
20c6249bb2SBram Moolenaar
21c6249bb2SBram Moolenaarif version < 700
22fc1421ebSBram Moolenaar    echohl ErrorMsg
23c6249bb2SBram Moolenaar    echo "Error: Required vim >= 7.0"
24fc1421ebSBram Moolenaar    echohl None
25c6249bb2SBram Moolenaar    finish
26c6249bb2SBram Moolenaarendif
27eb3593b3SBram Moolenaar" }}} requirement checks
28c6249bb2SBram Moolenaar
29eb3593b3SBram Moolenaarif !exists("g:rubycomplete_rails")
30eb3593b3SBram Moolenaar    let g:rubycomplete_rails = 0
31eb3593b3SBram Moolenaarendif
32fc1421ebSBram Moolenaar
33eb3593b3SBram Moolenaarif !exists("g:rubycomplete_classes_in_global")
34eb3593b3SBram Moolenaar    let g:rubycomplete_classes_in_global = 0
35eb3593b3SBram Moolenaarendif
36eb3593b3SBram Moolenaar
37eb3593b3SBram Moolenaar" {{{ vim-side support functions
38fc1421ebSBram Moolenaarfunction! GetBufferRubyModule(name)
39fc1421ebSBram Moolenaar    let [snum,enum] = GetBufferRubyEntity(a:name, "module")
40fc1421ebSBram Moolenaar    return snum . '..' . enum
41fc1421ebSBram Moolenaarendfunction
42fc1421ebSBram Moolenaar
43fc1421ebSBram Moolenaarfunction! GetBufferRubyClass(name)
44fc1421ebSBram Moolenaar    let [snum,enum] = GetBufferRubyEntity(a:name, "class")
45fc1421ebSBram Moolenaar    return snum . '..' . enum
46fc1421ebSBram Moolenaarendfunction
47fc1421ebSBram Moolenaar
48fc1421ebSBram Moolenaarfunction! GetBufferRubySingletonMethods(name)
49fc1421ebSBram Moolenaarendfunction
50fc1421ebSBram Moolenaar
51fc1421ebSBram Moolenaarfunction! GetBufferRubyEntity( name, type )
52fc1421ebSBram Moolenaar    let stopline = 1
53fc1421ebSBram Moolenaar    let crex = '^\s*' . a:type . '\s*' . a:name . '\s*\(<\s*.*\s*\)\?\n*\(\(\s\|#\).*\n*\)*\n*\s*end$'
54fc1421ebSBram Moolenaar    let [lnum,lcol] = searchpos( crex, 'nbw')
55fc1421ebSBram Moolenaar    if lnum == 0 && lcol == 0
56fc1421ebSBram Moolenaar        return [0,0]
57fc1421ebSBram Moolenaar    endif
58fc1421ebSBram Moolenaar
59fc1421ebSBram Moolenaar    let [enum,ecol] = searchpos( crex, 'nebw')
60fc1421ebSBram Moolenaar    if lnum > enum
61fc1421ebSBram Moolenaar        let realdef = getline( lnum )
62fc1421ebSBram Moolenaar        let crexb = '^' . realdef . '\n*\(\(\s\|#\).*\n*\)*\n*\s*end$'
63fc1421ebSBram Moolenaar        let [enum,ecol] = searchpos( crexb, 'necw' )
64fc1421ebSBram Moolenaar    endif
65fc1421ebSBram Moolenaar    " we found a the class def
66fc1421ebSBram Moolenaar    return [lnum,enum]
67fc1421ebSBram Moolenaarendfunction
68fc1421ebSBram Moolenaar
69fc1421ebSBram Moolenaarfunction! IsInClassDef()
70fc1421ebSBram Moolenaar    let [snum,enum] = GetBufferRubyEntity( '.*', "class" )
71fc1421ebSBram Moolenaar    let ret = 'nil'
72fc1421ebSBram Moolenaar    let pos = line('.')
73fc1421ebSBram Moolenaar
74fc1421ebSBram Moolenaar    if snum < pos && pos < enum
75fc1421ebSBram Moolenaar        let ret = snum . '..' . enum
76fc1421ebSBram Moolenaar    endif
77fc1421ebSBram Moolenaar
78fc1421ebSBram Moolenaar    return ret
79fc1421ebSBram Moolenaarendfunction
80fc1421ebSBram Moolenaar
81fc1421ebSBram Moolenaarfunction! GetRubyVarType(v)
82c6249bb2SBram Moolenaar    let stopline = 1
83c6249bb2SBram Moolenaar    let vtp = ''
84c6249bb2SBram Moolenaar    let pos = getpos('.')
85c6249bb2SBram Moolenaar    let [lnum,lcol] = searchpos('^\s*#\s*@var\s*'.a:v.'\>\s\+[^ \t]\+\s*$','nb',stopline)
86c6249bb2SBram Moolenaar    if lnum != 0 && lcol != 0
87c6249bb2SBram Moolenaar        call setpos('.',pos)
88c6249bb2SBram Moolenaar        let str = getline(lnum)
89c6249bb2SBram Moolenaar        let vtp = substitute(str,'^\s*#\s*@var\s*'.a:v.'\>\s\+\([^ \t]\+\)\s*$','\1','')
90c6249bb2SBram Moolenaar        return vtp
91c6249bb2SBram Moolenaar    endif
92c6249bb2SBram Moolenaar    call setpos('.',pos)
93551dbcc9SBram Moolenaar    if g:rubycomplete_rails == 1 && g:rubycomplete_rails_loaded == 1
94551dbcc9SBram Moolenaar        let ctors = '\(now\|new\|open\|get_instance\|find\|create\)'
95551dbcc9SBram Moolenaar    else
96551dbcc9SBram Moolenaar        let ctors = '\(now\|new\|open\|get_instance\)'
97551dbcc9SBram Moolenaar    endif
98551dbcc9SBram Moolenaar
99*d8fc5c0bSBram Moolenaar    let [lnum,lcol] = searchpos(''.a:v.'\>\s*[+\-*/]*=\s*\([^ \t]\+.' . ctors .'\>\|[\[{"''/]\|%r{\|[A-Za-z0-9@:\-()]\+...\?\)','nb',stopline)
100c6249bb2SBram Moolenaar    if lnum != 0 && lcol != 0
101*d8fc5c0bSBram Moolenaar        let str = matchstr(getline(lnum),'=\s*\([^ \t]\+.' . ctors . '\>\|[\[{"''/]\|%r{\|[A-Za-z0-9@:\-()]\+...\?\)',lcol)
102c6249bb2SBram Moolenaar        let str = substitute(str,'^=\s*','','')
103c6249bb2SBram Moolenaar        call setpos('.',pos)
104c6249bb2SBram Moolenaar        if str == '"' || str == ''''
105c6249bb2SBram Moolenaar            return 'String'
106c6249bb2SBram Moolenaar        elseif str == '['
107c6249bb2SBram Moolenaar            return 'Array'
108c6249bb2SBram Moolenaar        elseif str == '{'
109c6249bb2SBram Moolenaar            return 'Hash'
110fc1421ebSBram Moolenaar        elseif str == '/' || str == '%r{'
111fc1421ebSBram Moolenaar            return 'Regexp'
112*d8fc5c0bSBram Moolenaar        elseif strlen(str) >= 4 && stridx(str,'..') != -1
113*d8fc5c0bSBram Moolenaar            return 'Range'
114c6249bb2SBram Moolenaar        elseif strlen(str) > 4
115c6249bb2SBram Moolenaar            let l = stridx(str,'.')
116c6249bb2SBram Moolenaar            return str[0:l-1]
117c6249bb2SBram Moolenaar        end
118c6249bb2SBram Moolenaar        return ''
119c6249bb2SBram Moolenaar    endif
120c6249bb2SBram Moolenaar    call setpos('.',pos)
121c6249bb2SBram Moolenaar    return ''
122fc1421ebSBram Moolenaarendfunction
123c6249bb2SBram Moolenaar
124eb3593b3SBram Moolenaar"}}} vim-side support functions
125eb3593b3SBram Moolenaar
126c6249bb2SBram Moolenaarfunction! rubycomplete#Complete(findstart, base)
127c6249bb2SBram Moolenaar     "findstart = 1 when we need to get the text length
128c6249bb2SBram Moolenaar    if a:findstart
129c6249bb2SBram Moolenaar        let line = getline('.')
130c6249bb2SBram Moolenaar        let idx = col('.')
131c6249bb2SBram Moolenaar        while idx > 0
132c6249bb2SBram Moolenaar            let idx -= 1
133c6249bb2SBram Moolenaar            let c = line[idx-1]
134c6249bb2SBram Moolenaar            if c =~ '\w'
135c6249bb2SBram Moolenaar                continue
136c6249bb2SBram Moolenaar            elseif ! c =~ '\.'
137c6249bb2SBram Moolenaar                idx = -1
138c6249bb2SBram Moolenaar                break
139c6249bb2SBram Moolenaar            else
140c6249bb2SBram Moolenaar                break
141c6249bb2SBram Moolenaar            endif
142c6249bb2SBram Moolenaar        endwhile
143c6249bb2SBram Moolenaar
144c6249bb2SBram Moolenaar        return idx
145c6249bb2SBram Moolenaar    "findstart = 0 when we need to return the list of completions
146c6249bb2SBram Moolenaar    else
147fc1421ebSBram Moolenaar        let g:rubycomplete_completions = []
148c6249bb2SBram Moolenaar        execute "ruby get_completions('" . a:base . "')"
149fc1421ebSBram Moolenaar        return g:rubycomplete_completions
150c6249bb2SBram Moolenaar    endif
151c6249bb2SBram Moolenaarendfunction
152c6249bb2SBram Moolenaar
153c6249bb2SBram Moolenaar
154c6249bb2SBram Moolenaarfunction! s:DefRuby()
155c6249bb2SBram Moolenaarruby << RUBYEOF
156eb3593b3SBram Moolenaar# {{{ ruby completion
157fc1421ebSBram MoolenaarRailsWords = [
158fc1421ebSBram Moolenaar      "has_many", "has_one",
159fc1421ebSBram Moolenaar      "belongs_to",
160fc1421ebSBram Moolenaar    ]
161fc1421ebSBram Moolenaar
162c6249bb2SBram MoolenaarReservedWords = [
163c6249bb2SBram Moolenaar      "BEGIN", "END",
164c6249bb2SBram Moolenaar      "alias", "and",
165c6249bb2SBram Moolenaar      "begin", "break",
166c6249bb2SBram Moolenaar      "case", "class",
167c6249bb2SBram Moolenaar      "def", "defined", "do",
168c6249bb2SBram Moolenaar      "else", "elsif", "end", "ensure",
169c6249bb2SBram Moolenaar      "false", "for",
170c6249bb2SBram Moolenaar      "if", "in",
171c6249bb2SBram Moolenaar      "module",
172c6249bb2SBram Moolenaar      "next", "nil", "not",
173c6249bb2SBram Moolenaar      "or",
174c6249bb2SBram Moolenaar      "redo", "rescue", "retry", "return",
175c6249bb2SBram Moolenaar      "self", "super",
176c6249bb2SBram Moolenaar      "then", "true",
177c6249bb2SBram Moolenaar      "undef", "unless", "until",
178c6249bb2SBram Moolenaar      "when", "while",
179c6249bb2SBram Moolenaar      "yield",
180c6249bb2SBram Moolenaar    ]
181c6249bb2SBram Moolenaar
182c6249bb2SBram MoolenaarOperators = [ "%", "&", "*", "**", "+",  "-",  "/",
183c6249bb2SBram Moolenaar      "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
184c6249bb2SBram Moolenaar      "[]", "[]=", "^", ]
185c6249bb2SBram Moolenaar
186c6249bb2SBram Moolenaar
187c6249bb2SBram Moolenaardef load_requires
188eb3593b3SBram Moolenaar  buf = VIM::Buffer.current
189eb3593b3SBram Moolenaar  enum = buf.line_number
190c6249bb2SBram Moolenaar  nums = Range.new( 1, enum )
191c6249bb2SBram Moolenaar  nums.each do |x|
192eb3593b3SBram Moolenaar    ln = buf[x]
193c6249bb2SBram Moolenaar    begin
194c6249bb2SBram Moolenaar      eval( "require %s" % $1 ) if /.*require\s*(.*)$/.match( ln )
195c6249bb2SBram Moolenaar    rescue Exception
196c6249bb2SBram Moolenaar      #ignore?
197c6249bb2SBram Moolenaar    end
198c6249bb2SBram Moolenaar  end
199c6249bb2SBram Moolenaarend
200c6249bb2SBram Moolenaar
201fc1421ebSBram Moolenaardef load_buffer_class(name)
202fc1421ebSBram Moolenaar  classdef = get_buffer_entity(name, 'GetBufferRubyClass("%s")')
203fc1421ebSBram Moolenaar  return if classdef == nil
204fc1421ebSBram Moolenaar
205fc1421ebSBram Moolenaar  pare = /^\s*class\s*(.*)\s*<\s*(.*)\s*\n/.match( classdef )
206fc1421ebSBram Moolenaar  load_buffer_class( $2 ) if pare != nil
207fc1421ebSBram Moolenaar
208fc1421ebSBram Moolenaar  mixre = /.*\n\s*include\s*(.*)\s*\n/.match( classdef )
209fc1421ebSBram Moolenaar  load_buffer_module( $2 ) if mixre != nil
210fc1421ebSBram Moolenaar
211fc1421ebSBram Moolenaar  eval classdef
212fc1421ebSBram Moolenaarend
213fc1421ebSBram Moolenaar
214fc1421ebSBram Moolenaardef load_buffer_module(name)
215fc1421ebSBram Moolenaar  classdef = get_buffer_entity(name, 'GetBufferRubyModule("%s")')
216fc1421ebSBram Moolenaar  return if classdef == nil
217fc1421ebSBram Moolenaar
218fc1421ebSBram Moolenaar  eval classdef
219fc1421ebSBram Moolenaarend
220fc1421ebSBram Moolenaar
221fc1421ebSBram Moolenaardef get_buffer_entity(name, vimfun)
222*d8fc5c0bSBram Moolenaar  return nil if /(\"|\')+/.match( name )
223eb3593b3SBram Moolenaar  buf = VIM::Buffer.current
224fc1421ebSBram Moolenaar  nums = eval( VIM::evaluate( vimfun % name ) )
225fc1421ebSBram Moolenaar  return nil if nums == nil
226fc1421ebSBram Moolenaar  return nil if nums.min == nums.max && nums.min == 0
227fc1421ebSBram Moolenaar
228fc1421ebSBram Moolenaar  cur_line = VIM::Buffer.current.line_number
229fc1421ebSBram Moolenaar  classdef = ""
230fc1421ebSBram Moolenaar  nums.each do |x|
231fc1421ebSBram Moolenaar    if x != cur_line
232eb3593b3SBram Moolenaar      ln = buf[x]
233fc1421ebSBram Moolenaar      classdef += "%s\n" % ln
234fc1421ebSBram Moolenaar    end
235fc1421ebSBram Moolenaar  end
236fc1421ebSBram Moolenaar
237fc1421ebSBram Moolenaar  return classdef
238fc1421ebSBram Moolenaarend
239fc1421ebSBram Moolenaar
240*d8fc5c0bSBram Moolenaardef get_var_type( receiver )
241*d8fc5c0bSBram Moolenaar  if /(\"|\')+/.match( receiver )
242*d8fc5c0bSBram Moolenaar    "String"
243*d8fc5c0bSBram Moolenaar  else
244*d8fc5c0bSBram Moolenaar    VIM::evaluate("GetRubyVarType('%s')" % receiver)
245*d8fc5c0bSBram Moolenaar  end
246*d8fc5c0bSBram Moolenaarend
247*d8fc5c0bSBram Moolenaar
248eb3593b3SBram Moolenaardef get_buffer_classes()
249eb3593b3SBram Moolenaar  # this will be a little expensive.
250eb3593b3SBram Moolenaar  allow_aggressive_load = VIM::evaluate('g:rubycomplete_classes_in_global')
251eb3593b3SBram Moolenaar  return [] if allow_aggressive_load != '1'
252eb3593b3SBram Moolenaar
253eb3593b3SBram Moolenaar  buf = VIM::Buffer.current
254eb3593b3SBram Moolenaar  eob = buf.length
255eb3593b3SBram Moolenaar  ret = []
256eb3593b3SBram Moolenaar  rg = 1..eob
257eb3593b3SBram Moolenaar
258eb3593b3SBram Moolenaar  rg.each do |x|
259eb3593b3SBram Moolenaar    if /^\s*class\s*([A-Za-z0-9_-]*)(\s*<\s*([A-Za-z0-9_:-]*))?\s*/.match( buf[x] )
260eb3593b3SBram Moolenaar      ret.push $1
261eb3593b3SBram Moolenaar    end
262eb3593b3SBram Moolenaar  end
263eb3593b3SBram Moolenaar
264eb3593b3SBram Moolenaar  return ret
265eb3593b3SBram Moolenaarend
266eb3593b3SBram Moolenaar
267fc1421ebSBram Moolenaardef load_rails()
268fc1421ebSBram Moolenaar  allow_rails = VIM::evaluate('g:rubycomplete_rails')
269fc1421ebSBram Moolenaar  return if allow_rails != '1'
270fc1421ebSBram Moolenaar
271fc1421ebSBram Moolenaar  buf_path = VIM::evaluate('expand("%:p")')
272fc1421ebSBram Moolenaar  file_name = VIM::evaluate('expand("%:t")')
273fc1421ebSBram Moolenaar  path = buf_path.gsub( file_name, '' )
274fc1421ebSBram Moolenaar  path.gsub!( /\\/, "/" )
275551dbcc9SBram Moolenaar  pup = [ "./", "../", "../../", "../../../", "../../../../" ]
276fc1421ebSBram Moolenaar  pok = nil
277fc1421ebSBram Moolenaar
278fc1421ebSBram Moolenaar  pup.each do |sup|
279fc1421ebSBram Moolenaar    tpok = "%s%sconfig" % [ path, sup ]
280fc1421ebSBram Moolenaar    if File.exists?( tpok )
281fc1421ebSBram Moolenaar      pok = tpok
282fc1421ebSBram Moolenaar      break
283fc1421ebSBram Moolenaar    end
284fc1421ebSBram Moolenaar  end
285eb3593b3SBram Moolenaar
286eb3593b3SBram Moolenaar  return if pok == nil
287551dbcc9SBram Moolenaar
288fc1421ebSBram Moolenaar  bootfile = pok + "/boot.rb"
289551dbcc9SBram Moolenaar  envfile = pok + "/environment.rb"
290551dbcc9SBram Moolenaar  if File.exists?( bootfile ) && File.exists?( envfile )
291551dbcc9SBram Moolenaar    begin
292eb3593b3SBram Moolenaar      require bootfile
293551dbcc9SBram Moolenaar      require envfile
294551dbcc9SBram Moolenaar      require 'console_app'
295551dbcc9SBram Moolenaar      require 'console_with_helpers'
296551dbcc9SBram Moolenaar      VIM::command('let g:rubycomplete_rails_loaded = 1')
297551dbcc9SBram Moolenaar    rescue
298551dbcc9SBram Moolenaar      print "Error loading rails environment"
299551dbcc9SBram Moolenaar    end
300eb3593b3SBram Moolenaar  end
301fc1421ebSBram Moolenaarend
302fc1421ebSBram Moolenaar
303fc1421ebSBram Moolenaardef get_rails_helpers
304fc1421ebSBram Moolenaar  allow_rails = VIM::evaluate('g:rubycomplete_rails')
305eb3593b3SBram Moolenaar  rails_loaded = VIM::evaluate('g:rubycomplete_rails_loaded')
306eb3593b3SBram Moolenaar  return [] if allow_rails != '1' || rails_loaded != '1'
307fc1421ebSBram Moolenaar  return RailsWords
308fc1421ebSBram Moolenaarend
309fc1421ebSBram Moolenaar
310c6249bb2SBram Moolenaardef get_completions(base)
311c6249bb2SBram Moolenaar  load_requires
312fc1421ebSBram Moolenaar  load_rails
313fc1421ebSBram Moolenaar
314fc1421ebSBram Moolenaar  input = VIM::Buffer.current.line
315*d8fc5c0bSBram Moolenaar  cpos = VIM::Window.current.cursor[1] - 1
316*d8fc5c0bSBram Moolenaar  input = input[0..cpos] if cpos != 0
317*d8fc5c0bSBram Moolenaar  input += base
318c6249bb2SBram Moolenaar
319*d8fc5c0bSBram Moolenaar  rip = input.rindex(/\s/,cpos)
320*d8fc5c0bSBram Moolenaar  if rip
321*d8fc5c0bSBram Moolenaar    input = input[rip..input.length]
322*d8fc5c0bSBram Moolenaar  end
323*d8fc5c0bSBram Moolenaar
324*d8fc5c0bSBram Moolenaar  asn = /^.*(\+|\-|\*|=|\(|\[)=?(\s*[A-Za-z0-9_:@.-]*)(\s*(\{|\+|\-|\*|\%|\/)?\s*).*/
325*d8fc5c0bSBram Moolenaar  if asn.match(input)
326*d8fc5c0bSBram Moolenaar    input = $2
327*d8fc5c0bSBram Moolenaar  end
328*d8fc5c0bSBram Moolenaar
329*d8fc5c0bSBram Moolenaar  input.strip!
330*d8fc5c0bSBram Moolenaar  message = nil
331*d8fc5c0bSBram Moolenaar  receiver = nil
332*d8fc5c0bSBram Moolenaar  candidates = []
333c6249bb2SBram Moolenaar
334c6249bb2SBram Moolenaar  case input
335*d8fc5c0bSBram Moolenaar    when /^(\/[^\/]*\/)\.([^.]*)$/ # Regexp
336c6249bb2SBram Moolenaar      receiver = $1
337c6249bb2SBram Moolenaar      message = Regexp.quote($2)
338c6249bb2SBram Moolenaar      candidates = Regexp.instance_methods(true)
339c6249bb2SBram Moolenaar
340*d8fc5c0bSBram Moolenaar    when /^([^\]]*\])\.([^.]*)$/ # Array
341c6249bb2SBram Moolenaar      receiver = $1
342c6249bb2SBram Moolenaar      message = Regexp.quote($2)
343c6249bb2SBram Moolenaar      candidates = Array.instance_methods(true)
344c6249bb2SBram Moolenaar
345*d8fc5c0bSBram Moolenaar    when /^([^\}]*\})\.([^.]*)$/ # Proc or Hash
346c6249bb2SBram Moolenaar      receiver = $1
347c6249bb2SBram Moolenaar      message = Regexp.quote($2)
348c6249bb2SBram Moolenaar      candidates = Proc.instance_methods(true) | Hash.instance_methods(true)
349c6249bb2SBram Moolenaar
350*d8fc5c0bSBram Moolenaar    when /^(:[^:.]*)$/ # Symbol
351c6249bb2SBram Moolenaar      if Symbol.respond_to?(:all_symbols)
352*d8fc5c0bSBram Moolenaar        receiver = $1
353*d8fc5c0bSBram Moolenaar        candidates = Symbol.all_symbols.collect{|s| s.id2name}
354*d8fc5c0bSBram Moolenaar        candidates.delete_if { |c| c.match( /'/ ) }
355c6249bb2SBram Moolenaar      end
356c6249bb2SBram Moolenaar
357*d8fc5c0bSBram Moolenaar    when /^::([A-Z][^:\.\(]*)$/ # Absolute Constant or class methods
358c6249bb2SBram Moolenaar      receiver = $1
359c6249bb2SBram Moolenaar      candidates = Object.constants
360c6249bb2SBram Moolenaar      candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
361c6249bb2SBram Moolenaar
362*d8fc5c0bSBram Moolenaar    when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/ # Constant or class methods
363c6249bb2SBram Moolenaar      receiver = $1
364c6249bb2SBram Moolenaar      message = Regexp.quote($4)
365c6249bb2SBram Moolenaar      begin
366c6249bb2SBram Moolenaar        candidates = eval("#{receiver}.constants | #{receiver}.methods")
367c6249bb2SBram Moolenaar      rescue Exception
368c6249bb2SBram Moolenaar        candidates = []
369c6249bb2SBram Moolenaar      end
370c6249bb2SBram Moolenaar      candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
371c6249bb2SBram Moolenaar
372*d8fc5c0bSBram Moolenaar    when /^(:[^:.]+)\.([^.]*)$/ # Symbol
373c6249bb2SBram Moolenaar      receiver = $1
374c6249bb2SBram Moolenaar      message = Regexp.quote($2)
375c6249bb2SBram Moolenaar      candidates = Symbol.instance_methods(true)
376c6249bb2SBram Moolenaar
377*d8fc5c0bSBram Moolenaar    when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/ # Numeric
378c6249bb2SBram Moolenaar      receiver = $1
379c6249bb2SBram Moolenaar      message = Regexp.quote($4)
380c6249bb2SBram Moolenaar      begin
381c6249bb2SBram Moolenaar        candidates = eval(receiver).methods
382c6249bb2SBram Moolenaar      rescue Exception
383c6249bb2SBram Moolenaar        candidates
384c6249bb2SBram Moolenaar      end
385c6249bb2SBram Moolenaar
386*d8fc5c0bSBram Moolenaar    when /^(\$[^.]*)$/ #global
387c6249bb2SBram Moolenaar      candidates = global_variables.grep(Regexp.new(Regexp.quote($1)))
388c6249bb2SBram Moolenaar
389*d8fc5c0bSBram Moolenaar    when /^((\.?[^.]+)+)\.([^.]*)$/ # variable
390c6249bb2SBram Moolenaar      receiver = $1
391c6249bb2SBram Moolenaar      message = Regexp.quote($3)
392fc1421ebSBram Moolenaar      load_buffer_class( receiver )
393c6249bb2SBram Moolenaar
394c6249bb2SBram Moolenaar      cv = eval("self.class.constants")
395*d8fc5c0bSBram Moolenaar      vartype = get_var_type( receiver )
396c6249bb2SBram Moolenaar      if vartype != ''
397fc1421ebSBram Moolenaar        load_buffer_class( vartype )
398fc1421ebSBram Moolenaar
399fc1421ebSBram Moolenaar        begin
400c6249bb2SBram Moolenaar          candidates = eval("#{vartype}.instance_methods")
401fc1421ebSBram Moolenaar        rescue Exception
402fc1421ebSBram Moolenaar          candidates = []
403fc1421ebSBram Moolenaar        end
404c6249bb2SBram Moolenaar      elsif (cv).include?(receiver)
405c6249bb2SBram Moolenaar        # foo.func and foo is local var.
406c6249bb2SBram Moolenaar        candidates = eval("#{receiver}.methods")
407c6249bb2SBram Moolenaar      elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
408c6249bb2SBram Moolenaar        # Foo::Bar.func
409c6249bb2SBram Moolenaar        begin
410c6249bb2SBram Moolenaar          candidates = eval("#{receiver}.methods")
411c6249bb2SBram Moolenaar        rescue Exception
412c6249bb2SBram Moolenaar          candidates = []
413c6249bb2SBram Moolenaar        end
414c6249bb2SBram Moolenaar      else
415c6249bb2SBram Moolenaar        # func1.func2
416c6249bb2SBram Moolenaar        candidates = []
417c6249bb2SBram Moolenaar        ObjectSpace.each_object(Module){|m|
418c6249bb2SBram Moolenaar          next if m.name != "IRB::Context" and
419c6249bb2SBram Moolenaar            /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name
420c6249bb2SBram Moolenaar          candidates.concat m.instance_methods(false)
421c6249bb2SBram Moolenaar        }
422c6249bb2SBram Moolenaar      end
423c6249bb2SBram Moolenaar
424*d8fc5c0bSBram Moolenaar    when /^\(?\s*[A-Za-z0-9:^@.%\/+*\(\)]+\.\.\.?[A-Za-z0-9:^@.%\/+*\(\)]+\s*\)?\.([^.]*)/
425*d8fc5c0bSBram Moolenaar      message = $1
426*d8fc5c0bSBram Moolenaar      candidates = Range.instance_methods(true)
427c6249bb2SBram Moolenaar
428*d8fc5c0bSBram Moolenaar    when /^\[(\s*[A-Za-z0-9:^@.%\/+*\(\)\[\]\{\}.\'\"],?)*\].([^.]*)/
429*d8fc5c0bSBram Moolenaar      message = $2
430*d8fc5c0bSBram Moolenaar      candidates = Array.instance_methods(true)
431c6249bb2SBram Moolenaar
432*d8fc5c0bSBram Moolenaar    when /^\.([^.]*)$/ # unknown(maybe String)
433c6249bb2SBram Moolenaar      message = Regexp.quote($1)
434c6249bb2SBram Moolenaar      candidates = String.instance_methods(true)
435c6249bb2SBram Moolenaar
436c6249bb2SBram Moolenaar  else
437fc1421ebSBram Moolenaar    inclass = eval( VIM::evaluate("IsInClassDef()") )
438c6249bb2SBram Moolenaar
439fc1421ebSBram Moolenaar    if inclass != nil
440fc1421ebSBram Moolenaar      classdef = "%s\n" % VIM::Buffer.current[ inclass.min ]
441fc1421ebSBram Moolenaar      found = /^\s*class\s*([A-Za-z0-9_-]*)(\s*<\s*([A-Za-z0-9_:-]*))?\s*\n$/.match( classdef )
442fc1421ebSBram Moolenaar
443fc1421ebSBram Moolenaar      if found != nil
444fc1421ebSBram Moolenaar        receiver = $1
445fc1421ebSBram Moolenaar        message = input
446fc1421ebSBram Moolenaar        load_buffer_class( receiver )
447eb3593b3SBram Moolenaar        begin
448fc1421ebSBram Moolenaar          candidates = eval( "#{receiver}.instance_methods" )
449fc1421ebSBram Moolenaar          candidates += get_rails_helpers
450eb3593b3SBram Moolenaar        rescue Exception
451eb3593b3SBram Moolenaar          found = nil
452eb3593b3SBram Moolenaar        end
453fc1421ebSBram Moolenaar      end
454fc1421ebSBram Moolenaar    end
455fc1421ebSBram Moolenaar
456fc1421ebSBram Moolenaar    if inclass == nil || found == nil
457fc1421ebSBram Moolenaar      candidates = eval("self.class.constants")
458eb3593b3SBram Moolenaar      candidates += get_buffer_classes
459*d8fc5c0bSBram Moolenaar      message = receiver = input
460*d8fc5c0bSBram Moolenaar    end
461*d8fc5c0bSBram Moolenaar  end
462*d8fc5c0bSBram Moolenaar
463*d8fc5c0bSBram Moolenaar  candidates.delete_if { |x| x == nil }
464eb3593b3SBram Moolenaar  candidates.uniq!
465eb3593b3SBram Moolenaar  candidates.sort!
466*d8fc5c0bSBram Moolenaar  candidates = candidates.grep(/^#{Regexp.quote(message)}/) if message != nil
467c6249bb2SBram Moolenaar
468c6249bb2SBram Moolenaar  outp = ""
469fc1421ebSBram Moolenaar  valid = (candidates-Object.instance_methods)
470fc1421ebSBram Moolenaar
471fc1421ebSBram Moolenaar  rg = 0..valid.length
472fc1421ebSBram Moolenaar  rg.step(150) do |x|
473fc1421ebSBram Moolenaar    stpos = 0+x
474fc1421ebSBram Moolenaar    enpos = 150+x
475fc1421ebSBram Moolenaar    valid[stpos..enpos].each { |c| outp += "{'word':'%s','item':'%s'}," % [ c, c ] }
476c6249bb2SBram Moolenaar    outp.sub!(/,$/, '')
477fc1421ebSBram Moolenaar
478fc1421ebSBram Moolenaar    VIM::command("call extend(g:rubycomplete_completions, [%s])" % outp)
479fc1421ebSBram Moolenaar    outp = ""
480fc1421ebSBram Moolenaar  end
481c6249bb2SBram Moolenaarend
482c6249bb2SBram Moolenaar
483eb3593b3SBram Moolenaar# }}} ruby completion
484c6249bb2SBram MoolenaarRUBYEOF
485c6249bb2SBram Moolenaarendfunction
486c6249bb2SBram Moolenaar
487eb3593b3SBram Moolenaarlet g:rubycomplete_rails_loaded = 0
488fc1421ebSBram Moolenaar
489c6249bb2SBram Moolenaarcall s:DefRuby()
490*d8fc5c0bSBram Moolenaar" vim:tw=78:sw=4:ts=8:et:ft=vim:norl:
491