Common routines for XMPCompletionFilter/XMPDocFilter
# File lib/rcodetools/completion.rb, line 181 def __magic_help_code(result, v, meth) code = <<-EOC #{result} = #{v}.method(#{meth}).inspect.match( %r[\\A#<(?:Unbound)?Method: (.*?)>\\Z] )[1].sub(/\\A.*?\\((.*?)\\)(.*)\\Z/){ "\#{$1}\#{$2}" }.sub(/#<Class:(.*?)>#/) { "\#{$1}." } #{result} = #{v}.to_s + ".new" if #{result} == 'Class#new' and #{v}.private_method_defined?(:initialize) #{result} = "Object#" + #{meth} if #{result} =~ /^Kernel#/ and Kernel.instance_methods(false).map{|x| x.to_s}.include? #{meth} #{result} EOC end
# File lib/rcodetools/completion.rb, line 62 def _handle_brackets(expr_orig, expr) [ %w[{ }], %w[( )], %w[ ]! ].each do |left, right| n_left = expr_orig.count(left) - expr.count(left) n_right = expr_orig.count(right) - expr.count(right) n = n_left - n_right @postfix << ";#{left}" * n if n >= 0 end end
# File lib/rcodetools/completion.rb, line 55 def _handle_do_end(right_stripped) right_stripped << "\n" n_do = right_stripped.scan(/[\s\)]do\s/).length n_end = right_stripped.scan(/\bend\b/).length @postfix = ";begin" * (n_do - n_end) end
# File lib/rcodetools/completion.rb, line 71 def _handle_keywords(expr_orig, column) %w[if unless while until for].each do |keyw| pos = expr_orig.index(/\b#{keyw}\b/) @postfix << ";begin" if pos and pos < column # if * xxx pos = expr_orig.index(/;\s*#{keyw}\b/) @postfix << ";begin" if pos and column < pos # * ; if xxx end end
# File lib/rcodetools/completion.rb, line 140 def add_BEGIN <<XXX BEGIN { class Object def method_missing(meth, *args, &block) # ignore NoMethodError end end } XXX end
# File lib/rcodetools/completion.rb, line 81 def aref_or_aset?(right_stripped, last_char) if last_char == [ case right_stripped when /\]\s*=/ then "[]=" when /\]/ then "[]" end end end
# File lib/rcodetools/completion.rb, line 118 def current_phrase(expr) paren_level = 0 start = 0 (expr.length-1).downto(0) do |i| c = expr[i,1] if c =~ /[\)\}\]]/ paren_level += 1 next end if paren_level > 0 next if c =~ /[, ]/ else break (start = i+1) if c =~ /[ ,\(\{\[]/ end if c =~ /[\(\{\[]/ paren_level -= 1 break (start = i+1) if paren_level < 0 end end expr[start..-1] end
# File lib/rcodetools/completion.rb, line 11 def fill_literal!(expr) [ "\"", "'", "`" ].each do |q| expr.gsub!(/#{q}(.+)#{q}/){ '"' + "x"*$1.length + '"' } end expr.gsub!(/(%([wWqQxrs])?(\W))(.+?)\3/){ percent = $2 == 'x' ? '%'+$3 : $1 # avoid executing shell command percent + "x"*$4.length + $3 } [ %w[( )], %w[{ }], %w[ ]!, %w[< >] ].each do |b,e| rb, re = [b,e].map{ |x| Regexp.quote(x)} expr.gsub!(/(%([wWqQxrs])?(#{rb}))(.+)#{re}/){ percent = $2 == 'x' ? '%'+$3 : $1 # avoid executing shell command percent + "x"*$4.length + e } end end
# File lib/rcodetools/completion.rb, line 177 def runtime_data(code, lineno, column=nil) runtime_data_with_class(code, lineno, column)[1] end
# File lib/rcodetools/completion.rb, line 154 def runtime_data_with_class(code, lineno, column=nil) newcode = code.to_a.enum_with_index.map{|line, i| i+1==lineno ? prepare_line(line.chomp, column) : line }.join newcode << add_BEGIN if @ignore_NoMethodError debugprint "newcode", newcode.gsub(/;/, "\n"), "-"*80 stdout, stderr = execute(newcode) output = stderr.readlines debugprint "stderr", output, "-"*80 output = output.reject{|x| /^-:[0-9]+: warning/.match(x)} runtime_data = extract_data(output) if exception = /^-:[0-9]+:.*/.match(output.join) raise NewCodeError, exception[0].chomp end begin dat = runtime_data.results[1][0] debugprint "dat = #{dat.inspect}" [dat[0], dat[1..-1].to_s] rescue raise RuntimeDataError, runtime_data.inspect end end
# File lib/rcodetools/completion.rb, line 33 def set_expr_and_postfix!(expr, column, ®exp) expr.extend ExpressionExtension @postfix = "" expr_orig = expr.clone column ||= expr.length last_char = expr[column-1] expr.replace expr[ regexp[column] ] debugprint "expr_orig=#{expr_orig}", "expr(sliced)=#{expr}" right_stripped = Regexp.last_match.post_match _handle_do_end right_stripped aref_or_aset = aref_or_aset? right_stripped, last_char debugprint "aref_or_aset=#{aref_or_aset.inspect}" set_last_word! expr, aref_or_aset fill_literal! expr_orig _handle_brackets expr_orig, expr expr << aref_or_aset if aref_or_aset _handle_keywords expr_orig, column debugprint "expr(processed)=#{expr}" expr end
# File lib/rcodetools/completion.rb, line 90 def set_last_word!(expr, aref_or_aset=nil) debugprint "expr(before set_last_word)=#{expr}" if aref_or_aset opchars = "" else opchars = expr.slice!(/\s*[#{OPERATOR_CHARS}]+$/) debugprint "expr(strip opchars)=#{expr}" end expr.replace(if expr =~ /[\"\\`]$/ # String operations "''" else fill_literal! expr phrase = current_phrase(expr) if aref_or_aset expr.eval_string = expr[0..-2] expr.meth = aref_or_aset elsif phrase.match( /^(.+)\.(.*)$/ ) expr.eval_string, expr.meth = $1, $2 elsif opchars != '' expr end debugprint "expr.eval_string=#{expr.eval_string}", "expr.meth=#{expr.meth}" phrase end << (opchars || '')) # ` font-lock hack debugprint "expr(after set_last_word)=#{expr}" end