Module: RackConsole::AppHelpers

Defined in:
lib/rack_console/app_helpers.rb

Defined Under Namespace

Classes: MockMethod

Instance Method Summary collapse

Instance Method Details

#ansi2html(ansi) ⇒ Object



424
425
426
# File 'lib/rack_console/app_helpers.rb', line 424

def ansi2html ansi
  Ansi2Html.new.convert(ansi, '')
end

#console!Object



43
44
45
46
47
48
49
# File 'lib/rack_console/app_helpers.rb', line 43

def console!
  if has_console_access?
    haml :console, locals: locals, layout: layout
  else
    raise "not authorized"
  end
end

#const_get_safe(m, name) ⇒ Object



169
170
171
172
173
# File 'lib/rack_console/app_helpers.rb', line 169

def const_get_safe m, name
  m.const_get(name)
rescue Object
  "ERROR: #{$!.inspect}"
end

#css_dirObject



37
38
39
# File 'lib/rack_console/app_helpers.rb', line 37

def css_dir
  config[:css_dir]
end

#e(text) ⇒ Object



300
301
302
# File 'lib/rack_console/app_helpers.rb', line 300

def e(text)
  Rack::Utils.escape(text.to_s)
end

#evaluate_expr!Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/rack_console/app_helpers.rb', line 51

def evaluate_expr!
  result_capture! do
    @stdin  = StringIO.new('')
    @stdout = StringIO.new('')
    @stderr = StringIO.new('')
    @result_ok = false
    @expr = (params[:expr] || '').strip
    unless @expr.blank?
      @result_evaled = true
      Timeout.timeout(30) do
        _stdin, _stdout, _stderr = $stdin, $stdout, $stderr
        $stdin, $stdout, $stderr = @stdin, @stdout, @stderr
        begin
          expr_str = "begin; #{@expr} \n; end"
          @result = eval(expr_str)
          @result_ok = true
        ensure
          $stdin, $stdout, $stderr = _stdin, _stdout, _stderr
        end
      end
    end
  end
end

#evaluate_method!Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/rack_console/app_helpers.rb', line 91

def evaluate_method!
  evaluate_expr!
  if @result_ok && @result.is_a?(Module)
    result_capture! do
      @module = @result
      @method_name = params[:name]
      @method_kind = params[:kind].to_s =~ /i/ ? :instance_method : :method
      @method = @module.send(@method_kind, @method_name) rescue nil
      unless @method
        @method = @module.send(:method, @method_name)
        @method_kind = :method
      end
      @method_source_location = @method.source_location
      @method_source = @method_source_location && SourceFile.new(@method_source_location).load!.narrow_to_block!
      @result = @method
    end
  end
end

#evaluate_methods!Object



110
111
112
113
114
115
# File 'lib/rack_console/app_helpers.rb', line 110

def evaluate_methods!
  @methods = nil
  result_capture! do
    @methods = methods_matching(params)
  end
end

#evaluate_module!Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rack_console/app_helpers.rb', line 75

def evaluate_module!
  evaluate_expr!
  if @result_ok && @result.is_a?(Module)
    result_capture! do
      @module = @result
      @ancestors = @module.ancestors.drop(1)
      if @is_class = @module.is_a?(Class)
        @superclass = @module.superclass
        @subclasses = @module.subclasses.sort_by{|c| c.name || ''}
      end
      @constants = @module.constants(false).sort.map{|n| [ n, const_get_safe(@module, n) ]}
      @methods = methods_for_module(@module)
    end
  end
end

#file_line_to_href(name, lineno = nil) ⇒ Object



277
278
279
280
281
282
283
# File 'lib/rack_console/app_helpers.rb', line 277

def file_line_to_href name, lineno = nil
  link = name.sub(%r{^/}, '-')
  link = link.split('/').map{|s| e s}.join('/')
  link = url_root("/file/#{link}")
  link << ":#{lineno}\##{lineno - 2}" if lineno
  link
end

#file_name_tag(str) ⇒ Object



345
346
347
# File 'lib/rack_console/app_helpers.rb', line 345

