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*\<' . escape(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 = ''.escape(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                let 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_gems
270    fpath = VIM::evaluate("get(g:, 'rubycomplete_gemfile_path', 'Gemfile')")
271    return unless File.file?(fpath) && File.readable?(fpath)
272    want_bundler = VIM::evaluate("get(g:, 'rubycomplete_use_bundler')")
273    parse_file = !want_bundler
274    begin
275      require 'bundler'
276      Bundler.setup
277      Bundler.require
278    rescue Exception
279      parse_file = true
280    end
281    if parse_file
282      File.new(fpath).each_line do |line|
283        begin
284          require $1 if /\s*gem\s*['"]([^'"]+)/.match(line)
285        rescue Exception
286        end
287      end
288    end
289  end
290
291  def load_buffer_class(name)
292    dprint "load_buffer_class(%s) START" % name
293    classdef = get_buffer_entity(name, 's:GetBufferRubyClass("%s")')
294    return if classdef == nil
295
296    pare = /^\s*class\s*(.*)\s*<\s*(.*)\s*\n/.match( classdef )
297    load_buffer_class( $2 ) if pare != nil  && $2 != name # load parent class if needed
298
299    mixre = /.*\n\s*(include|prepend)\s*(.*)\s*\n/.match( classdef )
300    load_buffer_module( $2 ) if mixre != nil && $2 != name # load mixins if needed
301
302    begin
303      eval classdef
304    rescue Exception
305      VIM::evaluate( "s:ErrMsg( 'Problem loading class \"%s\", was it already completed?' )" % name )
306    end
307    dprint "load_buffer_class(%s) END" % name
308  end
309
310  def load_buffer_module(name)
311    dprint "load_buffer_module(%s) START" % name
312    classdef = get_buffer_entity(name, 's:GetBufferRubyModule("%s")')
313    return if classdef == nil
314
315    begin
316      eval classdef
317    rescue Exception
318      VIM::evaluate( "s:ErrMsg( 'Problem loading module \"%s\", was it already completed?' )" % name )
319    end
320    dprint "load_buffer_module(%s) END" % name
321  end
322
323  def get_buffer_entity(name, vimfun)
324    loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading")
325    return nil if loading_allowed.to_i.zero?
326    return nil if /(\"|\')+/.match( name )
327    buf = VIM::Buffer.current
328    nums = eval( VIM::evaluate( vimfun % name ) )
329    return nil if nums == nil
330    return nil if nums.min == nums.max && nums.min == 0
331
332    dprint "get_buffer_entity START"
333    visited = []
334    clscnt = 0
335    bufname = VIM::Buffer.current.name
336    classdef = ""
337    cur_line = VIM::Buffer.current.line_number
338    while (nums != nil && !(nums.min == 0 && nums.max == 0) )
339      dprint "visited: %s" % visited.to_s
340      break if visited.index( nums )
341      visited << nums
342
343      nums.each do |x|
344        if x != cur_line
345          next if x == 0
346          ln = buf[x]
347          if /^\s*(module|class|def|include)\s+/.match(ln)
348            clscnt += 1 if $1 == "class"
349            #dprint "\$1$1
350            classdef += "%s\n" % ln
351            classdef += "end\n" if /def\s+/.match(ln)
352            dprint ln
353          end
354        end
355      end
356
357      nm = "%s(::.*)*\", %s, \"" % [ name, nums.last ]
358      nums = eval( VIM::evaluate( vimfun % nm ) )
359      dprint "nm: \"%s\"" % nm
360      dprint "vimfun: %s" % (vimfun % nm)
361      dprint "got nums: %s" % nums.to_s
362    end
363    if classdef.length > 1
364        classdef += "end\n"*clscnt
365        # classdef = "class %s\n%s\nend\n" % [ bufname.gsub( /\/|\\/, "_" ), classdef ]
366    end
367
368    dprint "get_buffer_entity END"
369    dprint "classdef====start"
370    lns = classdef.split( "\n" )
371    lns.each { |x| dprint x }
372    dprint "classdef====end"
373    return classdef
374  end
375
376  def get_var_type( receiver )
377    if /(\"|\')+/.match( receiver )
378      "String"
379    else
380      VIM::evaluate("s:GetRubyVarType('%s')" % receiver)
381    end
382  end
383
384  def dprint( txt )
385    print txt if @@debug
386  end
387
388  def escape_vim_singlequote_string(str)
389    str.to_s.gsub(/'/,"\\'")
390  end
391
392  def get_buffer_entity_list( type )
393    # this will be a little expensive.
394    loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading")
395    allow_aggressive_load = VIM::evaluate("exists('g:rubycomplete_classes_in_global') && g:rubycomplete_classes_in_global")
396    return [] if allow_aggressive_load.to_i.zero? || loading_allowed.to_i.zero?
397
398    buf = VIM::Buffer.current
399    eob = buf.length
400    ret = []
401    rg = 1..eob
402    re = eval( "/^\s*%s\s*([A-Za-z0-9_:-]*)(\s*<\s*([A-Za-z0-9_:-]*))?\s*/" % type )
403
404    rg.each do |x|
405      if re.match( buf[x] )
406        next if type == "def" && eval( VIM::evaluate("s:IsPosInClassDef(%s)" % x) ) != nil
407        ret.push $1
408      end
409    end
410
411    return ret
412  end
413
414  def get_buffer_modules
415    return get_buffer_entity_list( "modules" )
416  end
417
418  def get_buffer_methods
419    return get_buffer_entity_list( "def" )
420  end
421
422  def get_buffer_classes
423    return get_buffer_entity_list( "class" )
424  end
425
426
427  def load_rails
428    allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails")
429    return if allow_rails.to_i.zero?
430
431    buf_path = VIM::evaluate('expand("%:p")')
432    file_name = VIM::evaluate('expand("%:t")')
433    vim_dir = VIM::evaluate('getcwd()')
434    file_dir = buf_path.gsub( file_name, '' )
435    file_dir.gsub!( /\\/, "/" )
436    vim_dir.gsub!( /\\/, "/" )
437    vim_dir << "/"
438    dirs = [ vim_dir, file_dir ]
439    sdirs = [ "", "./", "../", "../../", "../../../", "../../../../" ]
440    rails_base = nil
441
442    dirs.each do |dir|
443      sdirs.each do |sub|
444        trail = "%s%s" % [ dir, sub ]
445        tcfg = "%sconfig" % trail
446
447        if File.exists?( tcfg )
448          rails_base = trail
449          break
450        end
451      end
452      break if rails_base
453    end
454
455    return if rails_base == nil
456    $:.push rails_base unless $:.index( rails_base )
457
458    rails_config = rails_base + "config/"
459    rails_lib = rails_base + "lib/"
460    $:.push rails_config unless $:.index( rails_config )
461    $:.push rails_lib unless $:.index( rails_lib )
462
463    bootfile = rails_config + "boot.rb"
464    envfile = rails_config + "environment.rb"
465    if File.exists?( bootfile ) && File.exists?( envfile )
466      begin
467        require bootfile
468        require envfile
469        begin
470          require 'console_app'
471          require 'console_with_helpers'
472        rescue Exception
473          dprint "Rails 1.1+ Error %s" % $!
474          # assume 1.0
475        end
476        #eval( "Rails::Initializer.run" ) #not necessary?
477        VIM::command('let s:rubycomplete_rails_loaded = 1')
478        dprint "rails loaded"
479      rescue Exception
480        dprint "Rails Error %s" % $!
481        VIM::evaluate( "s:ErrMsg('Error loading rails environment')" )
482      end
483    end
484  end
485
486  def get_rails_helpers
487    allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails")
488    rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded')
489    return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero?
490
491    buf_path = VIM::evaluate('expand("%:p")')
492    buf_path.gsub!( /\\/, "/" )
493    path_elm = buf_path.split( "/" )
494    dprint "buf_path: %s" % buf_path
495    types = [ "app", "db", "lib", "test", "components", "script" ]
496
497    i = nil
498    ret = []
499    type = nil
500    types.each do |t|
501      i = path_elm.index( t )
502      break if i
503    end
504    type = path_elm[i]
505    type.downcase!
506
507    dprint "type: %s" % type
508    case type
509      when "app"
510        i += 1
511        subtype = path_elm[i]
512        subtype.downcase!
513
514        dprint "subtype: %s" % subtype
515        case subtype
516          when "views"
517            ret += ActionView::Base.instance_methods
518            ret += ActionView::Base.methods
519          when "controllers"
520            ret += ActionController::Base.instance_methods
521            ret += ActionController::Base.methods
522          when "models"
523            ret += ActiveRecord::Base.instance_methods
524            ret += ActiveRecord::Base.methods
525        end
526
527      when "db"
528        ret += ActiveRecord::ConnectionAdapters::SchemaStatements.instance_methods
529        ret += ActiveRecord::ConnectionAdapters::SchemaStatements.methods
530    end
531
532
533    return ret
534  end
535
536  def add_rails_columns( cls )
537    allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails")
538    rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded')
539    return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero?
540
541    begin
542        eval( "#{cls}.establish_connection" )
543        return [] unless eval( "#{cls}.ancestors.include?(ActiveRecord::Base).to_s" )
544        col = eval( "#{cls}.column_names" )
545        return col if col
546    rescue
547        dprint "add_rails_columns err: (cls: %s) %s" % [ cls, $! ]
548        return []
549    end
550    return []
551  end
552
553  def clean_sel(sel, msg)
554    ret = sel.reject{|x|x.nil?}.uniq
555    ret = ret.grep(/^#{Regexp.quote(msg)}/) if msg != nil
556    ret
557  end
558
559  def get_rails_view_methods
560    allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails")
561    rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded')
562    return [] if allow_rails.to_i.zero? || rails_loaded.to_i.zero?
563
564    buf_path = VIM::evaluate('expand("%:p")')
565    buf_path.gsub!( /\\/, "/" )
566    pelm = buf_path.split( "/" )
567    idx = pelm.index( "views" )
568
569    return [] unless idx
570    idx += 1
571
572    clspl = pelm[idx].camelize.pluralize
573    cls = clspl.singularize
574
575    ret = []
576    begin
577      ret += eval( "#{cls}.instance_methods" )
578      ret += eval( "#{clspl}Helper.instance_methods" )
579    rescue Exception
580      dprint "Error: Unable to load rails view helpers for %s: %s" % [ cls, $! ]
581    end
582
583    return ret
584  end
585# }}} buffer analysis magic
586
587# {{{ main completion code
588  def self.preload_rails
589    a = VimRubyCompletion.new
590    require 'Thread'
591    Thread.new(a) do |b|
592      begin
593      b.load_rails
594      rescue
595      end
596    end
597    a.load_rails
598  rescue
599  end
600
601  def self.get_completions(base)
602    b = VimRubyCompletion.new
603    b.get_completions base
604  end
605
606  def get_completions(base)
607    loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading")
608    if loading_allowed.to_i == 1
609      load_requires
610      load_rails
611    end
612
613    want_gems = VIM::evaluate("get(g:, 'rubycomplete_load_gemfile')")
614    load_gems unless want_gems.to_i.zero?
615
616
617    input = VIM::Buffer.current.line
618    cpos = VIM::Window.current.cursor[1] - 1
619    input = input[0..cpos]
620    input += base
621    input.sub!(/.*[ \t\n\"\\'`><=;|&{(]/, '') # Readline.basic_word_break_characters
622    input.sub!(/self\./, '')
623    input.sub!(/.*((\.\.[\[(]?)|([\[(]))/, '')
624
625    dprint 'input %s' % input
626    message = nil
627    receiver = nil
628    methods = []
629    variables = []
630    classes = []
631    constants = []
632
633    case input
634      when /^(\/[^\/]*\/)\.([^.]*)$/ # Regexp
635        receiver = $1
636        message = Regexp.quote($2)
637        methods = Regexp.instance_methods(true)
638
639      when /^([^\]]*\])\.([^.]*)$/ # Array
640        receiver = $1
641        message = Regexp.quote($2)
642        methods = Array.instance_methods(true)
643
644      when /^([^\}]*\})\.([^.]*)$/ # Proc or Hash
645        receiver = $1
646        message = Regexp.quote($2)
647        methods = Proc.instance_methods(true) | Hash.instance_methods(true)
648
649      when /^(:[^:.]*)$/ # Symbol
650        dprint "symbol"
651        if Symbol.respond_to?(:all_symbols)
652          receiver = $1
653          message = $1.sub( /:/, '' )
654          methods = Symbol.all_symbols.collect{|s| s.id2name}
655          methods.delete_if { |c| c.match( /'/ ) }
656        end
657
658      when /^::([A-Z][^:\.\(]*)$/ # Absolute Constant or class methods
659        dprint "const or cls"
660        receiver = $1
661        methods = Object.constants
662        methods.grep(/^#{receiver}/).collect{|e| "::" + e}
663
664      when /^(((::)?[A-Z][^:.\(]*)+?)::?([^:.]*)$/ # Constant or class methods
665        receiver = $1
666        message = Regexp.quote($4)
667        dprint "const or cls 2 [recv: \'%s\', msg: \'%s\']" % [ receiver, message ]
668        load_buffer_class( receiver )
669        begin
670          classes = eval("#{receiver}.constants")
671          #methods = eval("#{receiver}.methods")
672        rescue Exception
673          dprint "exception: %s" % $!
674          methods = []
675        end
676        methods.grep(/^#{message}/).collect{|e| receiver + "::" + e}
677
678      when /^(:[^:.]+)\.([^.]*)$/ # Symbol
679        dprint "symbol"
680        receiver = $1
681        message = Regexp.quote($2)
682        methods = Symbol.instance_methods(true)
683
684      when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/ # Numeric
685        dprint "numeric"
686        receiver = $1
687        message = Regexp.quote($4)
688        begin
689          methods = eval(receiver).methods
690        rescue Exception
691          methods = []
692        end
693
694      when /^(\$[^.]*)$/ #global
695        dprint "global"
696        methods = global_variables.grep(Regexp.new(Regexp.quote($1)))
697
698      when /^((\.?[^.]+)+?)\.([^.]*)$/ # variable
699        dprint "variable"
700        receiver = $1
701        message = Regexp.quote($3)
702        load_buffer_class( receiver )
703
704        cv = eval("self.class.constants")
705        vartype = get_var_type( receiver )
706        dprint "vartype: %s" % vartype
707
708        invalid_vartype = ['', "gets"]
709        if !invalid_vartype.include?(vartype)
710          load_buffer_class( vartype )
711
712          begin
713            methods = eval("#{vartype}.instance_methods")
714            variables = eval("#{vartype}.instance_variables")
715          rescue Exception
716            dprint "load_buffer_class err: %s" % $!
717          end
718        elsif (cv).include?(receiver)
719          # foo.func and foo is local var.
720          methods = eval("#{receiver}.methods")
721          vartype = receiver
722        elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
723          vartype = receiver
724          # Foo::Bar.func
725          begin
726            methods = eval("#{receiver}.methods")
727          rescue Exception
728          end
729        else
730          # func1.func2
731          ObjectSpace.each_object(Module){|m|
732            next if m.name != "IRB::Context" and
733              /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name
734            methods.concat m.instance_methods(false)
735          }
736        end
737        variables += add_rails_columns( "#{vartype}" ) if vartype && !invalid_vartype.include?(vartype)
738
739      when /^\(?\s*[A-Za-z0-9:^@.%\/+*\(\)]+\.\.\.?[A-Za-z0-9:^@.%\/+*\(\)]+\s*\)?\.([^.]*)/
740        message = $1
741        methods = Range.instance_methods(true)
742
743      when /^\.([^.]*)$/ # unknown(maybe String)
744        message = Regexp.quote($1)
745        methods = String.instance_methods(true)
746
747    else
748      dprint "default/other"
749      inclass = eval( VIM::evaluate("s:IsInClassDef()") )
750
751      if inclass != nil
752        dprint "inclass"
753        classdef = "%s\n" % VIM::Buffer.current[ inclass.min ]
754        found = /^\s*class\s*([A-Za-z0-9_-]*)(\s*<\s*([A-Za-z0-9_:-]*))?\s*\n$/.match( classdef )
755
756        if found != nil
757          receiver = $1
758          message = input
759          load_buffer_class( receiver )
760          begin
761            methods = eval( "#{receiver}.instance_methods" )
762            variables += add_rails_columns( "#{receiver}" )
763          rescue Exception
764            found = nil
765          end
766        end
767      end
768
769      if inclass == nil || found == nil
770        dprint "inclass == nil"
771        methods = get_buffer_methods
772        methods += get_rails_view_methods
773
774        cls_const = Class.constants
775        constants = cls_const.select { |c| /^[A-Z_-]+$/.match( c ) }
776        classes = eval("self.class.constants") - constants
777        classes += get_buffer_classes
778        classes += get_buffer_modules
779
780        include_objectspace = VIM::evaluate("exists('g:rubycomplete_include_objectspace') && g:rubycomplete_include_objectspace")
781        ObjectSpace.each_object(Class) { |cls| classes << cls.to_s } if include_objectspace == "1"
782        message = receiver = input
783      end
784
785      methods += get_rails_helpers
786      methods += Kernel.public_methods
787    end
788
789
790    include_object = VIM::evaluate("exists('g:rubycomplete_include_object') && g:rubycomplete_include_object")
791    methods = clean_sel( methods, message )
792    methods = (methods-Object.instance_methods) if include_object == "0"
793    rbcmeth = (VimRubyCompletion.instance_methods-Object.instance_methods) # lets remove those rubycomplete methods
794    methods = (methods-rbcmeth)
795
796    variables = clean_sel( variables, message )
797    classes = clean_sel( classes, message ) - ["VimRubyCompletion"]
798    constants = clean_sel( constants, message )
799
800    valid = []
801    valid += methods.collect { |m| { :name => m.to_s, :type => 'm' } }
802    valid += variables.collect { |v| { :name => v.to_s, :type => 'v' } }
803    valid += classes.collect { |c| { :name => c.to_s, :type => 't' } }
804    valid += constants.collect { |d| { :name => d.to_s, :type => 'd' } }
805    valid.sort! { |x,y| x[:name] <=> y[:name] }
806
807    outp = ""
808
809    rg = 0..valid.length
810    rg.step(150) do |x|
811      stpos = 0+x
812      enpos = 150+x
813      valid[stpos..enpos].each { |c| outp += "{'word':'%s','item':'%s','kind':'%s'}," % [ c[:name], c[:name], c[:type] ].map{|x|escape_vim_singlequote_string(x)} }
814      outp.sub!(/,$/, '')
815
816      VIM::command("call extend(g:rubycomplete_completions, [%s])" % outp)
817      outp = ""
818    end
819  end
820# }}} main completion code
821
822end # VimRubyCompletion
823# }}} ruby completion
824RUBYEOF
825endfunction
826
827let s:rubycomplete_rails_loaded = 0
828
829call s:DefRuby()
830"}}} ruby-side code
831
832
833" vim:tw=78:sw=4:ts=8:et:fdm=marker:ft=vim:norl:
834