trace_viewer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+