The attached patches update rubycomplete to match the vim-ruby version. This adds a few features and no longer defaults to loading code from the current buffer.
One patch handles the rubycomplete changes, the other updates the documentation to match the changed functionality. --mark -- sic transit gloria et adulescentia blog | http://blog.hasno.info/blog wiki | http://wiki.hasno.info
--- vim7\runtime\autoload\rubycomplete.vim Tue May 16 22:09:00 2006 +++ vim-ruby\autoload\rubycomplete.vim Mon Jun 19 13:10:24 2006 @@ -1,7 +1,7 @@ " Vim completion script " Language: Ruby " Maintainer: Mark Guzman <[EMAIL PROTECTED]> -" Info: $Id: rubycomplete.vim,v 1.5 2006/04/29 21:54:43 vimboss Exp $ +" Info: $Id: rubycomplete.vim,v 1.33 2006/06/19 17:10:24 segy Exp $ " URL: http://vim-ruby.rubyforge.org " Anon CVS: See above site " Release Coordinator: Doug Kearns <[EMAIL PROTECTED]> @@ -12,16 +12,12 @@ " {{{ requirement checks if !has('ruby') - echohl ErrorMsg - echo "Error: Required vim compiled with +ruby" - echohl None + s:ErrMsg( "Error: Required vim compiled with +ruby" ) finish endif if version < 700 - echohl ErrorMsg - echo "Error: Required vim >= 7.0" - echohl None + s:ErrMsg( "Error: Required vim >= 7.0" ) finish endif " }}} requirement checks @@ -34,21 +30,32 @@ let g:rubycomplete_classes_in_global = 0 endif +if !exists("g:rubycomplete_buffer_loading") + let g:rubycomplete_classes_in_global = 0 +endif + + " {{{ vim-side support functions -function! GetBufferRubyModule(name) - let [snum,enum] = GetBufferRubyEntity(a:name, "module") +function! s:ErrMsg(msg) + echohl ErrorMsg + echo a:msg + echohl None +endfunction + +function! s:GetBufferRubyModule(name) + let [snum,enum] = s:GetBufferRubyEntity(a:name, "module") return snum . '..' . enum endfunction -function! GetBufferRubyClass(name) - let [snum,enum] = GetBufferRubyEntity(a:name, "class") +function! s:GetBufferRubyClass(name) + let [snum,enum] = s:GetBufferRubyEntity(a:name, "class") return snum . '..' . enum endfunction -function! GetBufferRubySingletonMethods(name) +function! s:GetBufferRubySingletonMethods(name) endfunction -function! GetBufferRubyEntity( name, type ) +function! s:GetBufferRubyEntity( name, type ) let stopline = 1 let crex = '^\s*' . a:type . '\s*' . a:name . '\s*\(<\s*.*\s*\)\?\n*\(\(\s\|#\).*\n*\)*\n*\s*end$' let [lnum,lcol] = searchpos( crex, 'nbw') @@ -66,8 +73,8 @@ return [lnum,enum] endfunction -function! IsInClassDef() - let [snum,enum] = GetBufferRubyEntity( '.*', "class" ) +function! s:IsInClassDef() + let [snum,enum] = s:GetBufferRubyEntity( '.*', "class" ) let ret = 'nil' let pos = line('.') @@ -78,7 +85,7 @@ return ret endfunction -function! GetRubyVarType(v) +function! s:GetRubyVarType(v) let stopline = 1 let vtp = '' let pos = getpos('.') @@ -90,7 +97,7 @@ return vtp endif call setpos('.',pos) - if g:rubycomplete_rails == 1 && g:rubycomplete_rails_loaded == 1 + if exists('g:rubycomplete_rails') && g:rubycomplete_rails == 1 && s:rubycomplete_rails_loaded == 1 let ctors = '\(now\|new\|open\|get_instance\|find\|create\)' else let ctors = '\(now\|new\|open\|get_instance\)' @@ -199,7 +206,7 @@ end def load_buffer_class(name) - classdef = get_buffer_entity(name, 'GetBufferRubyClass("%s")') + classdef = get_buffer_entity(name, 's:GetBufferRubyClass("%s")') return if classdef == nil pare = /^\s*class\s*(.*)\s*<\s*(.*)\s*\n/.match( classdef ) @@ -208,17 +215,27 @@ mixre = /.*\n\s*include\s*(.*)\s*\n/.match( classdef ) load_buffer_module( $2 ) if mixre != nil - eval classdef + begin + eval classdef + rescue + VIM::evaluate( "s:ErrMsg( 'Problem loading class \"%s\", was it already completed?' )" % name ) + end end def load_buffer_module(name) - classdef = get_buffer_entity(name, 'GetBufferRubyModule("%s")') + classdef = get_buffer_entity(name, 's:GetBufferRubyModule("%s")') return if classdef == nil - eval classdef + begin + eval classdef + rescue + VIM::evaluate( "s:ErrMsg( 'Problem loading module \"%s\", was it already completed?' )" % name ) + end end def get_buffer_entity(name, vimfun) + loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading") + return nil if loading_allowed != '1' return nil if /(\"|\')+/.match( name ) buf = VIM::Buffer.current nums = eval( VIM::evaluate( vimfun % name ) ) @@ -241,14 +258,15 @@ if /(\"|\')+/.match( receiver ) "String" else - VIM::evaluate("GetRubyVarType('%s')" % receiver) + VIM::evaluate("s:GetRubyVarType('%s')" % receiver) end end def get_buffer_classes() # this will be a little expensive. - allow_aggressive_load = VIM::evaluate('g:rubycomplete_classes_in_global') - return [] if allow_aggressive_load != '1' + loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading") + allow_aggressive_load = VIM::evaluate("exists('g:rubycomplete_classes_in_global') && g:rubycomplete_classes_in_global") + return [] if allow_aggressive_load != '1' || loading_allowed != '1' buf = VIM::Buffer.current eob = buf.length @@ -265,7 +283,7 @@ end def load_rails() - allow_rails = VIM::evaluate('g:rubycomplete_rails') + allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails") return if allow_rails != '1' buf_path = VIM::evaluate('expand("%:p")') @@ -291,100 +309,119 @@ begin require bootfile require envfile - require 'console_app' - require 'console_with_helpers' - VIM::command('let g:rubycomplete_rails_loaded = 1') + begin + require 'console_app' + require 'console_with_helpers' + rescue + # 1.0 + end + Rails::Initializer.run + VIM::command('let s:rubycomplete_rails_loaded = 1') rescue - print "Error loading rails environment" + VIM::evaluate( "s:ErrMsg('Error loading rails environment')" ) end end end def get_rails_helpers - allow_rails = VIM::evaluate('g:rubycomplete_rails') - rails_loaded = VIM::evaluate('g:rubycomplete_rails_loaded') + allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails") + rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded') return [] if allow_rails != '1' || rails_loaded != '1' return RailsWords end +def add_rails_columns( cls ) + allow_rails = VIM::evaluate("exists('g:rubycomplete_rails') && g:rubycomplete_rails") + rails_loaded = VIM::evaluate('s:rubycomplete_rails_loaded') + return [] if allow_rails != '1' || rails_loaded != '1' + eval( "#{cls}.establish_connection" ) + return [] unless eval( "#{cls}.ancestors.include?(ActiveRecord::Base).to_s" ) + col = eval( "#{cls}.column_names" ) + return col if col + return [] +end + +def clean_sel(sel, msg) + sel.delete_if { |x| x == nil } + sel.uniq! + sel.grep(/^#{Regexp.quote(msg)}/) if msg != nil +end + def get_completions(base) - load_requires - load_rails + loading_allowed = VIM::evaluate("exists('g:rubycomplete_buffer_loading') && g:rubycomplete_buffer_loading") + if loading_allowed == '1' + load_requires + load_rails + end input = VIM::Buffer.current.line cpos = VIM::Window.current.cursor[1] - 1 - input = input[0..cpos] if cpos != 0 + input = input[0..cpos] input += base + input.sub!(/.*[ \t\n\"\\'`><=;|&{(]/, '') # Readline.basic_word_break_characters + input.sub!(/self\./, '') - rip = input.rindex(/\s/,cpos) - if rip - input = input[rip..input.length] - end - - asn = /^.*(\+|\-|\*|=|\(|\[)=?(\s*[A-Za-z0-9_:@.-]*)(\s*(\{|\+|\-|\*|\%|\/)?\s*).*/ - if asn.match(input) - input = $2 - end - - input.strip! message = nil receiver = nil - candidates = [] + methods = [] + variables = [] + classes = [] case input when /^(\/[^\/]*\/)\.([^.]*)$/ # Regexp receiver = $1 message = Regexp.quote($2) - candidates = Regexp.instance_methods(true) + methods = Regexp.instance_methods(true) when /^([^\]]*\])\.([^.]*)$/ # Array receiver = $1 message = Regexp.quote($2) - candidates = Array.instance_methods(true) + methods = Array.instance_methods(true) when /^([^\}]*\})\.([^.]*)$/ # Proc or Hash receiver = $1 message = Regexp.quote($2) - candidates = Proc.instance_methods(true) | Hash.instance_methods(true) + methods = Proc.instance_methods(true) | Hash.instance_methods(true) when /^(:[^:.]*)$/ # Symbol if Symbol.respond_to?(:all_symbols) receiver = $1 - candidates = Symbol.all_symbols.collect{|s| s.id2name} - candidates.delete_if { |c| c.match( /'/ ) } + message = $1.sub( /:/, '' ) + methods = Symbol.all_symbols.collect{|s| s.id2name} + methods.delete_if { |c| c.match( /'/ ) } end when /^::([A-Z][^:\.\(]*)$/ # Absolute Constant or class methods receiver = $1 - candidates = Object.constants - candidates.grep(/^#{receiver}/).collect{|e| "::" + e} + methods = Object.constants + methods.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") + methods = eval("#{receiver}.constants | #{receiver}.methods") rescue Exception - candidates = [] + methods = [] end - candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e} + methods.grep(/^#{message}/).collect{|e| receiver + "::" + e} when /^(:[^:.]+)\.([^.]*)$/ # Symbol receiver = $1 message = Regexp.quote($2) - candidates = Symbol.instance_methods(true) + methods = Symbol.instance_methods(true) when /^([0-9_]+(\.[0-9_]+)?(e[0-9]+)?)\.([^.]*)$/ # Numeric receiver = $1 message = Regexp.quote($4) begin - candidates = eval(receiver).methods + methods = eval(receiver).methods rescue Exception - candidates + methods = [] end when /^(\$[^.]*)$/ #global - candidates = global_variables.grep(Regexp.new(Regexp.quote($1))) + methods = global_variables.grep(Regexp.new(Regexp.quote($1))) when /^((\.?[^.]+)+)\.([^.]*)$/ # variable receiver = $1 @@ -397,44 +434,41 @@ load_buffer_class( vartype ) begin - candidates = eval("#{vartype}.instance_methods") + methods = eval("#{vartype}.instance_methods") + variables = eval("#{vartype}.instance_variables") rescue Exception - candidates = [] end elsif (cv).include?(receiver) # foo.func and foo is local var. - candidates = eval("#{receiver}.methods") + methods = eval("#{receiver}.methods") + vartype = receiver elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver + vartype = receiver # Foo::Bar.func begin - candidates = eval("#{receiver}.methods") + methods = 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) + methods.concat m.instance_methods(false) } end + variables += add_rails_columns( "#{vartype}" ) if vartype && vartype.length > 0 when /^\(?\s*[A-Za-z0-9:[EMAIL PROTECTED]/+*\(\)]+\.\.\.?[A-Za-z0-9:[EMAIL PROTECTED]/+*\(\)]+\s*\)?\.([^.]*)/ message = $1 - candidates = Range.instance_methods(true) - - when /^\[(\s*[A-Za-z0-9:[EMAIL PROTECTED]/+*\(\)\[\]\{\}.\'\"],?)*\].([^.]*)/ - message = $2 - candidates = Array.instance_methods(true) + methods = Range.instance_methods(true) when /^\.([^.]*)$/ # unknown(maybe String) message = Regexp.quote($1) - candidates = String.instance_methods(true) + methods = String.instance_methods(true) else - inclass = eval( VIM::evaluate("IsInClassDef()") ) + inclass = eval( VIM::evaluate("s:IsInClassDef()") ) if inclass != nil classdef = "%s\n" % VIM::Buffer.current[ inclass.min ] @@ -445,8 +479,9 @@ message = input load_buffer_class( receiver ) begin - candidates = eval( "#{receiver}.instance_methods" ) - candidates += get_rails_helpers + methods = eval( "#{receiver}.instance_methods" ) + methods += get_rails_helpers + variables += add_rails_columns( "#{receiver}" ) rescue Exception found = nil end @@ -454,25 +489,29 @@ end if inclass == nil || found == nil - candidates = eval("self.class.constants") - candidates += get_buffer_classes + classes = eval("self.class.constants") + classes += get_buffer_classes message = receiver = input end end - candidates.delete_if { |x| x == nil } - candidates.uniq! - candidates.sort! - candidates = candidates.grep(/^#{Regexp.quote(message)}/) if message != nil + methods = clean_sel( methods, message ) + methods = (methods-Object.instance_methods) + variables = clean_sel( variables, message ) + classes = clean_sel( classes, message ) + valid = [] + valid += methods.collect { |m| { :name => m, :type => 'f' } } + valid += variables.collect { |v| { :name => v, :type => 'v' } } + valid += classes.collect { |c| { :name => c, :type => 't' } } + valid.sort! { |x,y| x[:name] <=> y[:name] } outp = "" - valid = (candidates-Object.instance_methods) rg = 0..valid.length rg.step(150) do |x| stpos = 0+x enpos = 150+x - valid[stpos..enpos].each { |c| outp += "{'word':'%s','item':'%s'}," % [ c, c ] } + valid[stpos..enpos].each { |c| outp += "{'word':'%s','item':'%s','kind':'%s'}," % [ c[:name], c[:name], c[:type] ] } outp.sub!(/,$/, '') VIM::command("call extend(g:rubycomplete_completions, [%s])" % outp) @@ -484,7 +523,7 @@ RUBYEOF endfunction -let g:rubycomplete_rails_loaded = 0 +let s:rubycomplete_rails_loaded = 0 call s:DefRuby() -" vim:tw=78:sw=4:ts=8:et:ft=vim:norl: +" vim:tw=78:sw=4:ts=8:et:fdm=marker:ft=vim:norl:
--- vim7\runtime\doc\insert.txt.old Mon Jun 19 22:02:34 2006 +++ vim7\runtime\doc\insert.txt Mon Jun 19 22:03:44 2006 @@ -1390,8 +1390,10 @@ Notes: - Vim will load/evaluate code in order to provide completions. This may - cause some code execution, which may be a concern. - - In context 1 above, Vim can parse the entire buffer to add a list of + cause some code execution, which may be a concern. This is no longer + enabled by default, to enable this feature add > + let g:rubycomplete_buffer_loading = 1 +<- In context 1 above, Vim can parse the entire buffer to add a list of classes to the completion results. This feature is turned off by default, to enable it add > let g:rubycomplete_classes_in_global = 1