home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / runtime / autoload / rubycomplete.vim < prev    next >
Encoding:
Text File  |  2010-08-14  |  22.9 KB  |  803 lines

  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
  15. if !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
  21. endif
  22.  
  23. if version < 700
  24.     s:ErrMsg( "Error: Required vim >= 7.0" )
  25.     finish
  26. endif
  27. " }}} requirement checks
  28.  
  29. " {{{ configuration failsafe initialization
  30. if !exists("g:rubycomplete_rails")
  31.     let g:rubycomplete_rails = 0
  32. endif
  33.  
  34. if !exists("g:rubycomplete_classes_in_global")
  35.     let g:rubycomplete_classes_in_global = 0
  36. endif
  37.  
  38. if !exists("g:rubycomplete_buffer_loading")
  39.     let g:rubycomplete_buffer_loading = 0
  40. endif
  41.  
  42. if !exists("g:rubycomplete_include_object")
  43.     let g:rubycomplete_include_object = 0
  44. endif
  45.  
  46. if !exists("g:rubycomplete_include_objectspace")
  47.     let g:rubycomplete_include_objectspace = 0
  48. endif
  49. " }}} configuration failsafe initialization
  50.  
  51. " {{{ vim-side support functions
  52. let s:rubycomplete_debug = 0
  53.  
  54. function! s:ErrMsg(msg)
  55.     echohl ErrorMsg
  56.     echo a:msg
  57.     echohl None
  58. endfunction
  59.  
  60. function! s:dprint(msg)
  61.     if s:rubycomplete_debug == 1
  62.         echom a:msg
  63.     endif
  64. endfunction
  65.  
  66. function! 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
  73. endfunction
  74.  
  75. function! 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
  82. endfunction
  83.  
  84. function! s:GetBufferRubySingletonMethods(name)
  85. endfunction
  86.  
  87. function! 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]
  115. endfunction
  116.  
  117. function! s:IsInClassDef()
  118.     return s:IsPosInClassDef( line('.') )
  119. endfunction
  120.  
  121. function! 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
  130. endfunction
  131.  
  132. function! 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 ''
  180. endfunction
  181.  
  182. "}}} vim-side support functions
  183.  
  184. "{{{ vim-side completion function
  185. function! rubycomplete#Init()
  186.     execute "ruby VimRubyCompletion.preload_rails"
  187. endfunction
  188.  
  189. function! 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
  214. endfunction
  215. "}}} vim-side completion function
  216.  
  217. "{{{ ruby-side code
  218. function! s:DefRuby()
  219. ruby << RUBYEOF
  220. # {{{ ruby completion
  221.  
  222. begin
  223.     require 'rubygems' # let's assume this is safe...?
  224. rescue Exception
  225.     #ignore?
  226. end
  227. class 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.  
  791. end # VimRubyCompletion
  792. # }}} ruby completion
  793. RUBYEOF
  794. endfunction
  795.  
  796. let s:rubycomplete_rails_loaded = 0
  797.  
  798. call s:DefRuby()
  799. "}}} ruby-side code
  800.  
  801.  
  802. " vim:tw=78:sw=4:ts=8:et:fdm=marker:ft=vim:norl:
  803.