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