diff options
Diffstat (limited to 'runtime/autoload/rubycomplete.vim')
-rw-r--r-- | runtime/autoload/rubycomplete.vim | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/runtime/autoload/rubycomplete.vim b/runtime/autoload/rubycomplete.vim new file mode 100644 index 0000000000..8def228edc --- /dev/null +++ b/runtime/autoload/rubycomplete.vim @@ -0,0 +1,308 @@ +" Vim completion script +" Language: Ruby +" Maintainer: Mark Guzman ( segfault AT hasno DOT info ) +" Info: $Id$ +" URL: http://vim-ruby.rubyforge.org +" Anon CVS: See above site +" Release Coordinator: Doug Kearns <dougkearns@gmail.com> +" ---------------------------------------------------------------------------- +" +" Ruby IRB/Complete author: Keiju ISHITSUKA(keiju@ishitsuka.com) +" ---------------------------------------------------------------------------- + +if !has('ruby') + echo "Error: Required vim compiled with +ruby" + finish +endif + +if version < 700 + echo "Error: Required vim >= 7.0" + finish +endif + +func! GetRubyVarType(v) + let stopline = 1 + let vtp = '' + let pos = getpos('.') + let [lnum,lcol] = searchpos('^\s*#\s*@var\s*'.a:v.'\>\s\+[^ \t]\+\s*$','nb',stopline) + if lnum != 0 && lcol != 0 + call setpos('.',pos) + let str = getline(lnum) + let vtp = substitute(str,'^\s*#\s*@var\s*'.a:v.'\>\s\+\([^ \t]\+\)\s*$','\1','') + return vtp + endif + call setpos('.',pos) + let [lnum,lcol] = searchpos(''.a:v.'\>\s*[+\-*/]*=\s*\([^ \t]\+.\(now\|new\|open\|get_instance\)\>\|[\[{"'']\)','nb',stopline) + if lnum != 0 && lcol != 0 + let str = matchstr(getline(lnum),'=\s*\([^ \t]\+.\(now\|new\|open\|get_instance\)\>\|[\[{"'']\)',lcol) + let str = substitute(str,'^=\s*','','') + call setpos('.',pos) + if str == '"' || str == '''' + return 'String' + elseif str == '[' + return 'Array' + elseif str == '{' + return 'Hash' + elseif strlen(str) > 4 + let l = stridx(str,'.') + return str[0:l-1] + end + return '' + endif + call setpos('.',pos) + return '' +endf + +function! rubycomplete#Complete(findstart, base) + "findstart = 1 when we need to get the text length + if a:findstart + let line = getline('.') + let idx = col('.') + while idx > 0 + let idx -= 1 + let c = line[idx-1] + if c =~ '\w' + continue + elseif ! c =~ '\.' + idx = -1 + break + else + break + endif + endwhile + + return idx + "findstart = 0 when we need to return the list of completions + else + execute "ruby get_completions('" . a:base . "')" + return g:rbcomplete_completions + endif +endfunction + + +function! s:DefRuby() +ruby << RUBYEOF +ReservedWords = [ + "BEGIN", "END", + "alias", "and", + "begin", "break", + "case", "class", + "def", "defined", "do", + "else", "elsif", "end", "ensure", + "false", "for", + "if", "in", + "module", + "next", "nil", "not", + "or", + "redo", "rescue", "retry", "return", + "self", "super", + "then", "true", + "undef", "unless", "until", + "when", "while", + "yield", + ] + +Operators = [ "%", "&", "*", "**", "+", "-", "/", + "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>", + "[]", "[]=", "^", ] + +def identify_type(var) + @buf = VIM::Buffer.current + enum = @buf.line_number + snum = (enum-10).abs + nums = Range.new( snum, enum ) + regxs = '/.*(%s)\s*=(.*)/' % var + regx = Regexp.new( regxs ) + nums.each do |x| + ln = @buf[x] + #print $~ if regx.match( ln ) + end +end + +def load_requires + @buf = VIM::Buffer.current + enum = @buf.line_number + nums = Range.new( 1, enum ) + nums.each do |x| + ln = @buf[x] + begin + eval( "require %s" % $1 ) if /.*require\s*(.*)$/.match( ln ) + rescue Exception + #ignore? + end + end +end + +def get_completions(base) + load_requires + input = VIM::evaluate('expand("<cWORD>")') + input += base + message = nil + + + case input + when /^(\/[^\/]*\/)\.([^.]*)$/ + # Regexp + receiver = $1 + message = Regexp.quote($2) + + candidates = Regexp.instance_methods(true) + select_message(receiver, message, candidates) + + when /^([^\]]*\])\.([^.]*)$/ + # Array + receiver = $1 + message = Regexp.quote($2) + + candidates = Array.instance_methods(true) + select_message(receiver, message, candidates) + + when /^([^\}]*\})\.([^.]*)$/ + # Proc or Hash + receiver = $1 + message = Regexp.quote($2) + + candidates = Proc.instance_methods(true) | Hash.instance_methods(true) + select_message(receiver, message, candidates) + + when /^(:[^:.]*)$/ + # Symbol + if Symbol.respond_to?(:all_symbols) + sym = $1 + candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name} + candidates.grep(/^#{sym}/) + else + [] + end + + when /^::([A-Z][^:\.\(]*)$/ + # Absolute Constant or class methods + receiver = $1 + candidates = Object.constants + candidates.grep(/^#{receiver}/).collect{|e| "::" + e} + + when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/ + # Constant or class methods + receiver = $1 + message = Regexp.quote($4) + begin + candidates = eval("#{receiver}.constants | #{receiver}.methods") + rescue Exception + candidates = [] + end + candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e} + + when /^(:[^:.]+)\.([^.]*)$/ + # Symbol + receiver = $1 + message = Regexp.quote($2) + + candidates = Symbol.instance_methods(true) + select_message(receiver, message, candidates) + + when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/ + # Numeric + receiver = $1 + message = Regexp.quote($4) + + begin + candidates = eval(receiver).methods + rescue Exception + candidates + end + select_message(receiver, message, candidates) + + when /^(\$[^.]*)$/ + candidates = global_variables.grep(Regexp.new(Regexp.quote($1))) + +# when /^(\$?(\.?[^.]+)+)\.([^.]*)$/ + when /^((\.?[^.]+)+)\.([^.]*)$/ + # variable + receiver = $1 + message = Regexp.quote($3) + + cv = eval("self.class.constants") + + vartype = VIM::evaluate("GetRubyVarType('%s')" % receiver) + if vartype != '' + candidates = eval("#{vartype}.instance_methods") + elsif (cv).include?(receiver) + # foo.func and foo is local var. + candidates = eval("#{receiver}.methods") + elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver + # Foo::Bar.func + begin + candidates = eval("#{receiver}.methods") + rescue Exception + candidates = [] + end + else + # func1.func2 + candidates = [] + ObjectSpace.each_object(Module){|m| + next if m.name != "IRB::Context" and + /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name + candidates.concat m.instance_methods(false) + } + candidates.sort! + candidates.uniq! + end + #identify_type( receiver ) + select_message(receiver, message, candidates) + + #when /^((\.?[^.]+)+)\.([^.]*)\(\s*\)*$/ + #function call + #obj = $1 + #func = $3 + + when /^\.([^.]*)$/ + # unknown(maybe String) + + receiver = "" + message = Regexp.quote($1) + + candidates = String.instance_methods(true) + select_message(receiver, message, candidates) + + else + candidates = eval("self.class.constants") + + (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/) + end + + #print candidates + if message != nil && message.length > 0 + rexp = '^%s' % message.downcase + candidates.delete_if do |c| + c.downcase.match( rexp ) + $~ == nil + end + end + + outp = "" + # tags = VIM::evaluate("taglist('^%s$')" % + (candidates-Object.instance_methods).each { |c| outp += "{'word':'%s','item':'%s'}," % [ c, c ] } + outp.sub!(/,$/, '') + VIM::command("let g:rbcomplete_completions = [%s]" % outp) +end + + +def select_message(receiver, message, candidates) + candidates.grep(/^#{message}/).collect do |e| + case e + when /^[a-zA-Z_]/ + receiver + "." + e + when /^[0-9]/ + when *Operators + #receiver + " " + e + end + end + candidates.delete_if { |x| x == nil } + candidates.uniq! + candidates.sort! +end +RUBYEOF +endfunction + +call s:DefRuby() +" vim: set et ts=4: |