def file_name_tag str
  %Q{<span class="file_name">#{str}</span>}
end

#find_template(views, name, engine, &block) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/rack_console/app_helpers.rb', line 29

def find_template(views, name, engine, &block)
  views = config[:views] || views
  Array(views).each do |v|
    v = config[:views_default] if v == :default
    super(v, name, engine, &block)
  end
end

#format_as_terminal(str) ⇒ Object



415
416
417
418
419
420
421
422
# File 'lib/rack_console/app_helpers.rb', line 415

def format_as_terminal str
  str &&= str.to_s.force_encoding('UTF-8')
  if str.blank?
    %Q{<span class="none">NONE</span>}
  else
    ansi2html(str)
  end
end

#format_backtrace(line) ⇒ Object



361
362
363
364
365
366
367
368
369
370
# File 'lib/rack_console/app_helpers.rb', line 361

def format_backtrace line
  line = line.to_s
  html =
    if line =~ /^(.*):(\d+):(in .*)$/ && File.exist?($1)
      "#{format_source_location([$1, $2.to_i])}:#{h $3}"
    else
      file_name_tag(h line)
    end
  %Q{<span class="backtrace">#{html}</span>}
end

#format_method(m, kind, owner = nil) ⇒ Object



327
328
329
330
331
332
333
# File 'lib/rack_console/app_helpers.rb', line 327

def format_method m, kind, owner = nil
  owner ||= m.owner
  source_location = m.source_location
  source_location &&= source_location * ":"
  href = method_href(m, kind, owner)
  "<a href='#{href}' title='#{source_location}' class='method_name'>#{method_name_tag(h(m.name))}</a>"
end

#format_methods(name) ⇒ Object



340
341
342
343
# File 'lib/rack_console/app_helpers.rb', line 340

def format_methods name
  href = url_root("/methods/*/*/#{e name}")
  "<a href='#{href}' title='Other methods named #{h name.inspect}' class='method_name'>#{method_name_tag(h(name))}</a>"
end

#format_module(obj) ⇒ Object



312
313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'lib/rack_console/app_helpers.rb', line 312

def format_module obj
  return module_name_tag(h(obj.inspect)) unless obj && obj.name
  path = obj.name.to_s.split('::')
  result = ''
  name = ''; pre = ''
  path.each do | n |
    name << n
    href = url_root("/module/#{name}")
    result << "<a href='#{href}' class='module_name'>#{module_name_tag("#{pre}#{h n}")}</a>"
    name << '::'
    pre = '::'
  end
  module_name_tag(result)
end

#format_object(obj, inline = false) ⇒ Object



152
153
154
155
156
157
158
159
# File 'lib/rack_console/app_helpers.rb', line 152

def format_object obj, inline = false
  case obj
  when Module
    format_module obj
  else
    format_other obj, inline
  end
end

#format_other(obj, inline = false) ⇒ Object



161
162
163
164
165
166
167
# File 'lib/rack_console/app_helpers.rb', line 161

def format_other obj, inline = false
  if inline
    literal_tag(h(limit_string(safe_format(obj), 80)))
  else
    safe_format_structured(obj)
  end
end

#format_source_location(source_location, meth = nil, kind = nil, owner = nil) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/rack_console/app_helpers.rb', line 175

def format_source_location source_location, meth = nil, kind = nil, owner = nil
  file, line = source_location
  if file
    "<a href='#{file_line_to_href file, line}' class='file_name'>#{file_name_tag("#{file}:#{line}")}</a>"
  else
    if meth
      # Assume meth is Ruby Core and link to rdocs on ruby-doc.org.
      name = meth.name
      owner ||= meth.owner
      owner_name = (owner.name || '').gsub('::', '/')
      kind ||= (owner.instance_method(name) rescue nil) ? :i : :c
      a_name = name.to_s.gsub(/([^a-z0-9_])/i){|m| "-%X" % [ m.ord ]}
      a_name.sub!(/^-/, '')
      a_name = "method-#{kind}-#{a_name}"
      ruby_core_link = "http://www.ruby-doc.org/core-#{RUBY_VERSION}/#{owner_name}.html\##{a_name}"
      "<a href='#{ruby_core_link}' class='ruby_core_doc'>#{h ruby_core_link}</a>"
    else
      "NONE"
    end
  end
end

#h(text) ⇒ Object



296
297
298
# File 'lib/rack_console/app_helpers.rb', line 296

def h(text)
  Rack::Utils.escape_html(text.to_s)
end

#has_console_access?Boolean

Returns:

  • (Boolean)


9
10
11
# File 'lib/rack_console/app_helpers.rb', line 9

def has_console_access?
  true
end

#has_file_access?(file) ⇒ Boolean

Returns:

  • (Boolean)


13
14
15
# File 'lib/rack_console/app_helpers.rb', line 13

def has_file_access? file
  ! ! (file != '(eval)' && $".include?(file))
end

#href_to_file_line(path) ⇒ Object



285
286
287
288
289
290
# File 'lib/rack_console/app_helpers.rb', line 285

def href_to_file_line path
  path.to_s =~ /^([^:]+)(:([^:]+))?/
  file, line = $1, $3
  file.sub!(/^-/, '/')
  [ file, line && line.to_i ]
end

#instance_method_names(owner) ⇒ Object



253
254
255
256
257
258
# File 'lib/rack_console/app_helpers.rb', line 253

def instance_method_names owner
  ( owner.instance_methods(false) |
    owner.private_instance_methods(false) |
    owner.protected_instance_methods(false)
    ).sort
end

#layoutObject



25
26
27
# File 'lib/rack_console/app_helpers.rb', line 25

def layout
  config[:layout] || :layout
end

#limit_string(text, len) ⇒ Object



304
305
306
307
308
309
310
# File 'lib/rack_console/app_helpers.rb', line 304

def limit_string(text, len)
  text = text.to_s
  if text.size > len
    text = text[0 .. len] + ' ...'
  end
  text
end

#literal_tag(str) ⇒ Object



357
358
359
# File 'lib/rack_console/app_helpers.rb', line 357

def literal_tag str
  %Q{<span class="literal">#{str}</span>}
end

#localsObject



21
22
23
# File 'lib/rack_console/app_helpers.rb', line 21

def locals
  @locals ||= { }
end

#match_pred(value, m = nil) ⇒ Object



213
214
215
216
217
218
219
220
# File 'lib/rack_console/app_helpers.rb', line 213

def match_pred value, m = nil
  if value != '*' && value != ''
    value = value.send(m) if m
  else
    value = nil
  end
  value
end

#method_href(m, kind, owner = nil) ⇒ Object



335
336
337
338
# File 'lib/rack_console/app_helpers.rb', line 335

def method_href m, kind, owner = nil
  owner ||= m.owner
  href = url_root("/method/#{owner.name}/#{e kind.to_s}/#{e m.name}")
end

#method_name_tag(str) ⇒ Object



353
354
355
# File 'lib/rack_console/app_helpers.rb', line 353

def method_name_tag str
  %Q{<span class="method_name">#{str}</span>}
end

#methods_for_module(owner, name_p = nil, kind_p = nil, seen = { }, to_methods = nil) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/rack_console/app_helpers.rb', line 222

def methods_for_module owner, name_p = nil, kind_p = nil, seen = { }, to_methods = nil
  methods = to_methods || [ ]
  kind = :i
  unless kind_p && kind_p != kind
    instance_method_names(owner).each do | name |
      next if name_p && name_p != (name = name.to_sym)
      if meth = (owner.instance_method(name) rescue nil) and key = [ owner, kind, name ] and ! seen[key]
        seen[key] = true
        methods << MockMethod.new(meth, name, kind, owner)
      end
    end
  end

  kind = :c
  unless kind_p && kind_p != kind
    singleton_method_names(owner).each do | name |
      next if name_p && name_p != (name = name.to_sym)
      if meth = (owner.singleton_method(name) rescue nil) and key = [ owner, kind, name ] and ! seen[key]
        seen[key] = true
        methods << MockMethod.new(meth, name, kind, owner)
      end
    end
  end
  sort_methods! methods unless to_methods
  methods
end

#methods_matching(params) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/rack_console/app_helpers.rb', line 197

def methods_matching params
  name_p  = match_pred(params[:name], :to_sym)
  kind_p  = match_pred(params[:kind], :to_sym)
  owner_p = match_pred(params[:owner])

  methods = [ ]
  seen = { }
  ObjectSpace.each_object(::Module) do | owner |
    next unless (owner.name rescue nil)
    next if owner_p && owner_p != owner.name
    methods_for_module(owner, name_p, kind_p, seen, methods)
  end
  sort_methods! methods
  methods
end

#module_name_tag(str) ⇒ Object



349
350
351
# File 'lib/rack_console/app_helpers.rb', line 349

def module_name_tag str
  %Q{<span class="module_name">#{str}</span>}
end

#prepare_file!Object



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/rack_console/app_helpers.rb', line 117

def prepare_file!
  path = params[:splat][0]
  file, line = href_to_file_line(path)
  result_capture! do
    unless has_file_access? file
      content_type 'text/plain'
      return "NOT A LOADABLE FILE"
    end
    @source_file = SourceFile.new([ file, line ]).load!
  end
end

#result_capture!Object



129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/rack_console/app_helpers.rb', line 129

def result_capture!
  @result_ok = false
  result = yield
  @result_ok = true
  result
rescue
  @error = $!
  @error_description = @error.inspect
ensure
  @result_extended = @result.singleton_class.included_modules rescue nil
  @result_class = @result.class.name
end

#safe_format(obj) ⇒ Object



404
405
406
# File 'lib/rack_console/app_helpers.rb', line 404

def safe_format obj
  safe_pp(obj)
end

#safe_format_structured(obj) ⇒ Object



390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/rack_console/app_helpers.rb', line 390

def safe_format_structured obj
  begin
    if config[:awesome_print] && defined?(::AwesomePrint)
      ansi = obj.ai(indent: 2, html: false, index: false)
      ansi2html(ansi)
    else
      '<pre>' << wrap_lines(safe_pp(obj)) << '</pre>'
    end
  rescue
    STDERR.puts "  #{$!.inspect}: falling back to #inspect for #{obj.class}\n  #{$!.backtrace * "\n  "}"
    '<pre>' << wrap_lines(obj.inspect) << '</pre>'
  end
end

#safe_pp(obj) ⇒ Object



408
409
410
411
412
413
# File 'lib/rack_console/app_helpers.rb', line 408

def safe_pp obj
  ::PP.pp(obj, '')
rescue
  STDERR.puts "  #{$!.inspect}: falling back to #inspect for #{obj.class}\n  #{$!.backtrace * "\n  "}"
  obj.inspect
end

#server_infoObject



142
143
144
145
146
147
148
149
150
# File 'lib/rack_console/app_helpers.rb', line 142

def server_info
  thr = Thread.current
  (config[:server_info] || { }).merge(
    host: Socket.gethostname,
    pid: Process.pid,
    ppid: Process.ppid,
    thread: thr[:name] || thr.object_id,
  )
end

#singleton_method_names(owner) ⇒ Object



260
261
262
# File 'lib/rack_console/app_helpers.rb', line 260

def singleton_method_names owner
  owner.singleton_methods(false)
end

#sort_methods!(methods) ⇒ Object



249
250
251
# File 'lib/rack_console/app_helpers.rb', line 249

def sort_methods! methods
  methods.sort_by!{|x| [ x.owner.to_s, x.kind, x.name ]}
end

#source_file(source_location) ⇒ Object



292
293
294
# File 'lib/rack_console/app_helpers.rb', line 292

def source_file source_location
  source_location && SourceFile.new(source_location).load!
end

#url_root(url) ⇒ Object



17
18
19
# File 'lib/rack_console/app_helpers.rb', line 17

def url_root url
  "#{config[:url_root_prefix]}#{url}"
end

#wrap_line(str, width = 80) ⇒ Object



378
379
380
381
382
383
384
385
386
387
388
# File 'lib/rack_console/app_helpers.rb', line 378

def wrap_line str, width = 80
  str = str.to_s
  out = ''
  pos = 0
  while pos < str.size
    out << h(str[pos, width])
    pos += width
    out << "&nbsp;\u21B5\n" if pos < str.size
  end
  out
end

#wrap_lines(str, width = 80) ⇒ Object



372
373
374
375
376
# File 'lib/rack_console/app_helpers.rb', line 372

def wrap_lines str, width = 80
  str.to_s.split("\n").map do | line |
    wrap_line line, width
  end * "\n"
end