Module: Rcodetools::ProcessParticularLine

Included in:
XMPCompletionFilter, XMPDocFilter
Defined in:
lib/rcodetools/completion.rb

Overview

Common routines for XMPCompletionFilter/XMPDocFilter

Defined Under Namespace

Modules: ExpressionExtension Classes: NewCodeError, RuntimeDataError

Constant Summary collapse

OPERATOR_CHARS =
'\|^&<>=~\+\-\*\/%\['

Instance Method Summary collapse

Instance Method Details

#__magic_help_code(result, v, meth) ⇒ Object



181
182
183
184
185
186
187
188
# 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

#_handle_brackets(expr_orig, expr) ⇒ Object



62
63
64
65
66
67
68
69
# 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

#_handle_do_end(right_stripped) ⇒ Object



55
56
57
58
59
60
# 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

#_handle_keywords(expr_orig, column) ⇒ Object



71
72
73
74
75
76
77
78
79
# 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

#add_BEGINObject



140
141
142
143
144
145
146
147
148
149
150
# 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

#aref_or_aset?(right_stripped, last_char) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
84
85
86
87
88
# 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

#current_phrase(expr) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# 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

#fill_literal!(expr) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 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

#runtime_data(code, lineno, column = nil) ⇒ Object



177
178
179
# File 'lib/rcodetools/completion.rb', line 177

def runtime_data(code, lineno, column=nil)
  runtime_data_with_class(code, lineno, column)[1]
end

#runtime_data_with_class(code, lineno, column = nil) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# 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]+:.*/m.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

#set_expr_and_postfix!(expr, column, &regexp) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rcodetools/completion.rb', line 33

def set_expr_and_postfix!(expr, column, &regexp)
  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

#set_last_word!(expr, aref_or_aset = nil) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# 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