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