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