code_buddy 0.0.6 → 0.0.7
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/.gitignore +6 -0
- data/Gemfile +5 -0
- data/History.md +10 -0
- data/Rakefile +6 -1
- data/code_buddy.gemspec +4 -1
- data/features/rails2_app.feature +21 -0
- data/features/rails3_app.feature +21 -0
- data/features/sinatra.feature +15 -0
- data/features/step_definitions/rails_setup_steps.rb +68 -0
- data/features/support/env.rb +9 -0
- data/features/templates/rails_exception.feature.template +8 -0
- data/features/templates/sinatra_env.rb.template +22 -0
- data/features/templates/sinatra_homepage.feature.template +6 -0
- data/features/templates/sinatra_paths.rb.template +31 -0
- data/lib/code_buddy.rb +3 -2
- data/lib/code_buddy/app.rb +10 -6
- data/lib/code_buddy/middleware.rb +1 -1
- data/lib/code_buddy/public/javascripts/code_buddy.js +114 -53
- data/lib/code_buddy/public/javascripts/jquery.hotkeys.js +99 -0
- data/lib/code_buddy/public/stylesheets/code_buddy.css +4 -0
- data/lib/code_buddy/rails2/monkey_patch_action_controller.rb +2 -0
- data/lib/code_buddy/rails3/railtie.rb +3 -0
- data/lib/code_buddy/stack.rb +11 -7
- data/lib/code_buddy/stack_frame.rb +11 -0
- data/lib/code_buddy/version.rb +1 -1
- data/lib/code_buddy/views/header.erb +1 -0
- data/lib/code_buddy/views/index.erb +1 -6
- metadata +75 -5
- data/Gemfile.lock +0 -44
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/History.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
## Code Buddy release history
|
2
|
+
|
3
|
+
### 0.0.7 / 2011-01-04
|
4
|
+
|
5
|
+
[full changelog](https://github.com/patshaughnessy/code_buddy/compare/v0.0.6...v0.0.7)
|
6
|
+
|
7
|
+
* Bug fix: Handles stack traces from haml files
|
8
|
+
* 'e' opens an editor to current file (mvim and mate only based on EDITOR environment variable)
|
9
|
+
* 'h' show/hide code window
|
10
|
+
* Added some cucumber features so we know it works
|
data/Rakefile
CHANGED
@@ -3,8 +3,13 @@ Bundler::GemHelper.install_tasks
|
|
3
3
|
|
4
4
|
require 'rspec/core'
|
5
5
|
require 'rspec/core/rake_task'
|
6
|
+
require 'cucumber/rake/task'
|
7
|
+
|
6
8
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
7
9
|
spec.pattern = FileList['spec/**/*_spec.rb']
|
8
10
|
end
|
9
11
|
|
10
|
-
task :default => :spec
|
12
|
+
task :default => [:spec, :cucumber]
|
13
|
+
|
14
|
+
Cucumber::Rake::Task.new(:cucumber)
|
15
|
+
|
data/code_buddy.gemspec
CHANGED
@@ -27,5 +27,8 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency 'rake', '~> 0.8.7'
|
28
28
|
s.add_development_dependency 'rspec', '~> 2.2.0'
|
29
29
|
s.add_development_dependency 'mocha', '~> 0.9.10'
|
30
|
-
|
30
|
+
s.add_development_dependency 'cucumber', '~> 0.9.4'
|
31
|
+
s.add_development_dependency 'aruba', '~> 0.2.2'
|
32
|
+
# s.add_development_dependency 'capybara'
|
33
|
+
# s.add_development_dependency 'akephalos'
|
31
34
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Feature: Make sure CodeBuddy works with a Rails3 app
|
2
|
+
|
3
|
+
@announce
|
4
|
+
Scenario: See a stack trace with links
|
5
|
+
Given I have created a new Rails 2 app "new_rails2_app" with code_buddy
|
6
|
+
And I run "script/generate scaffold user"
|
7
|
+
And I overwrite "app/views/users/index.html.erb" with:
|
8
|
+
"""
|
9
|
+
<%= raise 'oops' %>
|
10
|
+
"""
|
11
|
+
And I run "rake db:migrate"
|
12
|
+
And I run "cp ../../../features/templates/rails_exception.feature.template features/rails_exception.feature"
|
13
|
+
And I am pending
|
14
|
+
And I run "rake cucumber"
|
15
|
+
Then it should pass with:
|
16
|
+
"""
|
17
|
+
1 scenario (1 passed)
|
18
|
+
4 steps (4 passed)
|
19
|
+
"""
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Feature: Make sure CodeBuddy works with a Rails3 app
|
2
|
+
|
3
|
+
@announce
|
4
|
+
Scenario: See a stack trace with links
|
5
|
+
Given I have created a new Rails 3 app "new_rails3_app" with code_buddy
|
6
|
+
And I run "rails generate scaffold users"
|
7
|
+
And I overwrite "app/views/users/index.html.erb" with:
|
8
|
+
"""
|
9
|
+
<%= raise 'oops' %>
|
10
|
+
"""
|
11
|
+
And I run "rake db:migrate"
|
12
|
+
And I enable show_exceptions in "config/environments/test.rb"
|
13
|
+
And I run "cp ../../../features/templates/rails_exception.feature.template features/rails_exception.feature"
|
14
|
+
And I run "bundle exec rake cucumber -v"
|
15
|
+
Then it should pass with:
|
16
|
+
"""
|
17
|
+
1 scenario (1 passed)
|
18
|
+
4 steps (4 passed)
|
19
|
+
"""
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Feature: Make sure CodeBuddy works when started as a sinatra app
|
2
|
+
|
3
|
+
@announce
|
4
|
+
Scenario: See a stack trace with links
|
5
|
+
Given I have created a test harness "sinatra_testing" for sinatra
|
6
|
+
And I run "cp ../../../features/templates/sinatra_homepage.feature.template features/sinatra_homepage.feature"
|
7
|
+
And I run "cp ../../../features/templates/sinatra_paths.rb.template features/support/paths.rb"
|
8
|
+
And I run "cucumber ."
|
9
|
+
Then it should pass with:
|
10
|
+
"""
|
11
|
+
1 scenario (1 passed)
|
12
|
+
2 steps (2 passed)
|
13
|
+
"""
|
14
|
+
|
15
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
Given /^I have created a new Rails 3 app "([^"]*)" with code_buddy$/ do |app_name|
|
2
|
+
steps <<-STEPS
|
3
|
+
Given I successfully run "rails new #{app_name}"
|
4
|
+
And I cd to "#{app_name}"
|
5
|
+
And I append to "Gemfile" with:
|
6
|
+
"""
|
7
|
+
gem 'rspec'
|
8
|
+
# gem 'akephalos', :git => 'https://github.com/thoughtbot/akephalos.git'
|
9
|
+
gem "cucumber-rails"
|
10
|
+
gem "capybara", '~> 0.3.8'
|
11
|
+
gem 'code_buddy', :path=>File.expand_path("../../../..", __FILE__)
|
12
|
+
"""
|
13
|
+
And I run "bundle install"
|
14
|
+
And I run "rails generate cucumber:install"
|
15
|
+
And I run "rake db:migrate"
|
16
|
+
STEPS
|
17
|
+
end
|
18
|
+
|
19
|
+
Given /^I have created a new Rails 2 app "([^"]*)" with code_buddy$/ do |app_name|
|
20
|
+
steps <<-STEPS
|
21
|
+
Given I run "gem install rails --version '=2.3.10'"
|
22
|
+
And I successfully run "rails _2.3.10_ #{app_name}"
|
23
|
+
And I cd to "#{app_name}"
|
24
|
+
And I replace "# Specify gems that this application depends on and have them installed with rake gems:install" in "config/environment.rb" with:
|
25
|
+
"""
|
26
|
+
# Specify gems that this application depends on and have them installed with rake gems:install
|
27
|
+
config.gem 'code_buddy'
|
28
|
+
config.middleware.use "CodeBuddy::ShowApp"
|
29
|
+
|
30
|
+
"""
|
31
|
+
And I run "mkdir vendor/gems"
|
32
|
+
And I run "ln -s #{File.expand_path("../../..", __FILE__)} vendor/gems/code_buddy-#{CodeBuddy::VERSION}"
|
33
|
+
And I run "script/generate cucumber"
|
34
|
+
And I run "rake db:migrate"
|
35
|
+
STEPS
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
Given /^I have created a test harness "([^"]*)" for sinatra$/ do |app_name|
|
40
|
+
steps <<-STEPS
|
41
|
+
Given I run "gem install cucumber-sinatra"
|
42
|
+
And I successfully run "mkdir #{app_name}"
|
43
|
+
And I cd to "#{app_name}"
|
44
|
+
And I run "cucumber-sinatra init CodeBuddy::App ../../../spec/spec_helper.rb"
|
45
|
+
STEPS
|
46
|
+
# And I run "cp #{File.expand_path("../templates/sinatra_env.rb.template", __FILE__)} features/support/env.rb"
|
47
|
+
end
|
48
|
+
|
49
|
+
Given /^I enable show_exceptions in "([^"]*)"$/ do |file_name|
|
50
|
+
# Given %Q[I replace "config.action_dispatch.show_exceptions = false" in "#{file_name}"], pystring #Cucumber::Ast::PyString.parse('config.action_dispatch.show_exceptions = true')
|
51
|
+
cmd = "sed s/'config.action_dispatch.show_exceptions = false'/'config.action_dispatch.show_exceptions = true'/ #{file_name}"
|
52
|
+
run_simple(cmd)
|
53
|
+
create_file(file_name, stdout_from(cmd), true)
|
54
|
+
end
|
55
|
+
|
56
|
+
Given /^I replace "([^"]*)" in "([^"]*)" with:$/ do |marker, file_name, new_text|
|
57
|
+
file = File.readlines(File.join(current_dir, file_name))
|
58
|
+
new_content = file.map do |line|
|
59
|
+
if line =~ Regexp.new(marker)
|
60
|
+
new_text
|
61
|
+
else
|
62
|
+
line
|
63
|
+
end
|
64
|
+
end
|
65
|
+
create_file(file_name, new_content, true)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Feature: Ensure CodeBuddy creates links in a Rails app
|
2
|
+
|
3
|
+
@allow-rescue
|
4
|
+
Scenario: Clicking on a line of a stack trace on the exception page
|
5
|
+
When I go to the users page
|
6
|
+
Then I should see "app/views/users/index.html.erb:1"
|
7
|
+
And I follow "app/views/users/index.html.erb:1"
|
8
|
+
Then I should see "CodeBuddySee your Ruby stack come alive"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Some minor edits after being
|
2
|
+
# Generated by cucumber-sinatra. (Wed Dec 22 13:32:12 -0500 2010)
|
3
|
+
|
4
|
+
ENV['RACK_ENV'] = 'test'
|
5
|
+
|
6
|
+
require File.join(File.dirname(__FILE__), '..', '..', '../../spec/spec_helper.rb')
|
7
|
+
|
8
|
+
require 'capybara'
|
9
|
+
require 'capybara/cucumber'
|
10
|
+
require 'rspec'
|
11
|
+
|
12
|
+
Capybara.app = CodeBuddy::App
|
13
|
+
|
14
|
+
class CodeBuddyWorld
|
15
|
+
include Capybara
|
16
|
+
include RSpec::Expectations
|
17
|
+
include RSpec::Matchers
|
18
|
+
end
|
19
|
+
|
20
|
+
World do
|
21
|
+
CodeBuddyWorld.new
|
22
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Taken from the cucumber-rails project.
|
2
|
+
|
3
|
+
module NavigationHelpers
|
4
|
+
# Maps a name to a path. Used by the
|
5
|
+
#
|
6
|
+
# When /^I go to (.+)$/ do |page_name|
|
7
|
+
#
|
8
|
+
# step definition in web_steps.rb
|
9
|
+
#
|
10
|
+
def path_to(page_name)
|
11
|
+
case page_name
|
12
|
+
|
13
|
+
when /the home page/
|
14
|
+
'/'
|
15
|
+
when /the new stack form page/
|
16
|
+
'/new'
|
17
|
+
|
18
|
+
# Add more mappings here.
|
19
|
+
# Here is an example that pulls values out of the Regexp:
|
20
|
+
#
|
21
|
+
# when /^(.*)'s profile page$/i
|
22
|
+
# user_profile_path(User.find_by_login($1))
|
23
|
+
|
24
|
+
else
|
25
|
+
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
|
26
|
+
"Now, go and add a mapping in #{__FILE__}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
World(NavigationHelpers)
|
data/lib/code_buddy.rb
CHANGED
@@ -9,8 +9,7 @@ require 'code_buddy/stack_frame'
|
|
9
9
|
require 'code_buddy/middleware'
|
10
10
|
|
11
11
|
begin
|
12
|
-
if Rails.env.development?
|
13
|
-
CodeBuddy::App.rails = true
|
12
|
+
if Rails.env.development? || Rails.env.test?
|
14
13
|
case Rails::VERSION::MAJOR
|
15
14
|
when 2:
|
16
15
|
require 'code_buddy/rails2/monkey_patch_action_controller'
|
@@ -21,3 +20,5 @@ begin
|
|
21
20
|
rescue NameError
|
22
21
|
nil
|
23
22
|
end
|
23
|
+
|
24
|
+
# CodeBuddy::App.run!
|
data/lib/code_buddy/app.rb
CHANGED
@@ -5,7 +5,7 @@ module CodeBuddy
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
attr_reader :stack
|
8
|
-
attr_accessor :
|
8
|
+
attr_accessor :path_prefix
|
9
9
|
|
10
10
|
def exception=(exception)
|
11
11
|
@stack = Stack.new(exception)
|
@@ -17,7 +17,7 @@ module CodeBuddy
|
|
17
17
|
end
|
18
18
|
|
19
19
|
get '/' do
|
20
|
-
redirect "#{
|
20
|
+
redirect "#{path_prefix}/stack"
|
21
21
|
end
|
22
22
|
|
23
23
|
get '/new' do
|
@@ -26,7 +26,7 @@ module CodeBuddy
|
|
26
26
|
|
27
27
|
post '/new' do
|
28
28
|
self.class.stack_string = params[:stack]
|
29
|
-
redirect "#{
|
29
|
+
redirect "#{path_prefix}/stack"
|
30
30
|
end
|
31
31
|
|
32
32
|
get '/stack' do
|
@@ -38,18 +38,22 @@ module CodeBuddy
|
|
38
38
|
display_stack(params[:selected].to_i)
|
39
39
|
end
|
40
40
|
|
41
|
+
get '/edit/:selected' do
|
42
|
+
self.class.stack.edit(params[:selected].to_i)
|
43
|
+
end
|
44
|
+
|
41
45
|
def display_stack(selected_param)
|
42
46
|
@stack = self.class.stack
|
43
47
|
if @stack
|
44
48
|
@stack.selected = selected_param
|
45
49
|
erb :index
|
46
50
|
else
|
47
|
-
redirect "#{
|
51
|
+
redirect "#{path_prefix}/new"
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
51
|
-
def
|
52
|
-
self.class.
|
55
|
+
def path_prefix
|
56
|
+
self.class.path_prefix
|
53
57
|
end
|
54
58
|
|
55
59
|
end
|
@@ -1,16 +1,31 @@
|
|
1
|
-
var
|
1
|
+
var CodeBuddy = {
|
2
|
+
stack : null,
|
3
|
+
stackView : null,
|
4
|
+
backbone : {}
|
5
|
+
}
|
6
|
+
|
7
|
+
CodeBuddy.backbone.Address = Backbone.Model.extend({
|
2
8
|
selected: function() {
|
3
|
-
return stack.selectedAddress() == this
|
4
|
-
},
|
9
|
+
return CodeBuddy.stack.selectedAddress() == this
|
10
|
+
},
|
5
11
|
});
|
6
12
|
|
7
|
-
|
13
|
+
CodeBuddy.backbone.Addresses = Backbone.Collection.extend({
|
14
|
+
model:CodeBuddy.backbone.Address,
|
15
|
+
|
16
|
+
bookmarked: function() {
|
17
|
+
return this.select(function(address){
|
18
|
+
return address.get('bookmarked');
|
19
|
+
})
|
20
|
+
}
|
21
|
+
})
|
8
22
|
|
9
|
-
|
23
|
+
CodeBuddy.backbone.Stack = Backbone.Model.extend({
|
10
24
|
initialize: function() {
|
25
|
+
_.bindAll(this, 'toggleBookmark', 'selectNextBookmark')
|
11
26
|
this.bind('change:selected', this.selectionChanged);
|
12
27
|
this.set({
|
13
|
-
addresses: new Addresses(this.get('stack_frames'))
|
28
|
+
addresses: new CodeBuddy.backbone.Addresses(this.get('stack_frames'))
|
14
29
|
})
|
15
30
|
},
|
16
31
|
|
@@ -19,6 +34,14 @@ var Stack = Backbone.Model.extend({
|
|
19
34
|
this.set({ selected: newSelected })
|
20
35
|
}
|
21
36
|
},
|
37
|
+
|
38
|
+
selectPrevious: function() {
|
39
|
+
this.setSelection(this.get('selected') - 1)
|
40
|
+
},
|
41
|
+
|
42
|
+
selectNext: function() {
|
43
|
+
this.setSelection(this.get('selected') + 1)
|
44
|
+
},
|
22
45
|
|
23
46
|
addresses: function() {
|
24
47
|
return this.get('addresses')
|
@@ -30,100 +53,138 @@ var Stack = Backbone.Model.extend({
|
|
30
53
|
},
|
31
54
|
|
32
55
|
selectionChanged: function(x) {
|
33
|
-
this.updateSelectedAddress(x)
|
34
|
-
this.view.render()
|
35
|
-
},
|
36
|
-
|
37
|
-
updateSelectedAddress: function(x) {
|
38
56
|
this.addresses().at(x.previousAttributes().selected).view.render()
|
39
57
|
this.addresses().at(x.changedAttributes().selected).view.render()
|
40
|
-
|
58
|
+
this.view.render()
|
59
|
+
},
|
41
60
|
|
61
|
+
toggleBookmark: function() {
|
62
|
+
this.selectedAddress().set({bookmarked:!this.get('bookmarked')})
|
63
|
+
this.selectedAddress().view.render();
|
64
|
+
},
|
42
65
|
|
66
|
+
selectNextBookmark: function() {
|
67
|
+
var bookmarked = this.addresses().bookmarked();
|
68
|
+
var length = bookmarked.length;
|
69
|
+
var toSelect;
|
70
|
+
if(length > 0) {
|
71
|
+
var current = _.indexOf(bookmarked, this.selectedAddress())
|
72
|
+
if(current > -1 && current < length - 1) {
|
73
|
+
toSelect = bookmarked[current + 1]
|
74
|
+
} else {
|
75
|
+
toSelect = bookmarked[0]
|
76
|
+
}
|
77
|
+
return this.setSelection(toSelect.cid.substr(1)-1)
|
78
|
+
}
|
79
|
+
}
|
43
80
|
});
|
44
81
|
|
45
82
|
// ADDRESS VIEW - SELECTED ADDRESS IN BOLD
|
46
|
-
|
83
|
+
CodeBuddy.backbone.AddressView = Backbone.View.extend({
|
47
84
|
tagName: "li",
|
48
85
|
|
49
86
|
template: _.template("<span class='container'><%= path %>:<%= line%><span class='overlay'></span></span>"),
|
50
87
|
|
51
88
|
initialize: function() {
|
52
|
-
_.bindAll(this, 'render', 'close');
|
53
|
-
this.model.bind('change', this.render);
|
54
89
|
this.model.view = this;
|
55
90
|
},
|
56
91
|
|
57
92
|
events: {
|
58
|
-
click: "open"
|
93
|
+
click: "open",
|
94
|
+
dblclick: "toggleBookmark"
|
59
95
|
},
|
96
|
+
|
60
97
|
open: function() {
|
61
|
-
stack.set({selected: this.model.cid.substr(1)-1});
|
98
|
+
CodeBuddy.stack.set({selected: this.model.cid.substr(1)-1});
|
99
|
+
},
|
100
|
+
|
101
|
+
toggleBookmark: function() {
|
102
|
+
this.open();
|
103
|
+
CodeBuddy.stack.toggleBookmark();
|
62
104
|
},
|
63
105
|
|
64
106
|
render: function() {
|
107
|
+
$(this.el).removeClass('selected bookmarked')
|
108
|
+
|
65
109
|
var html = this.template(this.model.toJSON())
|
66
110
|
|
67
111
|
$(this.el).html(html);
|
68
112
|
if (this.model.selected()) {
|
69
113
|
$(this.el).addClass('selected')
|
70
|
-
}
|
71
|
-
|
114
|
+
}
|
115
|
+
if (this.model.get('bookmarked')) {
|
116
|
+
$(this.el).addClass('bookmarked')
|
72
117
|
}
|
73
118
|
return this;
|
74
119
|
}
|
75
120
|
})
|
76
121
|
|
77
122
|
// STACK VIEW - LOGIC FOR ASSIGNING EACH ADDRESS VIEW TO EACH LI TAG
|
78
|
-
|
123
|
+
CodeBuddy.backbone.StackView = Backbone.View.extend({
|
79
124
|
|
80
125
|
el: $("#stack"),
|
81
126
|
|
82
|
-
events: {
|
83
|
-
"keypress #stack" : "changeSelectionOnArrow"
|
84
|
-
},
|
85
|
-
|
86
127
|
initialize: function() {
|
87
|
-
_.bindAll(this, '
|
88
|
-
this.model.bind('change', this.render);
|
128
|
+
_.bindAll(this, 'selectNext', 'selectPrevious')
|
89
129
|
this.model.view = this;
|
90
|
-
|
91
130
|
this.model.get('addresses').each(this.addOneAddress);
|
92
131
|
},
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
} else {
|
116
|
-
return true
|
132
|
+
|
133
|
+
selectPrevious: function() {
|
134
|
+
this.model.selectPrevious();
|
135
|
+
this.ensureVisibility();
|
136
|
+
return false;
|
137
|
+
},
|
138
|
+
|
139
|
+
selectNext: function() {
|
140
|
+
this.model.selectNext();
|
141
|
+
this.ensureVisibility();
|
142
|
+
return false;
|
143
|
+
},
|
144
|
+
|
145
|
+
ensureVisibility: function() {
|
146
|
+
var offset = $(CodeBuddy.stack.selectedAddress().view.el).offset()
|
147
|
+
var windowHeight = $(window).height()
|
148
|
+
if (offset.top > windowHeight + $(window).scrollTop() - 10) {
|
149
|
+
// scroll down
|
150
|
+
$('html,body').animate({scrollTop: offset.top - 200}, 500);
|
151
|
+
} else if (offset.top < $(window).scrollTop() + 100) {
|
152
|
+
// scroll up
|
153
|
+
$('html,body').animate({scrollTop: offset.top - 500}, 500);
|
117
154
|
}
|
155
|
+
return false
|
118
156
|
},
|
119
157
|
|
120
158
|
addOneAddress: function(address, index) {
|
121
|
-
var view = new AddressView({model: address});
|
159
|
+
var view = new CodeBuddy.backbone.AddressView({model: address});
|
122
160
|
this.$("#stack").append(view.render().el);
|
123
161
|
},
|
124
162
|
|
125
163
|
render: function() {
|
126
164
|
$('#code').html(this.model.selectedAddress().get('code'))
|
165
|
+
},
|
166
|
+
|
167
|
+
toggleCodeWindow: function() {
|
168
|
+
$('#code').toggle()
|
169
|
+
},
|
170
|
+
|
171
|
+
editCode: function() {
|
172
|
+
$.get('../edit/' + CodeBuddy.stack.get('selected'))
|
127
173
|
}
|
174
|
+
})
|
128
175
|
|
129
|
-
|
176
|
+
CodeBuddy.setKeyBindings = function(){
|
177
|
+
$(document).bind('keydown', 'up', CodeBuddy.stackView.selectPrevious)
|
178
|
+
$(document).bind('keydown', 'down', CodeBuddy.stackView.selectNext)
|
179
|
+
$(document).bind('keydown', 'a', CodeBuddy.stack.toggleBookmark)
|
180
|
+
$(document).bind('keydown', 's', CodeBuddy.stack.selectNextBookmark)
|
181
|
+
$(document).bind('keydown', 'h', CodeBuddy.stackView.toggleCodeWindow)
|
182
|
+
$(document).bind('keydown', 'e', CodeBuddy.stackView.editCode)
|
183
|
+
}
|
184
|
+
|
185
|
+
CodeBuddy.setup = function(stackJson) {
|
186
|
+
this.stack = new this.backbone.Stack(stackJson);
|
187
|
+
this.stackView = new this.backbone.StackView({model: this.stack});
|
188
|
+
this.stackView.render();
|
189
|
+
this.setKeyBindings();
|
190
|
+
}
|
@@ -0,0 +1,99 @@
|
|
1
|
+
/*
|
2
|
+
* jQuery Hotkeys Plugin
|
3
|
+
* Copyright 2010, John Resig
|
4
|
+
* Dual licensed under the MIT or GPL Version 2 licenses.
|
5
|
+
*
|
6
|
+
* Based upon the plugin by Tzury Bar Yochay:
|
7
|
+
* http://github.com/tzuryby/hotkeys
|
8
|
+
*
|
9
|
+
* Original idea by:
|
10
|
+
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
|
11
|
+
*/
|
12
|
+
|
13
|
+
(function(jQuery){
|
14
|
+
|
15
|
+
jQuery.hotkeys = {
|
16
|
+
version: "0.8",
|
17
|
+
|
18
|
+
specialKeys: {
|
19
|
+
8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
|
20
|
+
20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
|
21
|
+
37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
|
22
|
+
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
|
23
|
+
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
|
24
|
+
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
|
25
|
+
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta"
|
26
|
+
},
|
27
|
+
|
28
|
+
shiftNums: {
|
29
|
+
"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
|
30
|
+
"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
|
31
|
+
".": ">", "/": "?", "\\": "|"
|
32
|
+
}
|
33
|
+
};
|
34
|
+
|
35
|
+
function keyHandler( handleObj ) {
|
36
|
+
// Only care when a possible input has been specified
|
37
|
+
if ( typeof handleObj.data !== "string" ) {
|
38
|
+
return;
|
39
|
+
}
|
40
|
+
|
41
|
+
var origHandler = handleObj.handler,
|
42
|
+
keys = handleObj.data.toLowerCase().split(" ");
|
43
|
+
|
44
|
+
handleObj.handler = function( event ) {
|
45
|
+
// Don't fire in text-accepting inputs that we didn't directly bind to
|
46
|
+
if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
|
47
|
+
event.target.type === "text") ) {
|
48
|
+
return;
|
49
|
+
}
|
50
|
+
|
51
|
+
// Keypress represents characters, not special keys
|
52
|
+
var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ],
|
53
|
+
character = String.fromCharCode( event.which ).toLowerCase(),
|
54
|
+
key, modif = "", possible = {};
|
55
|
+
|
56
|
+
// check combinations (alt|ctrl|shift+anything)
|
57
|
+
if ( event.altKey && special !== "alt" ) {
|
58
|
+
modif += "alt+";
|
59
|
+
}
|
60
|
+
|
61
|
+
if ( event.ctrlKey && special !== "ctrl" ) {
|
62
|
+
modif += "ctrl+";
|
63
|
+
}
|
64
|
+
|
65
|
+
// TODO: Need to make sure this works consistently across platforms
|
66
|
+
if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
|
67
|
+
modif += "meta+";
|
68
|
+
}
|
69
|
+
|
70
|
+
if ( event.shiftKey && special !== "shift" ) {
|
71
|
+
modif += "shift+";
|
72
|
+
}
|
73
|
+
|
74
|
+
if ( special ) {
|
75
|
+
possible[ modif + special ] = true;
|
76
|
+
|
77
|
+
} else {
|
78
|
+
possible[ modif + character ] = true;
|
79
|
+
possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
|
80
|
+
|
81
|
+
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
|
82
|
+
if ( modif === "shift+" ) {
|
83
|
+
possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
for ( var i = 0, l = keys.length; i < l; i++ ) {
|
88
|
+
if ( possible[ keys[i] ] ) {
|
89
|
+
return origHandler.apply( this, arguments );
|
90
|
+
}
|
91
|
+
}
|
92
|
+
};
|
93
|
+
}
|
94
|
+
|
95
|
+
jQuery.each([ "keydown", "keyup", "keypress" ], function() {
|
96
|
+
jQuery.event.special[ this ] = { add: keyHandler };
|
97
|
+
});
|
98
|
+
|
99
|
+
})( jQuery );
|
@@ -6,6 +6,7 @@ module CodeBuddy
|
|
6
6
|
app.middleware.insert_before CodeBuddy::ShowExceptions, CodeBuddy::ShowApp
|
7
7
|
end
|
8
8
|
end
|
9
|
+
CodeBuddy::App.path_prefix = '/code_buddy'
|
9
10
|
end
|
10
11
|
|
11
12
|
class ShowExceptions < ActionDispatch::ShowExceptions
|
@@ -20,3 +21,5 @@ module CodeBuddy
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
24
|
+
|
25
|
+
|
data/lib/code_buddy/stack.rb
CHANGED
@@ -5,15 +5,19 @@ module CodeBuddy
|
|
5
5
|
|
6
6
|
def initialize(exception_or_string)
|
7
7
|
if exception_or_string.is_a?(Exception)
|
8
|
-
|
9
|
-
|
10
|
-
StackFrame.new(string)
|
11
|
-
end
|
8
|
+
backtrace = exception_or_string.backtrace
|
9
|
+
backtrace = backtrace.first.split("\n") if backtrace.size == 1 #haml errors come through this way
|
12
10
|
else
|
13
|
-
|
14
|
-
StackFrame.new(string)
|
15
|
-
end
|
11
|
+
backtrace = exception_or_string
|
16
12
|
end
|
13
|
+
|
14
|
+
@stack_frames = backtrace.collect do |string|
|
15
|
+
StackFrame.new(string)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def edit(index)
|
20
|
+
@stack_frames[index].open_in_editor
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
@@ -39,5 +39,16 @@ module CodeBuddy
|
|
39
39
|
"<span class=\"coderay\">Unable to read file:\n \"#{@path}\"</span>"
|
40
40
|
end
|
41
41
|
end
|
42
|
+
|
43
|
+
def open_in_editor
|
44
|
+
case ENV['EDITOR']
|
45
|
+
when 'mate'
|
46
|
+
`mate #{path} -l #{line}`
|
47
|
+
when 'mvim'
|
48
|
+
`mvim +#{line} #{path}`
|
49
|
+
else
|
50
|
+
puts "Sorry unable to open the file for editing. Please set your environment variable to either mate or mvim 'export EDITOR=mate' and restart the server"
|
51
|
+
end
|
52
|
+
end
|
42
53
|
end
|
43
54
|
end
|
data/lib/code_buddy/version.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
<link href="<%= @static_file_prefix %>stylesheets/code_buddy.css" media="screen" rel="stylesheet" type="text/css" />
|
4
4
|
<link href="<%= @static_file_prefix %>stylesheets/coderay.css" media="screen" rel="stylesheet" type="text/css" />
|
5
5
|
<script src="<%= @static_file_prefix %>javascripts/jquery.js" type="text/javascript"></script>
|
6
|
+
<script src="<%= @static_file_prefix %>javascripts/jquery.hotkeys.js" type="text/javascript"></script>
|
6
7
|
<script src="<%= @static_file_prefix %>javascripts/underscore.js" type="text/javascript"></script>
|
7
8
|
<script src="<%= @static_file_prefix %>javascripts/backbone.js" type="text/javascript"></script>
|
8
9
|
</head>
|
@@ -14,12 +14,7 @@
|
|
14
14
|
<div id='code'></div>
|
15
15
|
<script src="<%= @static_file_prefix %>javascripts/code_buddy.js" type="text/javascript"></script>
|
16
16
|
<script>
|
17
|
-
|
18
|
-
var stackView = new StackView({model: stack});
|
19
|
-
stackView.render();
|
20
|
-
$(document).keydown(function(event) {
|
21
|
-
return stack.view.changeSelectionOnArrow(event)
|
22
|
-
})
|
17
|
+
CodeBuddy.setup(<%= @stack.to_json %>)
|
23
18
|
</script>
|
24
19
|
</body>
|
25
20
|
</html>
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: code_buddy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 17
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
9
|
+
- 7
|
10
|
+
version: 0.0.7
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Pat Shaughnessy, Alex Rothenberg, Daniel Higginbotham
|
@@ -14,16 +15,18 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
+
date: 2011-01-04 00:00:00 -05:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: rack
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
27
30
|
segments:
|
28
31
|
- 0
|
29
32
|
version: "0"
|
@@ -33,9 +36,11 @@ dependencies:
|
|
33
36
|
name: sinatra
|
34
37
|
prerelease: false
|
35
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
36
40
|
requirements:
|
37
41
|
- - ~>
|
38
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 19
|
39
44
|
segments:
|
40
45
|
- 1
|
41
46
|
- 1
|
@@ -47,9 +52,11 @@ dependencies:
|
|
47
52
|
name: json_pure
|
48
53
|
prerelease: false
|
49
54
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
50
56
|
requirements:
|
51
57
|
- - ~>
|
52
58
|
- !ruby/object:Gem::Version
|
59
|
+
hash: 11
|
53
60
|
segments:
|
54
61
|
- 1
|
55
62
|
- 4
|
@@ -61,9 +68,11 @@ dependencies:
|
|
61
68
|
name: coderay
|
62
69
|
prerelease: false
|
63
70
|
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
64
72
|
requirements:
|
65
73
|
- - ~>
|
66
74
|
- !ruby/object:Gem::Version
|
75
|
+
hash: 55
|
67
76
|
segments:
|
68
77
|
- 0
|
69
78
|
- 9
|
@@ -75,9 +84,11 @@ dependencies:
|
|
75
84
|
name: rake
|
76
85
|
prerelease: false
|
77
86
|
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
78
88
|
requirements:
|
79
89
|
- - ~>
|
80
90
|
- !ruby/object:Gem::Version
|
91
|
+
hash: 49
|
81
92
|
segments:
|
82
93
|
- 0
|
83
94
|
- 8
|
@@ -89,9 +100,11 @@ dependencies:
|
|
89
100
|
name: rspec
|
90
101
|
prerelease: false
|
91
102
|
requirement: &id006 !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
92
104
|
requirements:
|
93
105
|
- - ~>
|
94
106
|
- !ruby/object:Gem::Version
|
107
|
+
hash: 7
|
95
108
|
segments:
|
96
109
|
- 2
|
97
110
|
- 2
|
@@ -103,9 +116,11 @@ dependencies:
|
|
103
116
|
name: mocha
|
104
117
|
prerelease: false
|
105
118
|
requirement: &id007 !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
106
120
|
requirements:
|
107
121
|
- - ~>
|
108
122
|
- !ruby/object:Gem::Version
|
123
|
+
hash: 47
|
109
124
|
segments:
|
110
125
|
- 0
|
111
126
|
- 9
|
@@ -113,6 +128,38 @@ dependencies:
|
|
113
128
|
version: 0.9.10
|
114
129
|
type: :development
|
115
130
|
version_requirements: *id007
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: cucumber
|
133
|
+
prerelease: false
|
134
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ~>
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
hash: 51
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
- 9
|
143
|
+
- 4
|
144
|
+
version: 0.9.4
|
145
|
+
type: :development
|
146
|
+
version_requirements: *id008
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: aruba
|
149
|
+
prerelease: false
|
150
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ~>
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
hash: 19
|
156
|
+
segments:
|
157
|
+
- 0
|
158
|
+
- 2
|
159
|
+
- 2
|
160
|
+
version: 0.2.2
|
161
|
+
type: :development
|
162
|
+
version_requirements: *id009
|
116
163
|
description: See the Ruby code running in your app.
|
117
164
|
email:
|
118
165
|
- pat@patshaughnessy.net, alex@alexrothenberg.com, daniel@flyingmachinestudios.com
|
@@ -126,18 +173,28 @@ files:
|
|
126
173
|
- .gitignore
|
127
174
|
- .rvmrc
|
128
175
|
- Gemfile
|
129
|
-
-
|
176
|
+
- History.md
|
130
177
|
- LICENSE
|
131
178
|
- README.rdoc
|
132
179
|
- Rakefile
|
133
180
|
- bin/code_buddy
|
134
181
|
- code_buddy.gemspec
|
182
|
+
- features/rails2_app.feature
|
183
|
+
- features/rails3_app.feature
|
184
|
+
- features/sinatra.feature
|
185
|
+
- features/step_definitions/rails_setup_steps.rb
|
186
|
+
- features/support/env.rb
|
187
|
+
- features/templates/rails_exception.feature.template
|
188
|
+
- features/templates/sinatra_env.rb.template
|
189
|
+
- features/templates/sinatra_homepage.feature.template
|
190
|
+
- features/templates/sinatra_paths.rb.template
|
135
191
|
- lib/code_buddy.rb
|
136
192
|
- lib/code_buddy/app.rb
|
137
193
|
- lib/code_buddy/middleware.rb
|
138
194
|
- lib/code_buddy/public/images/buddy.jpeg
|
139
195
|
- lib/code_buddy/public/javascripts/backbone.js
|
140
196
|
- lib/code_buddy/public/javascripts/code_buddy.js
|
197
|
+
- lib/code_buddy/public/javascripts/jquery.hotkeys.js
|
141
198
|
- lib/code_buddy/public/javascripts/jquery.js
|
142
199
|
- lib/code_buddy/public/javascripts/underscore.js
|
143
200
|
- lib/code_buddy/public/stylesheets/code_buddy.css
|
@@ -182,27 +239,40 @@ rdoc_options: []
|
|
182
239
|
require_paths:
|
183
240
|
- lib
|
184
241
|
required_ruby_version: !ruby/object:Gem::Requirement
|
242
|
+
none: false
|
185
243
|
requirements:
|
186
244
|
- - ">="
|
187
245
|
- !ruby/object:Gem::Version
|
246
|
+
hash: 3
|
188
247
|
segments:
|
189
248
|
- 0
|
190
249
|
version: "0"
|
191
250
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
251
|
+
none: false
|
192
252
|
requirements:
|
193
253
|
- - ">="
|
194
254
|
- !ruby/object:Gem::Version
|
255
|
+
hash: 3
|
195
256
|
segments:
|
196
257
|
- 0
|
197
258
|
version: "0"
|
198
259
|
requirements: []
|
199
260
|
|
200
261
|
rubyforge_project: code_buddy
|
201
|
-
rubygems_version: 1.3.
|
262
|
+
rubygems_version: 1.3.7
|
202
263
|
signing_key:
|
203
264
|
specification_version: 3
|
204
265
|
summary: See the Ruby code running in your app.
|
205
266
|
test_files:
|
267
|
+
- features/rails2_app.feature
|
268
|
+
- features/rails3_app.feature
|
269
|
+
- features/sinatra.feature
|
270
|
+
- features/step_definitions/rails_setup_steps.rb
|
271
|
+
- features/support/env.rb
|
272
|
+
- features/templates/rails_exception.feature.template
|
273
|
+
- features/templates/sinatra_env.rb.template
|
274
|
+
- features/templates/sinatra_homepage.feature.template
|
275
|
+
- features/templates/sinatra_paths.rb.template
|
206
276
|
- spec/app_spec.rb
|
207
277
|
- spec/middleware_spec.rb
|
208
278
|
- spec/spec_helper.rb
|
data/Gemfile.lock
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
code_buddy (0.0.6)
|
5
|
-
coderay (~> 0.9.6)
|
6
|
-
json_pure (~> 1.4.6)
|
7
|
-
rack
|
8
|
-
sinatra (~> 1.1.0)
|
9
|
-
|
10
|
-
GEM
|
11
|
-
remote: http://rubygems.org/
|
12
|
-
specs:
|
13
|
-
coderay (0.9.6)
|
14
|
-
diff-lcs (1.1.2)
|
15
|
-
json_pure (1.4.6)
|
16
|
-
mocha (0.9.10)
|
17
|
-
rake
|
18
|
-
rack (1.2.1)
|
19
|
-
rake (0.8.7)
|
20
|
-
rspec (2.2.0)
|
21
|
-
rspec-core (~> 2.2)
|
22
|
-
rspec-expectations (~> 2.2)
|
23
|
-
rspec-mocks (~> 2.2)
|
24
|
-
rspec-core (2.2.1)
|
25
|
-
rspec-expectations (2.2.0)
|
26
|
-
diff-lcs (~> 1.1.2)
|
27
|
-
rspec-mocks (2.2.0)
|
28
|
-
sinatra (1.1.0)
|
29
|
-
rack (~> 1.1)
|
30
|
-
tilt (~> 1.1)
|
31
|
-
tilt (1.1)
|
32
|
-
|
33
|
-
PLATFORMS
|
34
|
-
ruby
|
35
|
-
|
36
|
-
DEPENDENCIES
|
37
|
-
code_buddy!
|
38
|
-
coderay (~> 0.9.6)
|
39
|
-
json_pure (~> 1.4.6)
|
40
|
-
mocha (~> 0.9.10)
|
41
|
-
rack
|
42
|
-
rake (~> 0.8.7)
|
43
|
-
rspec (~> 2.2.0)
|
44
|
-
sinatra (~> 1.1.0)
|