1" Vim completion script 2" Language: Ruby 3" Maintainer: Mark Guzman ( segfault AT hasno DOT info ) 4" Info: $Id$ 5" URL: http://vim-ruby.rubyforge.org 6" Anon CVS: See above site 7" Release Coordinator: Doug Kearns <[email protected]> 8" ---------------------------------------------------------------------------- 9" 10" Ruby IRB/Complete author: Keiju ISHITSUKA([email protected]) 11" ---------------------------------------------------------------------------- 12 13if !has('ruby') 14 echo "Error: Required vim compiled with +ruby" 15 finish 16endif 17 18if version < 700 19 echo "Error: Required vim >= 7.0" 20 finish 21endif 22 23func! GetRubyVarType(v) 24 let stopline = 1 25 let vtp = '' 26 let pos = getpos('.') 27 let [lnum,lcol] = searchpos('^\s*#\s*@var\s*'.a:v.'\>\s\+[^ \t]\+\s*$','nb',stopline) 28 if lnum != 0 && lcol != 0 29 call setpos('.',pos) 30 let str = getline(lnum) 31 let vtp = substitute(str,'^\s*#\s*@var\s*'.a:v.'\>\s\+\([^ \t]\+\)\s*$','\1','') 32 return vtp 33 endif 34 call setpos('.',pos) 35 let [lnum,lcol] = searchpos(''.a:v.'\>\s*[+\-*/]*=\s*\([^ \t]\+.\(now\|new\|open\|get_instance\)\>\|[\[{"'']\)','nb',stopline) 36 if lnum != 0 && lcol != 0 37 let str = matchstr(getline(lnum),'=\s*\([^ \t]\+.\(now\|new\|open\|get_instance\)\>\|[\[{"'']\)',lcol) 38 let str = substitute(str,'^=\s*','','') 39 call setpos('.',pos) 40 if str == '"' || str == '''' 41 return 'String' 42 elseif str == '[' 43 return 'Array' 44 elseif str == '{' 45 return 'Hash' 46 elseif strlen(str) > 4 47 let l = stridx(str,'.') 48 return str[0:l-1] 49 end 50 return '' 51 endif 52 call setpos('.',pos) 53 return '' 54endf 55 56function! rubycomplete#Complete(findstart, base) 57 "findstart = 1 when we need to get the text length 58 if a:findstart 59 let line = getline('.') 60 let idx = col('.') 61 while idx > 0 62 let idx -= 1 63 let c = line[idx-1] 64 if c =~ '\w' 65 continue 66 elseif ! c =~ '\.' 67 idx = -1 68 break 69 else 70 break 71 endif 72 endwhile 73 74 return idx 75 "findstart = 0 when we need to return the list of completions 76 else 77 execute "ruby get_completions('" . a:base . "')" 78 return g:rbcomplete_completions 79 endif 80endfunction 81 82 83function! s:DefRuby() 84ruby << RUBYEOF 85ReservedWords = [ 86 "BEGIN", "END", 87 "alias", "and", 88 "begin", "break", 89 "case", "class", 90 "def", "defined", "do", 91 "else", "elsif", "end", "ensure", 92 "false", "for", 93 "if", "in", 94 "module", 95 "next", "nil", "not", 96 "or", 97 "redo", "rescue", "retry", "return", 98 "self", "super", 99 "then", "true", 100 "undef", "unless", "until", 101 "when", "while", 102 "yield", 103 ] 104 105Operators = [ "%", "&", "*", "**", "+", "-", "/", 106 "<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>", 107 "[]", "[]=", "^", ] 108 109def identify_type(var) 110 @buf = VIM::Buffer.current 111 enum = @buf.line_number 112 snum = (enum-10).abs 113 nums = Range.new( snum, enum ) 114 regxs = '/.*(%s)\s*=(.*)/' % var 115 regx = Regexp.new( regxs ) 116 nums.each do |x| 117 ln = @buf[x] 118 #print $~ if regx.match( ln ) 119 end 120end 121 122def load_requires 123 @buf = VIM::Buffer.current 124 enum = @buf.line_number 125 nums = Range.new( 1, enum ) 126 nums.each do |x| 127 ln = @buf[x] 128 begin 129 eval( "require %s" % $1 ) if /.*require\s*(.*)$/.match( ln ) 130 rescue Exception 131 #ignore? 132 end 133 end 134end 135 136def get_completions(base) 137 load_requires 138 input = VIM::evaluate('expand("<cWORD>")') 139 input += base 140 message = nil 141 142 143 case input 144 when /^(\/[^\/]*\/)\.([^.]*)$/ 145 # Regexp 146 receiver = $1 147 message = Regexp.quote($2) 148 149 candidates = Regexp.instance_methods(true) 150 select_message(receiver, message, candidates) 151 152 when /^([^\]]*\])\.([^.]*)$/ 153 # Array 154 receiver = $1 155 message = Regexp.quote($2) 156 157 candidates = Array.instance_methods(true) 158 select_message(receiver, message, candidates) 159 160 when /^([^\}]*\})\.([^.]*)$/ 161 # Proc or Hash 162 receiver = $1 163 message = Regexp.quote($2) 164 165 candidates = Proc.instance_methods(true) | Hash.instance_methods(true) 166 select_message(receiver, message, candidates) 167 168 when /^(:[^:.]*)$/ 169 # Symbol 170 if Symbol.respond_to?(:all_symbols) 171 sym = $1 172 candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name} 173 candidates.grep(/^#{sym}/) 174 else 175 [] 176 end 177 178 when /^::([A-Z][^:\.\(]*)$/ 179 # Absolute Constant or class methods 180 receiver = $1 181 candidates = Object.constants 182 candidates.grep(/^#{receiver}/).collect{|e| "::" + e} 183 184 when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/ 185 # Constant or class methods 186 receiver = $1 187 message = Regexp.quote($4) 188 begin 189 candidates = eval("#{receiver}.constants | #{receiver}.methods") 190 rescue Exception 191 candidates = [] 192 end 193 candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e} 194 195 when /^(:[^:.]+)\.([^.]*)$/ 196 # Symbol 197 receiver = $1 198 message = Regexp.quote($2) 199 200 candidates = Symbol.instance_methods(true) 201 select_message(receiver, message, candidates) 202 203 when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/ 204 # Numeric 205 receiver = $1 206 message = Regexp.quote($4) 207 208 begin 209 candidates = eval(receiver).methods 210 rescue Exception 211 candidates 212 end 213 select_message(receiver, message, candidates) 214 215 when /^(\$[^.]*)$/ 216 candidates = global_variables.grep(Regexp.new(Regexp.quote($1))) 217 218# when /^(\$?(\.?[^.]+)+)\.([^.]*)$/ 219 when /^((\.?[^.]+)+)\.([^.]*)$/ 220 # variable 221 receiver = $1 222 message = Regexp.quote($3) 223 224 cv = eval("self.class.constants") 225 226 vartype = VIM::evaluate("GetRubyVarType('%s')" % receiver) 227 if vartype != '' 228 candidates = eval("#{vartype}.instance_methods") 229 elsif (cv).include?(receiver) 230 # foo.func and foo is local var. 231 candidates = eval("#{receiver}.methods") 232 elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver 233 # Foo::Bar.func 234 begin 235 candidates = eval("#{receiver}.methods") 236 rescue Exception 237 candidates = [] 238 end 239 else 240 # func1.func2 241 candidates = [] 242 ObjectSpace.each_object(Module){|m| 243 next if m.name != "IRB::Context" and 244 /^(IRB|SLex|RubyLex|RubyToken)/ =~ m.name 245 candidates.concat m.instance_methods(false) 246 } 247 candidates.sort! 248 candidates.uniq! 249 end 250 #identify_type( receiver ) 251 select_message(receiver, message, candidates) 252 253 #when /^((\.?[^.]+)+)\.([^.]*)\(\s*\)*$/ 254 #function call 255 #obj = $1 256 #func = $3 257 258 when /^\.([^.]*)$/ 259 # unknown(maybe String) 260 261 receiver = "" 262 message = Regexp.quote($1) 263 264 candidates = String.instance_methods(true) 265 select_message(receiver, message, candidates) 266 267 else 268 candidates = eval("self.class.constants") 269 270 (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/) 271 end 272 273 #print candidates 274 if message != nil && message.length > 0 275 rexp = '^%s' % message.downcase 276 candidates.delete_if do |c| 277 c.downcase.match( rexp ) 278 $~ == nil 279 end 280 end 281 282 outp = "" 283 # tags = VIM::evaluate("taglist('^%s$')" % 284 (candidates-Object.instance_methods).each { |c| outp += "{'word':'%s','item':'%s'}," % [ c, c ] } 285 outp.sub!(/,$/, '') 286 VIM::command("let g:rbcomplete_completions = [%s]" % outp) 287end 288 289 290def select_message(receiver, message, candidates) 291 candidates.grep(/^#{message}/).collect do |e| 292 case e 293 when /^[a-zA-Z_]/ 294 receiver + "." + e 295 when /^[0-9]/ 296 when *Operators 297 #receiver + " " + e 298 end 299 end 300 candidates.delete_if { |x| x == nil } 301 candidates.uniq! 302 candidates.sort! 303end 304RUBYEOF 305endfunction 306 307call s:DefRuby() 308" vim: set et ts=4: 309