trace_viewer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest ADDED
@@ -0,0 +1,7 @@
1
+ Rakefile
2
+ lib/trace_viewer.rb
3
+ lib/trace_viewer/line_detail.rb
4
+ lib/views/index.html.haml
5
+ spec/spec_helper.rb
6
+ spec/trace_viewer/trace_viewer_spec.rb
7
+ Manifest
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('trace_viewer', '0.0.1') do |p|
6
+ p.description = "Launches your web browser to view the functions in a stack trace in chronological order"
7
+ p.url = "http://github.com/cj2/trace_viewer"
8
+ p.author = "Chris Young"
9
+ p.email = "beesucker @nospam@ gmail.com"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = []
12
+ end
@@ -0,0 +1,24 @@
1
+ module TraceViewer
2
+ class LineDetail
3
+ attr_accessor :filename, :line_number, :source, :function_node
4
+
5
+ def line_count
6
+ formatted_source.size
7
+ end
8
+
9
+ def formatted_source
10
+ @formatted_source ||= begin
11
+ if (source)
12
+ source = self.source.clone
13
+ source[0] =~ /^(\s+)/
14
+ leading_characters = $1 || ''
15
+ source.map {|line|
16
+ line ? line.sub(leading_characters, '') : nil
17
+ }
18
+ else
19
+ []
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,97 @@
1
+ require 'launchy'
2
+ require 'haml'
3
+ require 'redparse'
4
+ require 'trace_viewer/line_detail'
5
+
6
+ module TraceViewer
7
+ class << self
8
+ def run
9
+ trace = load_and_parse_trace
10
+ loaded_trace = map_trace_to_line_details(trace)
11
+ html = build_html(loaded_trace)
12
+ filename = store_html(html)
13
+ open_html(filename)
14
+ end
15
+
16
+ def open_html(filename)
17
+ Launchy::Browser.run(filename)
18
+ end
19
+
20
+ def store_html(html)
21
+ filename = File.join(Dir.pwd, "trace_viewer_#{Time.now.to_i}.html")
22
+ File.open(filename, "w") do |file|
23
+ file.puts html
24
+ end
25
+ filename
26
+ end
27
+
28
+ def build_html(trace)
29
+ template_name = File.join(File.dirname(__FILE__), "views", "index.html.haml")
30
+ template_contents = File.read(template_name)
31
+
32
+ engine = Haml::Engine.new(template_contents)
33
+ engine.render(Object.new, :trace => trace)
34
+ end
35
+
36
+ def load_and_parse_trace
37
+ trace_lines = filtered_trace
38
+ trace_lines.map do |line|
39
+ parse_trace_line(line)
40
+ end
41
+ end
42
+
43
+ def map_trace_to_line_details(parsed_trace)
44
+ parsed_trace.map do |line|
45
+ filename,line_number = line
46
+
47
+ function_node, source = load_function(filename, line_number)
48
+
49
+ detail = LineDetail.new
50
+ detail.filename = filename
51
+ detail.line_number = line_number
52
+ detail.source = source
53
+ detail.function_node = function_node
54
+
55
+ detail
56
+ end
57
+ end
58
+
59
+ def filtered_trace
60
+ caller.select {|line|
61
+ # line !~ /\/trace_viewer\// &&
62
+ line !~ /\/rspec/
63
+ }
64
+ end
65
+
66
+ def parse_trace_line(line)
67
+ path,line_number,function = line.split(':')
68
+ line_number = line_number.to_i
69
+ if (function)
70
+ [path,line_number]
71
+ else
72
+ []
73
+ end
74
+ end
75
+
76
+ def load_function(filename,line_number)
77
+ lines = File.read(filename)
78
+ parser=RedParse.new(lines)
79
+ tree=parser.parse
80
+ walk_tree(tree) do |function_node|
81
+ if (function_node.kind_of?(RedParse::MethodNode) && (line_number.between?(function_node.startline, function_node.endline)))
82
+ source = lines.split("\n").slice(function_node.startline-1, function_node.endline-function_node.startline+1)
83
+ return [function_node, source]
84
+ end
85
+ end
86
+ nil
87
+ end
88
+
89
+ def walk_tree(node,depth=0,&block)
90
+ return if node.nil? || !node.kind_of?(RedParse::Node)
91
+ node.each do |child|
92
+ yield child if child.kind_of?(RedParse::MethodNode)
93
+ walk_tree(child,depth+1,&block) unless depth >= 10
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,90 @@
1
+ %script(type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js")
2
+
3
+ :css
4
+ body {
5
+ font-size: 14px;
6
+ }
7
+ a {
8
+ text-decoration: none;
9
+ color: #000;
10
+ }
11
+ .clear { clear: both; }
12
+
13
+ #controls ul {
14
+ margin: 20px 0 20px 10px;
15
+ font-size: 16px;
16
+ list-style-type: none;
17
+ padding: 0px;
18
+ }
19
+ #controls li {
20
+ float: left; margin: 0 30px 10px 0; padding: 0;
21
+ }
22
+ .box, #controls {
23
+ margin: auto;
24
+ width: 1000px;
25
+ }
26
+ .box {
27
+ border: 1px dashed #000;
28
+ margin-bottom: 15px;
29
+ }
30
+ .filename {
31
+ padding: 5px 10px;
32
+ background-color: #eef;
33
+ }
34
+ .line_numbers {
35
+ float: left;
36
+ background-color: #eee;
37
+ }
38
+ .code, .line_numbers {
39
+ padding: 0px 10px;
40
+ }
41
+ .code {
42
+ overflow: hidden;
43
+ }
44
+
45
+ #controls
46
+ %ul
47
+ %li
48
+ %a#collapse_all{:href => '#collapse'} Collapse All
49
+ %li
50
+ %a#expand_all{:href => '#expand'} Expand All
51
+
52
+ .clear
53
+
54
+ - trace.each do |line_detail|
55
+ .box
56
+ .filename
57
+ = line_detail.filename
58
+ line
59
+ = line_detail.line_number
60
+
61
+ .line_numbers
62
+ %pre
63
+ - line_detail.line_count.times do |i|
64
+ - perform_highlight = line_detail.line_number - line_detail.function_node.startline == i
65
+ - if (perform_highlight)
66
+ %strong= line_detail.function_node.startline+i
67
+ - else
68
+ = line_detail.function_node.startline+i
69
+
70
+ .code
71
+ %a{:href => "txmt://open/?url=file://#{line_detail.filename}&line=#{line_detail.line_number}"}
72
+ %pre
73
+ - line_detail.formatted_source.each_with_index do |line,i|
74
+ - perform_highlight = line_detail.line_number - line_detail.function_node.startline == i
75
+ - if (perform_highlight)
76
+ %strong= line
77
+ - else
78
+ = line
79
+
80
+ :javascript
81
+ $("#expand_all").click(function() {
82
+ $(".filename").siblings().show();
83
+ })
84
+ $("#collapse_all").click(function() {
85
+ $(".filename").siblings().hide();
86
+ })
87
+ $(".filename").click(function() {
88
+ $(this).siblings().toggle();
89
+ });
90
+
@@ -0,0 +1,88 @@
1
+ unless $spec_helper_loaded
2
+ $spec_helper_loaded = true
3
+
4
+ $LOAD_PATH.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
5
+ SPEC_TMP_DIR = File.expand_path('tmp', File.dirname(__FILE__))
6
+ require 'spork'
7
+ require 'stringio'
8
+ require 'fileutils'
9
+ require 'rspec'
10
+ require 'trace_viewer'
11
+
12
+ RSpec.configure do |config|
13
+ config.before(:each) do
14
+ $test_stdout = StringIO.new
15
+ $test_stderr = StringIO.new
16
+ @current_dir = nil
17
+ end
18
+
19
+ config.after(:each) do
20
+ FileUtils.rm_rf(SPEC_TMP_DIR) if File.directory?(SPEC_TMP_DIR)
21
+
22
+ end
23
+
24
+ def create_file(filename, contents)
25
+ FileUtils.mkdir_p(SPEC_TMP_DIR) unless File.directory?(SPEC_TMP_DIR)
26
+
27
+ in_current_dir do
28
+ FileUtils.mkdir_p(File.dirname(filename))
29
+ File.open(filename, 'wb') { |f| f << contents }
30
+ end
31
+ end
32
+
33
+ def create_helper_file(test_framework = FakeFramework)
34
+ create_file(test_framework.helper_file, "# stub spec helper file")
35
+ end
36
+
37
+ def in_current_dir(&block)
38
+ Dir.chdir(current_dir, &block)
39
+ end
40
+
41
+ def current_dir
42
+ @current_dir ||= SPEC_TMP_DIR
43
+ end
44
+
45
+ def change_current_dir(sub_path)
46
+ @current_dir = File.expand_path(sub_path, SPEC_TMP_DIR)
47
+ end
48
+
49
+ def windows?
50
+ ENV['OS'] == 'Windows_NT'
51
+ end
52
+ end
53
+
54
+
55
+ module RSpec
56
+ module Matchers
57
+ class IncludeAStringLike
58
+ def initialize(substring_or_regex)
59
+ case substring_or_regex
60
+ when String
61
+ @regex = Regexp.new(Regexp.escape(substring_or_regex))
62
+ when Regexp
63
+ @regex = substring_or_regex
64
+ else
65
+ raise ArgumentError, "don't know what to do with the #{substring_or_regex.class} you provided"
66
+ end
67
+ end
68
+
69
+ def matches?(list_of_strings)
70
+ @list_of_strings = list_of_strings
71
+ @list_of_strings.any? { |s| s =~ @regex }
72
+ end
73
+ def failure_message
74
+ "#{@list_of_strings.inspect} expected to include a string like #{@regex.inspect}"
75
+ end
76
+ def negative_failure_message
77
+ "#{@list_of_strings.inspect} expected to not include a string like #{@regex.inspect}, but did"
78
+ end
79
+ end
80
+
81
+ def include_a_string_like(substring_or_regex)
82
+ IncludeAStringLike.new(substring_or_regex)
83
+ end
84
+ end
85
+ end
86
+
87
+ Dir.glob(File.dirname(__FILE__) + "/support/*.rb").each { |f| require(f) }
88
+ end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe TraceViewer do
4
+ describe "run" do
5
+ TraceViewer.run
6
+ end
7
+
8
+ describe "load_and_parse_trace" do
9
+ end
10
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{trace_viewer}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Chris Young"]
9
+ s.date = %q{2010-10-18}
10
+ s.description = %q{Launches your web browser to view the functions in a stack trace in chronological order}
11
+ s.email = %q{beesucker @nospam@ gmail.com}
12
+ s.extra_rdoc_files = ["lib/trace_viewer.rb", "lib/trace_viewer/line_detail.rb", "lib/views/index.html.haml"]
13
+ s.files = ["Rakefile", "lib/trace_viewer.rb", "lib/trace_viewer/line_detail.rb", "lib/views/index.html.haml", "spec/spec_helper.rb", "spec/trace_viewer/trace_viewer_spec.rb", "Manifest", "trace_viewer.gemspec"]
14
+ s.homepage = %q{http://github.com/cj2/trace_viewer}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Trace_viewer"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{trace_viewer}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Launches your web browser to view the functions in a stack trace in chronological order}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trace_viewer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Chris Young
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-18 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Launches your web browser to view the functions in a stack trace in chronological order
22
+ email: beesucker @nospam@ gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - lib/trace_viewer.rb
29
+ - lib/trace_viewer/line_detail.rb
30
+ - lib/views/index.html.haml
31
+ files:
32
+ - Rakefile
33
+ - lib/trace_viewer.rb
34
+ - lib/trace_viewer/line_detail.rb
35
+ - lib/views/index.html.haml
36
+ - spec/spec_helper.rb
37
+ - spec/trace_viewer/trace_viewer_spec.rb
38
+ - Manifest
39
+ - trace_viewer.gemspec
40
+ has_rdoc: true
41
+ homepage: http://github.com/cj2/trace_viewer
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --line-numbers
47
+ - --inline-source
48
+ - --title
49
+ - Trace_viewer
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 1
67
+ - 2
68
+ version: "1.2"
69
+ requirements: []
70
+
71
+ rubyforge_project: trace_viewer
72
+ rubygems_version: 1.3.7
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Launches your web browser to view the functions in a stack trace in chronological order
76
+ test_files: []
77
+