1c6249bb2SBram Moolenaar" Vim completion script
2c6249bb2SBram Moolenaar" Language:             Ruby
3fc1421ebSBram Moolenaar" Maintainer:           Mark Guzman <[email protected]>
4ec7944aaSBram Moolenaar" URL:                  https://github.com/vim-ruby/vim-ruby
5c6249bb2SBram Moolenaar" Release Coordinator:  Doug Kearns <[email protected]>
61d68952aSBram Moolenaar" Maintainer Version:   0.8.1
7c6249bb2SBram Moolenaar" ----------------------------------------------------------------------------
8c6249bb2SBram Moolenaar"
9c6249bb2SBram Moolenaar" Ruby IRB/Complete author: Keiju ISHITSUKA([email protected])
10c6249bb2SBram Moolenaar" ----------------------------------------------------------------------------
11c6249bb2SBram Moolenaar
12eb3593b3SBram Moolenaar" {{{ requirement checks
13ec7944aaSBram Moolenaar
14ec7944aaSBram Moolenaarfunction! s:ErrMsg(msg)
15ec7944aaSBram Moolenaar    echohl ErrorMsg
16ec7944aaSBram Moolenaar    echo a:msg
17ec7944aaSBram Moolenaar    echohl None
18ec7944aaSBram Moolenaarendfunction
19ec7944aaSBram Moolenaar
20c6249bb2SBram Moolenaarif !has('ruby')
21ec7944aaSBram Moolenaar    call s:ErrMsg( "Error: Rubycomplete requires vim compiled with +ruby" )
22ec7944aaSBram Moolenaar    call s:ErrMsg( "Error: falling back to syntax completion" )
239964e468SBram Moolenaar    " lets fall back to syntax completion
249964e468SBram Moolenaar    setlocal omnifunc=syntaxcomplete#Complete
25c6249bb2SBram Moolenaar    finish
26c6249bb2SBram Moolenaarendif
27c6249bb2SBram Moolenaar
28c6249bb2SBram Moolenaarif version < 700
29ec7944aaSBram Moolenaar    call s:ErrMsg( "Error: Required vim >= 7.0" )
30c6249bb2SBram Moolenaar    finish
31c6249bb2SBram Moolenaarendif
32eb3593b3SBram Moolenaar" }}} requirement checks
33c6249bb2SBram Moolenaar
349964e468SBram Moolenaar" {{{ configuration failsafe initialization
35eb3593b3SBram Moolenaarif !exists("g:rubycomplete_rails")
36eb3593b3SBram Moolenaar    let g:rubycomplete_rails = 0
37eb3593b3SBram Moolenaarendif
38fc1421ebSBram Moolenaar
39eb3593b3SBram Moolenaarif !exists("g:rubycomplete_classes_in_global")
40eb3593b3SBram Moolenaar    let g:rubycomplete_classes_in_global = 0
41eb3593b3SBram Moolenaarendif
42eb3593b3SBram Moolenaar
439964e468SBram Moolenaarif !exists("g:rubycomplete_buffer_loading")
44a7241f5fSBram Moolenaar    let g:rubycomplete_buffer_loading = 0
459964e468SBram Moolenaarendif
469964e468SBram Moolenaar
479964e468SBram Moolenaarif !exists("g:rubycomplete_include_object")
489964e468SBram Moolenaar    let g:rubycomplete_include_object = 0
499964e468SBram Moolenaarendif
509964e468SBram Moolenaar
519964e468SBram Moolenaarif !exists("g:rubycomplete_include_objectspace")
529964e468SBram Moolenaar    let g:rubycomplete_include_objectspace = 0
539964e468SBram Moolenaarendif
549964e468SBram Moolenaar" }}} configuration failsafe initialization
559964e468SBram Moolenaar
56eb3593b3SBram Moolenaar" {{{ vim-side support functions
579964e468SBram Moolenaarlet s:rubycomplete_debug = 0
589964e468SBram Moolenaar
599964e468SBram Moolenaarfunction! s:dprint(msg)
609964e468SBram Moolenaar    if s:rubycomplete_debug == 1
619964e468SBram Moolenaar        echom a:msg
629964e468SBram Moolenaar    endif
639964e468SBram Moolenaarendfunction
649964e468SBram Moolenaar
659964e468SBram Moolenaarfunction! s:GetBufferRubyModule(name, ...)
669964e468SBram Moolenaar    if a:0 == 1
679964e468SBram Moolenaar        let [snum,enum] = s:GetBufferRubyEntity(a:name, "module", a:1)
689964e468SBram Moolenaar    else
699964e468SBram Moolenaar        let [snum,enum] = s:GetBufferRubyEntity(a:name, "module")
709964e468SBram Moolenaar    endif
71fc1421ebSBram Moolenaar    return snum . '..' . enum
72fc1421ebSBram Moolenaarendfunction
73fc1421ebSBram Moolenaar
749964e468SBram Moolenaarfunction! s:GetBufferRubyClass(name, ...)
759964e468SBram Moolenaar    if a:0 >= 1
769964e468SBram Moolenaar        let [snum,enum] = s:GetBufferRubyEntity(a:name, "class", a:1)
779964e468SBram Moolenaar    else
789964e468SBram Moolenaar        let [snum,enum] = s:GetBufferRubyEntity(a:name, "class")
799964e468SBram Moolenaar    endif
80fc1421ebSBram Moolenaar    return snum . '..' . enum
81fc1421ebSBram Moolenaarendfunction
82fc1421ebSBram Moolenaar
839964e468SBram Moolenaarfunction! s:GetBufferRubySingletonMethods(name)
84fc1421ebSBram Moolenaarendfunction
85fc1421ebSBram Moolenaar
869964e468SBram Moolenaarfunction! s:GetBufferRubyEntity( name, type, ... )
879964e468SBram Moolenaar    let lastpos = getpos(".")
889964e468SBram Moolenaar    let lastline = lastpos
899964e468SBram Moolenaar    if (a:0 >= 1)
909964e468SBram Moolenaar        let lastline = [ 0, a:1, 0, 0 ]
919964e468SBram Moolenaar        call cursor( a:1, 0 )
929964e468SBram Moolenaar    endif
939964e468SBram Moolenaar
94fc1421ebSBram Moolenaar    let stopline = 1
959964e468SBram Moolenaar
9689bcfda6SBram Moolenaar    let crex = '^\s*\<' . a:type . '\>\s*\<' . escape(a:name, '*') . '\>\s*\(<\s*.*\s*\)\?'
979964e468SBram Moolenaar    let [lnum,lcol] = searchpos( crex, 'w' )
989964e468SBram Moolenaar    "let [lnum,lcol] = searchpairpos( crex . '\zs', '', '\(end\|}\)', 'w' )
999964e468SBram Moolenaar
100fc1421ebSBram Moolenaar    if lnum == 0 && lcol == 0
1019964e468SBram Moolenaar        call cursor(lastpos[1], lastpos[2])
102fc1421ebSBram Moolenaar        return [0,0]
103fc1421ebSBram Moolenaar    endif
104fc1421ebSBram Moolenaar
1059964e468SBram Moolenaar    let curpos = getpos(".")
1069964e468SBram Moolenaar    let [enum,ecol] = searchpairpos( crex, '', '\(end\|}\)', 'wr' )
1079964e468SBram Moolenaar    call cursor(lastpos[1], lastpos[2])
1089964e468SBram Moolenaar
109fc1421ebSBram Moolenaar    if lnum > enum
1109964e468SBram Moolenaar        return [0,0]
111fc1421ebSBram Moolenaar    endif
112fc1421ebSBram Moolenaar    " we found a the class def
113fc1421ebSBram Moolenaar    return [lnum,enum]
114fc1421ebSBram Moolenaarendfunction
115fc1421ebSBram Moolenaar
1169964e468SBram Moolenaarfunction! s:IsInClassDef()
1179964e468SBram Moolenaar    return s:IsPosInClassDef( line('.') )
1189964e468SBram Moolenaarendfunction
119fc1421ebSBram Moolenaar
1209964e468SBram Moolenaarfunction! s:IsPosInClassDef(pos)
1219964e468SBram Moolenaar    let [snum,enum] = s:GetBufferRubyEntity( '.*', "class" )
1229964e468SBram Moolenaar    let ret = 'nil'
1239964e468SBram Moolenaar
1249964e468SBram Moolenaar    if snum < a:pos && a:pos < enum
125fc1421ebSBram Moolenaar        let ret = snum . '..' . enum
126fc1421ebSBram Moolenaar    endif
127fc1421ebSBram Moolenaar
128fc1421ebSBram Moolenaar    return ret
129fc1421ebSBram Moolenaarendfunction
130fc1421ebSBram Moolenaar
1319964e468SBram Moolenaarfunction! s:GetRubyVarType(v)
132c6249bb2SBram Moolenaar    let stopline = 1
133c6249bb2SBram Moolenaar    let vtp = ''
134c6249bb2SBram Moolenaar    let pos = getpos('.')
135ec7944aaSBram Moolenaar    let sstr = '^\s*#\s*@var\s*'.escape(a:v, '*').'\>\s\+[^ \t]\+\s*$'
1369964e468SBram Moolenaar    let [lnum,lcol] = searchpos(sstr,'nb',stopline)
137c6249bb2SBram Moolenaar    if lnum != 0 && lcol != 0
138c6249bb2SBram Moolenaar        call setpos('.',pos)
139c6249bb2SBram Moolenaar        let str = getline(lnum)
1409964e468SBram Moolenaar        let vtp = substitute(str,sstr,'\1','')
141c6249bb2SBram Moolenaar        return vtp
142c6249bb2SBram Moolenaar    endif
143c6249bb2SBram Moolenaar    call setpos('.',pos)
1449964e468SBram Moolenaar    let ctors = '\(now\|new\|open\|get_instance'
1459964e468SBram Moolenaar    if exists('g:rubycomplete_rails') && g:rubycomplete_rails == 1 && s:rubycomplete_rails_loaded == 1
1469964e468SBram Moolenaar        let ctors = ctors.'\|find\|create'
147551dbcc9SBram Moolenaar    else
148551dbcc9SBram Moolenaar    endif
1499964e468SBram Moolenaar    let ctors = ctors.'\)'
150551dbcc9SBram Moolenaar
1519964e468SBram Moolenaar    let fstr = '=\s*\([^ \t]\+.' . ctors .'\>\|[\[{"''/]\|%[xwQqr][(\[{@]\|[A-Za-z0-9@:\-()\.]\+...\?\|lambda\|&\)'
15289bcfda6SBram Moolenaar    let sstr = ''.escape(a:v, '*').'\>\s*[+\-*/]*'.fstr
1539964e468SBram Moolenaar    let [lnum,lcol] = searchpos(sstr,'nb',stopline)
154c6249bb2SBram Moolenaar    if lnum != 0 && lcol != 0
1559964e468SBram Moolenaar        let str = matchstr(getline(lnum),fstr,lcol)
156c6249bb2SBram Moolenaar        let str = substitute(str,'^=\s*','','')
1579964e468SBram Moolenaar
158c6249bb2SBram Moolenaar        call setpos('.',pos)
1599964e468SBram Moolenaar        if str == '"' || str == '''' || stridx(tolower(str), '%q[') != -1
160c6249bb2SBram Moolenaar            return 'String'
1619964e468SBram Moolenaar        elseif str == '[' || stridx(str, '%w[') != -1
162c6249bb2SBram Moolenaar            return 'Array'
163c6249bb2SBram Moolenaar        elseif str == '{'
164c6249bb2SBram Moolenaar            return 'Hash'
165fc1421ebSBram Moolenaar        elseif str == '/' || str == '%r{'
166fc1421ebSBram Moolenaar            return 'Regexp'
167d8fc5c0bSBram Moolenaar        elseif strlen(str) >= 4 && stridx(str,'..') != -1
168d8fc5c0bSBram Moolenaar            return 'Range'
1699964e468SBram Moolenaar        elseif stridx(str, 'lambda') != -1 || str == '&'
1709964e468SBram Moolenaar            return 'Proc'
171c6249bb2SBram Moolenaar        elseif strlen(str) > 4
172c6249bb2SBram Moolenaar            let l = stridx(str,'.')
173c6249bb2SBram Moolenaar            return str[0:l-1]
174c6249bb2SBram Moolenaar        end
175c6249bb2SBram Moolenaar        return ''
176c6249bb2SBram Moolenaar    endif
177c6249bb2SBram Moolenaar    call setpos('.',pos)
178c6249bb2SBram Moolenaar    return ''
179fc1421ebSBram Moolenaarendfunction
180c6249bb2SBram Moolenaar
181eb3593b3SBram Moolenaar"}}} vim-side support functions
182eb3593b3SBram Moolenaar
1839964e468SBram Moolenaar"{{{ vim-side completion function
1849964e468SBram Moolenaarfunction! rubycomplete#Init()
1859964e468SBram Moolenaar    execute "ruby VimRubyCompletion.preload_rails"
1869964e468SBram Moolenaarendfunction
1879964e468SBram Moolenaar
188c6249bb2SBram Moolenaarfunction! rubycomplete#Complete(findstart, base)
189c6249bb2SBram Moolenaar     "findstart = 1 when we need to get the text length
190c6249bb2SBram Moolenaar    if a:findstart
191c6249bb2SBram Moolenaar        let line = getline('.')
192c6249bb2SBram Moolenaar        let idx = col('.')
193c6249bb2SBram Moolenaar        while idx > 0
194c6249bb2SBram Moolenaar            let idx -= 1
195c6249bb2SBram Moolenaar            let c = line[idx-1]
196c6249bb2SBram Moolenaar            if c =~ '\w'
197c6249bb2SBram Moolenaar                continue
198c6249bb2SBram Moolenaar            elseif ! c =~ '\.'
199*4575876dSBram Moolenaar                let idx = -1
200c6249bb2SBram Moolenaar                break
201c6249bb2SBram Moolenaar            else
202c6249bb2SBram Moolenaar                break
203c6249bb2SBram Moolenaar            endif
204c6249bb2SBram Moolenaar        endwhile
205c6249bb2SBram Moolenaar
206c6249bb2SBram Moolenaar        return idx
207c6249bb2SBram Moolenaar    "findstart = 0 when we need to return the list of completions
208c6249bb2SBram Moolenaar    else
209fc1421ebSBram Moolenaar        let g:rubycomplete_completions = []
2109964e468SBram Moolenaar        execute "ruby VimRubyCompletion.get_completions('" . a:base . "')"
211fc1421ebSBram Moolenaar        return g:rubycomplete_completions
212c6249bb2SBram Moolenaar    endif
213c6249bb2SBram Moolenaarendfunction
2149964e468SBram Moolenaar"}}} vim-side completion function
215c6249bb2SBram Moolenaar
2169964e468SBram Moolenaar"{{{ ruby-side code
217c6249bb2SBram Moolenaarfunction! s:DefRuby()
218c6249bb2SBram Moolenaarruby << RUBYEOF
219eb3593b3SBram Moolenaar# {{{ ruby completion
220fc1421ebSBram Moolenaar
2219964e468SBram Moolenaarbegin
2229964e468SBram Moolenaar    require 'rubygems' # let's assume this is safe...?
2239964e468SBram Moolenaarrescue Exception
2249964e468SBram Moolenaar    #ignore?
2259964e468SBram Moolenaarend
2269964e468SBram Moolenaarclass VimRubyCompletion
2279964e468SBram Moolenaar# {{{ constants
2289964e468SBram Moolenaar  @@debug = false
2299964e468SBram Moolenaar  @@ReservedWords = [
230c6249bb2SBram Moolenaar        "BEGIN", "END",
231c6249bb2SBram Moolenaar        "alias", "and",
232c6249bb2SBram Moolenaar        "begin", "break",
233c6249bb2SBram Moolenaar        "case", "class",
234c6249bb2SBram Moolenaar        "def", "defined", "do",
235c6249bb2SBram Moolenaar        "else", "elsif", "end", "ensure",
236c6249bb2SBram Moolenaar        "false", "for",
237c6249bb2SBram Moolenaar        "if", "in",
238c6249bb2SBram Moolenaar        "module",
239c6249bb2SBram Moolenaar        "next", "nil", "not",
240c6249bb2SBram Moolenaar        "or",
241c6249bb2SBram Moolenaar        "redo", "rescue", "retry", "return",
242c6249bb2SBram Moolenaar        "self", "super",
243c6249bb2SBram Moolenaar        "then", "true",
244c6249bb2SBram Moolenaar        "undef", "unless", "until",
245c6249bb2SBram Moolenaar        "when", "while",
246c6249bb2SBram Moolenaar        "yield",
247c6249bb2SBram Moolenaar      ]
248c6249bb2SBram Moolenaar
2499964e468SBram Moolenaar  @@Operators = [ "%", "&", "*", "**", "+",  "-",  "/",
250c6249bb2SBram Moolenaar        "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
251c6249bb2SBram Moolenaar        "[]", "[]=", "^", ]
2529964e468SBram Moolenaar# }}} constants
253c6249bb2SBram Moolenaar
2549964e468SBram Moolenaar# {{{ buffer analysis magic
255c6249bb2SBram Moolenaar  def load_requires
256eb3593b3SBram Moolenaar    buf = VIM::Buffer.current
257eb3593b3SBram Moolenaar    enum = buf.line_number
258c6249bb2SBram Moolenaar    nums = Range.new( 1, enum )
259c6249bb2SBram Moolenaar    nums.each do |x|
260eb3593b3SBram Moolenaar      ln = buf[x]
261c6249bb2SBram Moolenaar      begin
262c6249bb2SBram Moolenaar        eval( "require %s" % $1 ) if /.*require\s*(.*)$/.match( ln )
263c6249bb2SBram Moolenaar      rescue Exception
264c6249bb2SBram Moolenaar        #ignore?
265c6249bb2SBram Moolenaar      end
266c6249bb2SBram Moolenaar    end
267c6249bb2SBram Moolenaar  end
268c6249bb2SBram Moolenaar
26989bcfda6SBram Moolenaar  def load_gems
27089bcfda6SBram Moolenaar    fpath = VIM::evaluate("get(g:, 'rubycomplete_gemfile_path', 'Gemfile')")
27189bcfda6SBram Moolenaar    return unless File.file?(fpath) && File.readable?(fpath)
27289bcfda6SBram Moolenaar    want_bundler = VIM::evaluate("get(g:, 'rubycomplete_use_bundler')")
27389bcfda6SBram Moolenaar    parse_file = !want_bundler
27489bcfda6SBram Moolenaar    begin
27589bcfda6SBram Moolenaar      require 'bundler'
27689bcfda6SBram Moolenaar      Bundler.setup
27789bcfda6SBram Moolenaar      Bundler.require
27889bcfda6SBram Moolenaar    rescue Exception
27989bcfda6SBram Moolenaar      parse_file = true
28089bcfda6SBram Moolenaar    end
28189bcfda6SBram Moolenaar    if parse_file
28289bcfda6SBram Moolenaar      File.new(fpath).each_line do |line|
28389bcfda6SBram Moolenaar        begin
28489bcfda6SBram Moolenaar          require $1 if /\s*gem\s*['"]([^'"]+)/.match(line)
28589bcfda6SBram Moolenaar        rescue Exception
28689bcfda6SBram Moolenaar        end
28789bcfda6SBram Moolenaar      end
28889bcfda6SBram Moolenaar    end
28989bcfda6SBram Moolenaar  end
29089bcfda6SBram Moolenaar
291fc1421ebSBram Moolenaar  def load_buffer_class(name)
2929964e468SBram Moolenaar    dprint "load_buffer_class(%s) START" % name
2939964e468SBram Moolenaar    classdef = get_buffer_entity(name, 's:GetBufferRubyClass("%s")')
294fc1421ebSBram Moolenaar    return if classdef == nil
295fc1421ebSBram Moolenaar
296fc1421ebSBram Moolenaar    pare = /^\s*class\s*(.*)\s*<\s*(.*)\s*\n/.match( classdef )
2979964e468SBram Moolenaar    load_buffer_class( $2 ) if pare != nil  && $2 != name # load parent class if needed
298fc1421ebSBram Moolenaar
299ec7944aaSBram Moolenaar    mixre = /.*\n\s*(include|prepend)\s*(.*)\s*\n/.match( classdef )
3009964e468SBram Moolenaar    load_buffer_module( $2 ) if mixre != nil && $2 != name # load mixins if needed
301fc1421ebSBram Moolenaar
3029964e468SBram Moolenaar    begin
303fc1421ebSBram Moolenaar      eval classdef
3049964e468SBram Moolenaar    rescue Exception
3059964e468SBram Moolenaar      VIM::evaluate( "s:ErrMsg( 'Problem loading class \"%s\", was it already completed?' )" % name )
3069964e468SBram Moolenaar    end
3079964e468SBram Moolenaar    dprint "load_buffer_class(%s) END" % name
308fc1421ebSBram Moolenaar  end
309fc1421ebSBram Moolenaar
310fc1421ebSBram Moolenaar  def load_buffer_module(name)
3119964e468SBram Moolenaar    dprint "load_buffer_module(%s) START" % name
3129964e468SBram Moolenaar    classdef = get_buffer_entity(name, 's:GetBufferRubyModule("%s")')
313fc1421ebSBram Moolenaar    return if classdef == nil
314fc1421ebSBram Moolenaar
3159964e468SBram Moolenaar    begin
316fc1421ebSBram Moolenaar      eval classdef
3179964e468SBram Moolenaar    rescue Exception
3189964e468SBram Moolenaar      VIM::evaluate( "s:ErrMsg( 'Problem loading module \"%s\", was it already completed?' )" % name )
3199964e468SBram Moolenaar    end
3209964e468SBram Moolenaar    dprint "load_buffer_module(%s) END" % name
321fc1421ebSBram Moolenaar  end
322fc1421ebSBram Moolenaar
323fc1421ebSBram Moolenaar  def get_buffer_entity(name, vimfun)
3249964e468SBram Moolenaar    loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading")
325c236c16dSBram Moolenaar    return nil if loading_allowed.to_i.zero?
326d8fc5c0bSBram Moolenaar    return nil if /(\"|\')+/.match( name )
327eb3593b3SBram Moolenaar    buf = VIM::Buffer.current
328fc1421ebSBram Moolenaar    nums = eval( VIM::evaluate( vimfun % name ) )
329fc1421ebSBram Moolenaar    return nil if nums == nil
330fc1421ebSBram Moolenaar    return nil if nums.min == nums.max && nums.min == 0
331fc1421ebSBram Moolenaar
3329964e468SBram Moolenaar    dprint "get_buffer_entity START"
3339964e468SBram Moolenaar    visited = []
3349964e468SBram Moolenaar    clscnt = 0
3359964e468SBram Moolenaar    bufname = VIM::Buffer.current.name
336fc1421ebSBram Moolenaar    classdef = ""
3379964e468SBram Moolenaar    cur_line = VIM::Buffer.current.line_number
3389964e468SBram Moolenaar    while (nums != nil && !(nums.min == 0 && nums.max == 0) )
3399964e468SBram Moolenaar      dprint "visited: %s" % visited.to_s
3409964e468SBram Moolenaar      break if visited.index( nums )
3419964e468SBram Moolenaar      visited << nums
3429964e468SBram Moolenaar
343fc1421ebSBram Moolenaar      nums.each do |x|
344fc1421ebSBram Moolenaar        if x != cur_line
3459964e468SBram Moolenaar          next if x == 0
346eb3593b3SBram Moolenaar          ln = buf[x]
3479964e468SBram Moolenaar          if /^\s*(module|class|def|include)\s+/.match(ln)
3489964e468SBram Moolenaar            clscnt += 1 if $1 == "class"
3491d68952aSBram Moolenaar            #dprint "\$1$1
350fc1421ebSBram Moolenaar            classdef += "%s\n" % ln
3519964e468SBram Moolenaar            classdef += "end\n" if /def\s+/.match(ln)
3529964e468SBram Moolenaar            dprint ln
3539964e468SBram Moolenaar          end
354fc1421ebSBram Moolenaar        end
355fc1421ebSBram Moolenaar      end
356fc1421ebSBram Moolenaar
3579964e468SBram Moolenaar      nm = "%s(::.*)*\", %s, \"" % [ name, nums.last ]
3589964e468SBram Moolenaar      nums = eval( VIM::evaluate( vimfun % nm ) )
3599964e468SBram Moolenaar      dprint "nm: \"%s\"" % nm
3609964e468SBram Moolenaar      dprint "vimfun: %s" % (vimfun % nm)
3619964e468SBram Moolenaar      dprint "got nums: %s" % nums.to_s
3629964e468SBram Moolenaar    end
3639964e468SBram Moolenaar    if classdef.length > 1
3649964e468SBram Moolenaar        classdef += "end\n"*clscnt
3659964e468SBram Moolenaar        # classdef = "class %s\n%s\nend\n" % [ bufname.gsub( /\/|\\/, "_" ), classdef ]
3669964e468SBram Moolenaar    end
3679964e468SBram Moolenaar
3689964e468SBram Moolenaar    dprint "get_buffer_entity END"
3699964e468SBram Moolenaar    dprint "classdef====start"
3709964e468SBram Moolenaar    lns = classdef.split( "\n" )
3719964e468SBram Moolenaar    lns.each { |x| dprint x }
3729964e468SBram Moolenaar    dprint "classdef====end"
373fc1421ebSBram Moolenaar    return classdef
374fc1421ebSBram Moolenaar  end
375fc1421ebSBram Moolenaar
376d8fc5c0bSBram Moolenaar  def get_var_type( receiver )
377d8fc5c0bSBram Moolenaar    if /(\"|\')+/.match( receiver )
378d8fc5c0bSBram Moolenaar      "String"
379d8fc5c0bSBram Moolenaar    else
3809964e468SBram Moolenaar      VIM::evaluate("s:GetRubyVarType('%s')" % receiver)
381d8fc5c0bSBram Moolenaar    end
382d8fc5c0bSBram Moolenaar  end
383d8fc5c0bSBram Moolenaar
3849964e468SBram Moolenaar  def dprint( txt )
3859964e468SBram Moolenaar    print txt if @@debug
3869964e468SBram Moolenaar  end
3879964e468SBram Moolenaar
388ec7944aaSBram Moolenaar  def escape_vim_singlequote_string(str)
389ec7944aaSBram Moolenaar    str.to_s.gsub(/'/,"\\'")
390ec7944aaSBram Moolenaar  end
391ec7944aaSBram Moolenaar
3929964e468SBram Moolenaar  def get_buffer_entity_list( type )
393eb3593b3SBram Moolenaar    # this will be a little expensive.
3949964e468SBram Moolenaar    loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading")
3959964e468SBram Moolenaar    allow_aggressive_load = VIM::evaluate("exists('g:rubycomplete_classes_in_global') && g:rubycomplete_classes_in_global")
396c236c16dSBram Moolenaar    return [] if allow_aggressive_load.to_i.zero? || loading_allowed.to_i.zero?
397eb3593b3SBram Moolenaar
398eb3593b3SBram Moolenaar    buf = VIM::Buffer.current
399eb3593b3SBram Moolenaar    eob = buf.length
400eb3593b3SBram Moolenaar    ret = []
401eb3593b3SBram Moolenaar    rg = 1..eob
4029964e468SBram Moolenaar    re = eval( "/^\s*%s\s*([A-Za-z0-9_:-]*)(\s*<\s*([A-Za-z0-9_:-]*))?\s*/" % type )
403eb3593b3SBram Moolenaar
404eb3593b3SBram Moolenaar    rg.each do |x|
4059964e468SBram Moolenaar      if re.match( buf[x] )
4069964e468SBram Moolenaar        next if type == "def" && eval( VIM::evaluate("s:IsPosInClassDef(%s)" % x) ) != nil
407eb3593b3SBram Moolenaar        ret.push $1
408eb3593b3SBram Moolenaar      end
409eb3593b3SBram Moolenaar    end
410eb3593b3SBram Moolenaar
411eb3593b3SBram Moolenaar    return ret
412eb3593b3SBram Moolenaar  end
413eb3593b3SBram Moolenaar
4149964e468SBram Moolenaar  def get_buffer_modules
4159964e468SBram Moolenaar    return get_buffer_entity_list( "modules" )
4169964e468SBram Moolenaar  end
4179964e468SBram Moolenaar
4189964e468SBram Moolenaar  def get_buffer_methods
4199964e468SBram Moolenaar    return get_buffer_entity_list( "def" )
4209964e468SBram Moolenaar  end
4219964e468SBram Moolenaar
4229964e468SBram Moolenaar  def get_buffer_classes
4239964e468SBram Moolenaar    return get_buffer_entity_list( "class" )
4249964e468SBram Moolenaar  end
4259964e468SBram Moolenaar
4269964e468SBram Moolenaar
4279964e468SBram Moolenaar  def load_rails
4289964e468SBram Moolenaar    allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails")
429c236c16dSBram Moolenaar    return if allow_rails.to_i.zero?
430fc1421ebSBram Moolenaar
431fc1421ebSBram Moolenaar    buf_path = VIM::evaluate('expand("%:p")')
432fc1421ebSBram Moolenaar    file_name = VIM::evaluate('expand("%:t")')
4339964e468SBram Moolenaar    vim_dir = VIM::evaluate('getcwd()')
4349964e468SBram Moolenaar    file_dir = buf_path.gsub( file_name, '' )
4359964e468SBram Moolenaar    file_dir.gsub!( /\\/, "/" )
4369964e468SBram Moolenaar    vim_dir.gsub!( /\\/, "/" )
4379964e468SBram Moolenaar    vim_dir << "/"
4389964e468SBram Moolenaar    dirs = [ vim_dir, file_dir ]
4399964e468SBram Moolenaar    sdirs = [ "", "./", "../", "../../", "../../../", "../../../../" ]
4409964e468SBram Moolenaar    rails_base = nil
441fc1421ebSBram Moolenaar
4429964e468SBram Moolenaar    dirs.each do |dir|
4439964e468SBram Moolenaar      sdirs.each do |sub|
4449964e468SBram Moolenaar        trail = "%s%s" % [ dir, sub ]
4459964e468SBram Moolenaar        tcfg = "%sconfig" % trail
4469964e468SBram Moolenaar
4479964e468SBram Moolenaar        if File.exists?( tcfg )
4489964e468SBram Moolenaar          rails_base = trail
449fc1421ebSBram Moolenaar          break
450fc1421ebSBram Moolenaar        end
451fc1421ebSBram Moolenaar      end
4529964e468SBram Moolenaar      break if rails_base
4539964e468SBram Moolenaar    end
454eb3593b3SBram Moolenaar
4559964e468SBram Moolenaar    return if rails_base == nil
4569964e468SBram Moolenaar    $:.push rails_base unless $:.index( rails_base )
457551dbcc9SBram Moolenaar
4589964e468SBram Moolenaar    rails_config = rails_base + "config/"
4599964e468SBram Moolenaar    rails_lib = rails_base + "lib/"
4609964e468SBram Moolenaar    $:.push rails_config unless $:.index( rails_config )
4619964e468SBram Moolenaar    $:.push rails_lib unless $:.index( rails_lib )
4629964e468SBram Moolenaar
4639964e468SBram Moolenaar    bootfile = rails_config + "boot.rb"
4649964e468SBram Moolenaar    envfile = rails_config + "environment.rb"
465551dbcc9SBram Moolenaar    if File.exists?( bootfile ) && File.exists?( envfile )
466551dbcc9SBram Moolenaar      begin
467eb3593b3SBram Moolenaar        require bootfile
468551dbcc9SBram Moolenaar        require envfile
4699964e468SBram Moolenaar        begin
470551dbcc9SBram Moolenaar          require 'console_app'
471551dbcc9SBram Moolenaar          require 'console_with_helpers'
4729964e468SBram Moolenaar        rescue Exception
4739964e468SBram Moolenaar          dprint "Rails 1.1+ Error %s" % $!
4749964e468SBram Moolenaar          # assume 1.0
4759964e468SBram Moolenaar        end
4769964e468SBram Moolenaar        #eval( "Rails::Initializer.run" ) #not necessary?
4779964e468SBram Moolenaar        VIM::command('let s:rubycomplete_rails_loaded = 1')
4789964e468SBram Moolenaar        dprint "rails loaded"
4799964e468SBram Moolenaar      rescue Exception
4809964e468SBram Moolenaar        dprint "Rails Error %s" % $!
4819964e468SBram Moolenaar        VIM::evaluate( "s:ErrMsg('Error loading rails environment')" )
482551dbcc9SBram Moolenaar      end
483eb3593b3SBram Moolenaar    end
484fc1421ebSBram Moolenaar  end
485fc1421ebSBram Moolenaar
486fc1421ebSBram Moolenaar  def get_rails_helpers
4879964e468SBram Moolenaar    allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails")
4889964e468SBram Moolenaar    rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded')
489c236c16dSBram Moolenaar    return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero?
4909964e468SBram Moolenaar
4919964e468SBram Moolenaar    buf_path = VIM::evaluate('expand("%:p")')
4929964e468SBram Moolenaar    buf_path.gsub!( /\\/, "/" )
4939964e468SBram Moolenaar    path_elm = buf_path.split( "/" )
4949964e468SBram Moolenaar    dprint "buf_path: %s" % buf_path
4959964e468SBram Moolenaar    types = [ "app", "db", "lib", "test", "components", "script" ]
4969964e468SBram Moolenaar
4979964e468SBram Moolenaar    i = nil
4989964e468SBram Moolenaar    ret = []
4999964e468SBram Moolenaar    type = nil
5009964e468SBram Moolenaar    types.each do |t|
5019964e468SBram Moolenaar      i = path_elm.index( t )
5029964e468SBram Moolenaar      break if i
5039964e468SBram Moolenaar    end
5049964e468SBram Moolenaar    type = path_elm[i]
5059964e468SBram Moolenaar    type.downcase!
5069964e468SBram Moolenaar
5079964e468SBram Moolenaar    dprint "type: %s" % type
5089964e468SBram Moolenaar    case type
5099964e468SBram Moolenaar      when "app"
5109964e468SBram Moolenaar        i += 1
5119964e468SBram Moolenaar        subtype = path_elm[i]
5129964e468SBram Moolenaar        subtype.downcase!
5139964e468SBram Moolenaar
5149964e468SBram Moolenaar        dprint "subtype: %s" % subtype
5159964e468SBram Moolenaar        case subtype
5169964e468SBram Moolenaar          when "views"
5179964e468SBram Moolenaar            ret += ActionView::Base.instance_methods
5189964e468SBram Moolenaar            ret += ActionView::Base.methods
5199964e468SBram Moolenaar          when "controllers"
5209964e468SBram Moolenaar            ret += ActionController::Base.instance_methods
5219964e468SBram Moolenaar            ret += ActionController::Base.methods
5229964e468SBram Moolenaar          when "models"
5239964e468SBram Moolenaar            ret += ActiveRecord::Base.instance_methods
5249964e468SBram Moolenaar            ret += ActiveRecord::Base.methods
5259964e468SBram Moolenaar        end
5269964e468SBram Moolenaar
5279964e468SBram Moolenaar      when "db"
5289964e468SBram Moolenaar        ret += ActiveRecord::ConnectionAdapters::SchemaStatements.instance_methods
5299964e468SBram Moolenaar        ret += ActiveRecord::ConnectionAdapters::SchemaStatements.methods
5309964e468SBram Moolenaar    end
5319964e468SBram Moolenaar
5329964e468SBram Moolenaar
5339964e468SBram Moolenaar    return ret
5349964e468SBram Moolenaar  end
5359964e468SBram Moolenaar
5369964e468SBram Moolenaar  def add_rails_columns( cls )
5379964e468SBram Moolenaar    allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails")
5389964e468SBram Moolenaar    rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded')
539c236c16dSBram Moolenaar    return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero?
5409964e468SBram Moolenaar
5419964e468SBram Moolenaar    begin
5429964e468SBram Moolenaar        eval( "#{cls}.establish_connection" )
5439964e468SBram Moolenaar        return [] unless eval( "#{cls}.ancestors.include?(ActiveRecord::Base).to_s" )
5449964e468SBram Moolenaar        col = eval( "#{cls}.column_names" )
5459964e468SBram Moolenaar        return col if col
5469964e468SBram Moolenaar    rescue
5479964e468SBram Moolenaar        dprint "add_rails_columns err: (cls: %s) %s" % [ cls, $! ]
5489964e468SBram Moolenaar        return []
5499964e468SBram Moolenaar    end
5509964e468SBram Moolenaar    return []
5519964e468SBram Moolenaar  end
5529964e468SBram Moolenaar
5539964e468SBram Moolenaar  def clean_sel(sel, msg)
554ec7944aaSBram Moolenaar    ret = sel.reject{|x|x.nil?}.uniq
555ec7944aaSBram Moolenaar    ret = ret.grep(/^#{Regexp.quote(msg)}/) if msg != nil
556ec7944aaSBram Moolenaar    ret
5579964e468SBram Moolenaar  end
5589964e468SBram Moolenaar
5599964e468SBram Moolenaar  def get_rails_view_methods
5609964e468SBram Moolenaar    allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails")
5619964e468SBram Moolenaar    rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded')
562c236c16dSBram Moolenaar    return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero?
5639964e468SBram Moolenaar
5649964e468SBram Moolenaar    buf_path = VIM::evaluate('expand("%:p")')
5659964e468SBram Moolenaar    buf_path.gsub!( /\\/, "/" )
5669964e468SBram Moolenaar    pelm = buf_path.split( "/" )
5679964e468SBram Moolenaar    idx = pelm.index( "views" )
5689964e468SBram Moolenaar
5699964e468SBram Moolenaar    return [] unless idx
5709964e468SBram Moolenaar    idx += 1
5719964e468SBram Moolenaar
5729964e468SBram Moolenaar    clspl = pelm[idx].camelize.pluralize
5739964e468SBram Moolenaar    cls = clspl.singularize
5749964e468SBram Moolenaar
5759964e468SBram Moolenaar    ret = []
5769964e468SBram Moolenaar    begin
5779964e468SBram Moolenaar      ret += eval( "#{cls}.instance_methods" )
5789964e468SBram Moolenaar      ret += eval( "#{clspl}Helper.instance_methods" )
5799964e468SBram Moolenaar    rescue Exception
5809964e468SBram Moolenaar      dprint "Error: Unable to load rails view helpers for %s: %s" % [ cls, $! ]
5819964e468SBram Moolenaar    end
5829964e468SBram Moolenaar
5839964e468SBram Moolenaar    return ret
5849964e468SBram Moolenaar  end
5859964e468SBram Moolenaar# }}} buffer analysis magic
5869964e468SBram Moolenaar
5879964e468SBram Moolenaar# {{{ main completion code
5889964e468SBram Moolenaar  def self.preload_rails
5899964e468SBram Moolenaar    a = VimRubyCompletion.new
5909964e468SBram Moolenaar    require 'Thread'
5919964e468SBram Moolenaar    Thread.new(a) do |b|
5929964e468SBram Moolenaar      begin
5939964e468SBram Moolenaar      b.load_rails
5949964e468SBram Moolenaar      rescue
5959964e468SBram Moolenaar      end
5969964e468SBram Moolenaar    end
5979964e468SBram Moolenaar    a.load_rails
5989964e468SBram Moolenaar  rescue
5999964e468SBram Moolenaar  end
6009964e468SBram Moolenaar
6019964e468SBram Moolenaar  def self.get_completions(base)
6029964e468SBram Moolenaar    b = VimRubyCompletion.new
6039964e468SBram Moolenaar    b.get_completions base
604fc1421ebSBram Moolenaar  end
605fc1421ebSBram Moolenaar
606c6249bb2SBram Moolenaar  def get_completions(base)
6079964e468SBram Moolenaar    loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading")
608c236c16dSBram Moolenaar    if loading_allowed.to_i == 1
609c6249bb2SBram Moolenaar      load_requires
610fc1421ebSBram Moolenaar      load_rails
6119964e468SBram Moolenaar    end
612fc1421ebSBram Moolenaar
61389bcfda6SBram Moolenaar    want_gems = VIM::evaluate("get(g:, 'rubycomplete_load_gemfile')")
61489bcfda6SBram Moolenaar    load_gems unless want_gems.to_i.zero?
61589bcfda6SBram Moolenaar
61689bcfda6SBram Moolenaar
617fc1421ebSBram Moolenaar    input = VIM::Buffer.current.line
618d8fc5c0bSBram Moolenaar    cpos = VIM::Window.current.cursor[1] - 1
6199964e468SBram Moolenaar    input = input[0..cpos]
620d8fc5c0bSBram Moolenaar    input += base
6219964e468SBram Moolenaar    input.sub!(/.*[ \t\n\"\\'`><=;|&{(]/, '') # Readline.basic_word_break_characters
6229964e468SBram Moolenaar    input.sub!(/self\./, '')
6239964e468SBram Moolenaar    input.sub!(/.*((\.\.[\[(]?)|([\[(]))/, '')
624c6249bb2SBram Moolenaar
6259964e468SBram Moolenaar    dprint 'input %s' % input
626d8fc5c0bSBram Moolenaar    message = nil
627d8fc5c0bSBram Moolenaar    receiver = nil
6289964e468SBram Moolenaar    methods = []
6299964e468SBram Moolenaar    variables = []
6309964e468SBram Moolenaar    classes = []
6319964e468SBram Moolenaar    constants = []
632c6249bb2SBram Moolenaar
633c6249bb2SBram Moolenaar    case input
634d8fc5c0bSBram Moolenaar      when /^(\/[^\/]*\/)\.([^.]*)$/ # Regexp
635c6249bb2SBram Moolenaar        receiver = $1
636c6249bb2SBram Moolenaar        message = Regexp.quote($2)
6379964e468SBram Moolenaar        methods = Regexp.instance_methods(true)
638c6249bb2SBram Moolenaar
639d8fc5c0bSBram Moolenaar      when /^([^\]]*\])\.([^.]*)$/ # Array
640c6249bb2SBram Moolenaar        receiver = $1
641c6249bb2SBram Moolenaar        message = Regexp.quote($2)
6429964e468SBram Moolenaar        methods = Array.instance_methods(true)
643c6249bb2SBram Moolenaar
644d8fc5c0bSBram Moolenaar      when /^([^\}]*\})\.([^.]*)$/ # Proc or Hash
645c6249bb2SBram Moolenaar        receiver = $1
646c6249bb2SBram Moolenaar        message = Regexp.quote($2)
6479964e468SBram Moolenaar        methods = Proc.instance_methods(true) | Hash.instance_methods(true)
648c6249bb2SBram Moolenaar
649d8fc5c0bSBram Moolenaar      when /^(:[^:.]*)$/ # Symbol
6509964e468SBram Moolenaar        dprint "symbol"
651c6249bb2SBram Moolenaar        if Symbol.respond_to?(:all_symbols)
652d8fc5c0bSBram Moolenaar          receiver = $1
6539964e468SBram Moolenaar          message = $1.sub( /:/, '' )
6549964e468SBram Moolenaar          methods = Symbol.all_symbols.collect{|s| s.id2name}
6559964e468SBram Moolenaar          methods.delete_if { |c| c.match( /'/ ) }
656c6249bb2SBram Moolenaar        end
657c6249bb2SBram Moolenaar
658d8fc5c0bSBram Moolenaar      when /^::([A-Z][^:\.\(]*)$/ # Absolute Constant or class methods
6599964e468SBram Moolenaar        dprint "const or cls"
660c6249bb2SBram Moolenaar        receiver = $1
6619964e468SBram Moolenaar        methods = Object.constants
6629964e468SBram Moolenaar        methods.grep(/^#{receiver}/).collect{|e| "::" + e}
663c6249bb2SBram Moolenaar
6641d68952aSBram Moolenaar      when /^(((::)?[A-Z][^:.\(]*)+?)::?([^:.]*)$/ # Constant or class methods
665c6249bb2SBram Moolenaar        receiver = $1
666c6249bb2SBram Moolenaar        message = Regexp.quote($4)
6679964e468SBram Moolenaar        dprint "const or cls 2 [recv: \'%s\', msg: \'%s\']" % [ receiver, message ]
6689964e468SBram Moolenaar        load_buffer_class( receiver )
669c6249bb2SBram Moolenaar        begin
6709964e468SBram Moolenaar          classes = eval("#{receiver}.constants")
6719964e468SBram Moolenaar          #methods = eval("#{receiver}.methods")
672c6249bb2SBram Moolenaar        rescue Exception
6739964e468SBram Moolenaar          dprint "exception: %s" % $!
6749964e468SBram Moolenaar          methods = []
675c6249bb2SBram Moolenaar        end
6769964e468SBram Moolenaar        methods.grep(/^#{message}/).collect{|e| receiver + "::" + e}
677c6249bb2SBram Moolenaar
678d8fc5c0bSBram Moolenaar      when /^(:[^:.]+)\.([^.]*)$/ # Symbol
6799964e468SBram Moolenaar        dprint "symbol"
680c6249bb2SBram Moolenaar        receiver = $1
681c6249bb2SBram Moolenaar        message = Regexp.quote($2)
6829964e468SBram Moolenaar        methods = Symbol.instance_methods(true)
683c6249bb2SBram Moolenaar
684d8fc5c0bSBram Moolenaar      when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/ # Numeric
6859964e468SBram Moolenaar        dprint "numeric"
686c6249bb2SBram Moolenaar        receiver = $1
687c6249bb2SBram Moolenaar        message = Regexp.quote($4)
688c6249bb2SBram Moolenaar        begin
6899964e468SBram Moolenaar          methods = eval(receiver).methods
690c6249bb2SBram Moolenaar        rescue Exception
6919964e468SBram Moolenaar          methods = []
692c6249bb2SBram Moolenaar        end
693c6249bb2SBram Moolenaar
694d8fc5c0bSBram Moolenaar      when /^(\$[^.]*)$/ #global
6959964e468SBram Moolenaar        dprint "global"
6969964e468SBram Moolenaar        methods = global_variables.grep(Regexp.new(Regexp.quote($1)))
697c6249bb2SBram Moolenaar
6981d68952aSBram Moolenaar      when /^((\.?[^.]+)+?)\.([^.]*)$/ # variable
6999964e468SBram Moolenaar        dprint "variable"
700c6249bb2SBram Moolenaar        receiver = $1
701c6249bb2SBram Moolenaar        message = Regexp.quote($3)
702fc1421ebSBram Moolenaar        load_buffer_class( receiver )
703c6249bb2SBram Moolenaar
704c6249bb2SBram Moolenaar        cv = eval("self.class.constants")
705d8fc5c0bSBram Moolenaar        vartype = get_var_type( receiver )
7069964e468SBram Moolenaar        dprint "vartype: %s" % vartype
70789bcfda6SBram Moolenaar
70889bcfda6SBram Moolenaar        invalid_vartype = ['', "gets"]
70989bcfda6SBram Moolenaar        if !invalid_vartype.include?(vartype)
710fc1421ebSBram Moolenaar          load_buffer_class( vartype )
711fc1421ebSBram Moolenaar
712fc1421ebSBram Moolenaar          begin
7139964e468SBram Moolenaar            methods = eval("#{vartype}.instance_methods")
7149964e468SBram Moolenaar            variables = eval("#{vartype}.instance_variables")
715fc1421ebSBram Moolenaar          rescue Exception
7169964e468SBram Moolenaar            dprint "load_buffer_class err: %s" % $!
717fc1421ebSBram Moolenaar          end
718c6249bb2SBram Moolenaar        elsif (cv).include?(receiver)
719c6249bb2SBram Moolenaar          # foo.func and foo is local var.
7209964e468SBram Moolenaar          methods = eval("#{receiver}.methods")
7219964e468SBram Moolenaar          vartype = receiver
722c6249bb2SBram Moolenaar        elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
7239964e468SBram Moolenaar          vartype = receiver
724c6249bb2SBram Moolenaar          # Foo::Bar.func
725c6249bb2SBram Moolenaar          begin
7269964e468SBram Moolenaar            methods = eval("#{receiver}.methods")
727c6249bb2SBram Moolenaar          rescue Exception
728c6249bb2SBram Moolenaar          end
729c6249bb2SBram Moolenaar        else
730c6249bb2SBram Moolenaar          # func1.func2
731c6249bb2SBram Moolenaar          ObjectSpace.each_object(Module){|m|
732c6249bb2SBram Moolenaar            next if m.name != "IRB::Context" and
733c6249bb2SBram Moolenaar              /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name
7349964e468SBram Moolenaar            methods.concat m.instance_methods(false)
735c6249bb2SBram Moolenaar          }
736c6249bb2SBram Moolenaar        end
73789bcfda6SBram Moolenaar        variables += add_rails_columns( "#{vartype}" ) if vartype && !invalid_vartype.include?(vartype)
738c6249bb2SBram Moolenaar
739d8fc5c0bSBram Moolenaar      when /^\(?\s*[A-Za-z0-9:^@.%\/+*\(\)]+\.\.\.?[A-Za-z0-9:^@.%\/+*\(\)]+\s*\)?\.([^.]*)/
740d8fc5c0bSBram Moolenaar        message = $1
7419964e468SBram Moolenaar        methods = Range.instance_methods(true)
742c6249bb2SBram Moolenaar
743d8fc5c0bSBram Moolenaar      when /^\.([^.]*)$/ # unknown(maybe String)
744c6249bb2SBram Moolenaar        message = Regexp.quote($1)
7459964e468SBram Moolenaar        methods = String.instance_methods(true)
746c6249bb2SBram Moolenaar
747c6249bb2SBram Moolenaar    else
7489964e468SBram Moolenaar      dprint "default/other"
7499964e468SBram Moolenaar      inclass = eval( VIM::evaluate("s:IsInClassDef()") )
750c6249bb2SBram Moolenaar
751fc1421ebSBram Moolenaar      if inclass != nil
7529964e468SBram Moolenaar        dprint "inclass"
753fc1421ebSBram Moolenaar        classdef = "%s\n" % VIM::Buffer.current[ inclass.min ]
754fc1421ebSBram Moolenaar        found = /^\s*class\s*([A-Za-z0-9_-]*)(\s*<\s*([A-Za-z0-9_:-]*))?\s*\n$/.match( classdef )
755fc1421ebSBram Moolenaar
756fc1421ebSBram Moolenaar        if found != nil
757fc1421ebSBram Moolenaar          receiver = $1
758fc1421ebSBram Moolenaar          message = input
759fc1421ebSBram Moolenaar          load_buffer_class( receiver )
760eb3593b3SBram Moolenaar          begin
7619964e468SBram Moolenaar            methods = eval( "#{receiver}.instance_methods" )
7629964e468SBram Moolenaar            variables += add_rails_columns( "#{receiver}" )
763eb3593b3SBram Moolenaar          rescue Exception
764eb3593b3SBram Moolenaar            found = nil
765eb3593b3SBram Moolenaar          end
766fc1421ebSBram Moolenaar        end
767fc1421ebSBram Moolenaar      end
768fc1421ebSBram Moolenaar
769fc1421ebSBram Moolenaar      if inclass == nil || found == nil
7709964e468SBram Moolenaar        dprint "inclass == nil"
7719964e468SBram Moolenaar        methods = get_buffer_methods
7729964e468SBram Moolenaar        methods += get_rails_view_methods
7739964e468SBram Moolenaar
7749964e468SBram Moolenaar        cls_const = Class.constants
7759964e468SBram Moolenaar        constants = cls_const.select { |c| /^[A-Z_-]+$/.match( c ) }
7769964e468SBram Moolenaar        classes = eval("self.class.constants") - constants
7779964e468SBram Moolenaar        classes += get_buffer_classes
7789964e468SBram Moolenaar        classes += get_buffer_modules
7799964e468SBram Moolenaar
7809964e468SBram Moolenaar        include_objectspace = VIM::evaluate("exists('g:rubycomplete_include_objectspace') && g:rubycomplete_include_objectspace")
7819964e468SBram Moolenaar        ObjectSpace.each_object(Class) { |cls| classes << cls.to_s } if include_objectspace == "1"
782d8fc5c0bSBram Moolenaar        message = receiver = input
783d8fc5c0bSBram Moolenaar      end
7849964e468SBram Moolenaar
7859964e468SBram Moolenaar      methods += get_rails_helpers
7869964e468SBram Moolenaar      methods += Kernel.public_methods
787d8fc5c0bSBram Moolenaar    end
788d8fc5c0bSBram Moolenaar
7899964e468SBram Moolenaar
7909964e468SBram Moolenaar    include_object = VIM::evaluate("exists('g:rubycomplete_include_object') && g:rubycomplete_include_object")
7919964e468SBram Moolenaar    methods = clean_sel( methods, message )
7929964e468SBram Moolenaar    methods = (methods-Object.instance_methods) if include_object == "0"
7939964e468SBram Moolenaar    rbcmeth = (VimRubyCompletion.instance_methods-Object.instance_methods) # lets remove those rubycomplete methods
7949964e468SBram Moolenaar    methods = (methods-rbcmeth)
7959964e468SBram Moolenaar
7969964e468SBram Moolenaar    variables = clean_sel( variables, message )
7979964e468SBram Moolenaar    classes = clean_sel( classes, message ) - ["VimRubyCompletion"]
7989964e468SBram Moolenaar    constants = clean_sel( constants, message )
7999964e468SBram Moolenaar
8009964e468SBram Moolenaar    valid = []
801ec7944aaSBram Moolenaar    valid += methods.collect { |m| { :name => m.to_s, :type => 'm' } }
802ec7944aaSBram Moolenaar    valid += variables.collect { |v| { :name => v.to_s, :type => 'v' } }
803ec7944aaSBram Moolenaar    valid += classes.collect { |c| { :name => c.to_s, :type => 't' } }
804ec7944aaSBram Moolenaar    valid += constants.collect { |d| { :name => d.to_s, :type => 'd' } }
8059964e468SBram Moolenaar    valid.sort! { |x,y| x[:name] <=> y[:name] }
806c6249bb2SBram Moolenaar
807c6249bb2SBram Moolenaar    outp = ""
808fc1421ebSBram Moolenaar
809fc1421ebSBram Moolenaar    rg = 0..valid.length
810fc1421ebSBram Moolenaar    rg.step(150) do |x|
811fc1421ebSBram Moolenaar      stpos = 0+x
812fc1421ebSBram Moolenaar      enpos = 150+x
813ec7944aaSBram Moolenaar      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)} }
814c6249bb2SBram Moolenaar      outp.sub!(/,$/, '')
815fc1421ebSBram Moolenaar
816fc1421ebSBram Moolenaar      VIM::command("call extend(g:rubycomplete_completions, [%s])" % outp)
817fc1421ebSBram Moolenaar      outp = ""
818fc1421ebSBram Moolenaar    end
819c6249bb2SBram Moolenaar  end
8209964e468SBram Moolenaar# }}} main completion code
821c6249bb2SBram Moolenaar
8229964e468SBram Moolenaarend # VimRubyCompletion
823eb3593b3SBram Moolenaar# }}} ruby completion
824c6249bb2SBram MoolenaarRUBYEOF
825c6249bb2SBram Moolenaarendfunction
826c6249bb2SBram Moolenaar
8279964e468SBram Moolenaarlet s:rubycomplete_rails_loaded = 0
828fc1421ebSBram Moolenaar
829c6249bb2SBram Moolenaarcall s:DefRuby()
8309964e468SBram Moolenaar"}}} ruby-side code
8319964e468SBram Moolenaar
8329964e468SBram Moolenaar
8339964e468SBram Moolenaar" vim:tw=78:sw=4:ts=8:et:fdm=marker:ft=vim:norl:
834