open_exception 0.2.0 → 0.2.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/README.md +44 -0
- data/VERSION +1 -1
- data/lib/open_exception.rb +5 -0
- data/lib/open_exception/growl_support.rb +13 -5
- data/lib/open_exception/open_exception.rb +41 -24
- data/lib/open_exception/rails.rb +1 -1
- data/open_exception.gemspec +4 -8
- data/spec/open_exception_spec.rb +6 -6
- metadata +5 -8
- data/README.rdoc +0 -17
- data/init.rb +0 -1
- data/rails/init.rb +0 -1
- data/test_data/raiser.rb +0 -25
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
open_exception
|
2
|
+
==============
|
3
|
+
|
4
|
+
open_exception opens an exception in your favorite editor when developing locally. It
|
5
|
+
works by parsing the backtrace, and opening the offending file at the offending line
|
6
|
+
in your favorite editor (assuming your favorite editor supports remote open commands).
|
7
|
+
|
8
|
+
You can add filters that allow you to ignore some exceptions, and filters that allow you
|
9
|
+
to scope the backtrace search. The backtrace scoping is useful for opening the last call
|
10
|
+
in your application code when the exception occurs in a framework or lib.
|
11
|
+
|
12
|
+
If you are on MacOSX and have the [growl gem](http://rubygems.org/gems/growl) installed,
|
13
|
+
you will get a growl notification with the exception message when the file is opened.
|
14
|
+
|
15
|
+
Configuration
|
16
|
+
-------------
|
17
|
+
|
18
|
+
To configure, pass a block to the configure method:
|
19
|
+
|
20
|
+
OpenException.configure do |oe|
|
21
|
+
oe.open_with = :emacs
|
22
|
+
end
|
23
|
+
|
24
|
+
Rails Integration
|
25
|
+
-----------------
|
26
|
+
|
27
|
+
auto filter
|
28
|
+
|
29
|
+
Standalone/Other Frameworks
|
30
|
+
---------------------------
|
31
|
+
|
32
|
+
|
33
|
+
Note on Patches/Pull Requests
|
34
|
+
-----------------------------
|
35
|
+
|
36
|
+
* Fork the project.
|
37
|
+
* Make your feature addition or bug fix.
|
38
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
39
|
+
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
40
|
+
* Send me a pull request. Bonus points for topic branches.
|
41
|
+
|
42
|
+
== Copyright
|
43
|
+
|
44
|
+
Copyright (c) 2010 Tobias Crawley. See LICENSE for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.1
|
data/lib/open_exception.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/open_exception/open_exception"
|
2
2
|
require File.dirname(__FILE__) + "/open_exception/rails" if defined?(ActionController)
|
3
3
|
|
4
|
+
init_message = "** open_extension initialized "
|
5
|
+
|
4
6
|
begin
|
5
7
|
require 'growl'
|
6
8
|
require File.dirname(__FILE__) + "/open_exception/growl_support"
|
9
|
+
init_message << "with growl support"
|
7
10
|
rescue LoadError
|
8
11
|
#ignore
|
9
12
|
end
|
13
|
+
|
14
|
+
puts init_message
|
@@ -1,9 +1,17 @@
|
|
1
1
|
module OpenException
|
2
2
|
module GrowlSupport
|
3
|
+
def self.included(base)
|
4
|
+
if !base.instance_methods.include?(:open_without_growl)
|
5
|
+
base.send(:alias_method, :open_file_without_growl, :open_file)
|
6
|
+
base.send(:alias_method, :open_file, :open_file_with_growl)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
3
10
|
protected
|
4
|
-
def
|
5
|
-
|
6
|
-
|
11
|
+
def open_file_with_growl(file, line)
|
12
|
+
puts 'growl open file'
|
13
|
+
growl_notify(file, line) if File.readable?(file)
|
14
|
+
open_file_without_growl(file, line)
|
7
15
|
end
|
8
16
|
|
9
17
|
def growl_notify(file, line)
|
@@ -16,10 +24,10 @@ module OpenException
|
|
16
24
|
end
|
17
25
|
|
18
26
|
def growl_message(file, line)
|
19
|
-
msg = "
|
27
|
+
msg = "Exception: #{exception.message} at #{exception.backtrace.first}\nOpening #{file}:#{line}"
|
20
28
|
msg << " in #{options[:open_with]}" if options[:open_with].is_a?(Symbol)
|
21
29
|
end
|
22
30
|
end
|
23
31
|
end
|
24
32
|
|
25
|
-
OpenException::ExceptionOpener.send(:include, OpenException::GrowlSupport)
|
33
|
+
OpenException::ExceptionOpener.send(:include, OpenException::GrowlSupport)
|
@@ -1,10 +1,24 @@
|
|
1
1
|
module OpenException
|
2
|
+
|
3
|
+
EDITOR_COMMANDS = {
|
4
|
+
:emacs => '/usr/bin/emacsclient -n +{line} {file}',
|
5
|
+
:textmate => '/usr/local/bin/mate -a -d -l {line} {file}',
|
6
|
+
:macvim => '/usr/local/bin/mvim +{line} {file}'
|
7
|
+
}
|
2
8
|
|
9
|
+
DEFAULT_OPTIONS = {
|
10
|
+
:open_with => :emacs,
|
11
|
+
:exclusion_filters => [], #[ExceptionClass, lambda] # any can return/be true to exclude
|
12
|
+
:backtrace_line_filters => [] #[/regex/, lambda] # the first backtrace line that returns true is used
|
13
|
+
}
|
14
|
+
|
3
15
|
class << self
|
4
|
-
attr_writer :options
|
5
|
-
|
6
16
|
def options
|
7
|
-
@options ||=
|
17
|
+
@options ||= DEFAULT_OPTIONS.clone
|
18
|
+
end
|
19
|
+
|
20
|
+
def configure
|
21
|
+
yield Configurator.new(options)
|
8
22
|
end
|
9
23
|
|
10
24
|
def open(exception, options = { })
|
@@ -13,22 +27,12 @@ module OpenException
|
|
13
27
|
end
|
14
28
|
|
15
29
|
class ExceptionOpener
|
16
|
-
DEFAULT_OPTIONS = {
|
17
|
-
:open_with => :emacs,
|
18
|
-
:emacs_command => '/usr/bin/emacsclient -n +{line} {file}',
|
19
|
-
:textmate_command => '/usr/local/bin/mate -a -d -l {line} {file}',
|
20
|
-
:macvim_command => '/usr/local/bin/mvim +{line} {file}'
|
21
|
-
# :exclusion_filter => [ExceptionClass, lambda] # any can return/be
|
22
|
-
# true to exclude
|
23
|
-
# :backtrace_line_filter => [/regex/, lambda] # the first backtrace
|
24
|
-
# line that returns true is used
|
25
|
-
}
|
26
30
|
|
27
31
|
attr_accessor :options
|
28
32
|
|
29
33
|
def initialize(exception, options = {})
|
30
34
|
@exception = exception
|
31
|
-
@options =
|
35
|
+
@options = OpenException.options.merge(options)
|
32
36
|
end
|
33
37
|
|
34
38
|
def open
|
@@ -37,21 +41,21 @@ module OpenException
|
|
37
41
|
open_file(*file_and_line) if file_and_line
|
38
42
|
end
|
39
43
|
end
|
40
|
-
|
44
|
+
|
41
45
|
protected
|
42
46
|
attr_reader :exception
|
43
|
-
|
47
|
+
|
44
48
|
def extract_file_and_line
|
45
49
|
if exception.backtrace and
|
46
|
-
|
50
|
+
filter_backtrace(exception.backtrace) =~ /(.*?):(\d*)/
|
47
51
|
[$1, $2]
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
51
55
|
def filter_backtrace(backtrace)
|
52
|
-
if options[:
|
56
|
+
if !options[:backtrace_line_filters].empty?
|
53
57
|
backtrace.find do |line|
|
54
|
-
apply_backtrace_filter(options[:
|
58
|
+
apply_backtrace_filter(options[:backtrace_line_filters], line)
|
55
59
|
end
|
56
60
|
else
|
57
61
|
backtrace.first
|
@@ -67,10 +71,10 @@ module OpenException
|
|
67
71
|
line =~ filter
|
68
72
|
end
|
69
73
|
end
|
70
|
-
|
74
|
+
|
71
75
|
def exclude_exception?
|
72
|
-
if options[:
|
73
|
-
apply_exclusion_filter(options[:
|
76
|
+
if !options[:exclusion_filters].empty?
|
77
|
+
apply_exclusion_filter(options[:exclusion_filters])
|
74
78
|
end
|
75
79
|
end
|
76
80
|
|
@@ -83,7 +87,7 @@ module OpenException
|
|
83
87
|
exception.is_a?(filter)
|
84
88
|
end
|
85
89
|
end
|
86
|
-
|
90
|
+
|
87
91
|
def open_file(file_name, line_number)
|
88
92
|
if File.readable?(file_name)
|
89
93
|
cmd = open_command.gsub('{file}', file_name).gsub('{line}', line_number)
|
@@ -94,11 +98,24 @@ module OpenException
|
|
94
98
|
|
95
99
|
def open_command
|
96
100
|
if options[:open_with].is_a?(Symbol)
|
97
|
-
|
101
|
+
EDITOR_COMMANDS[options[:open_with]]
|
98
102
|
else
|
99
103
|
options[:open_with]
|
100
104
|
end
|
101
105
|
end
|
102
106
|
end
|
107
|
+
|
108
|
+
class Configurator
|
109
|
+
def initialize(options)
|
110
|
+
@options = options
|
111
|
+
end
|
103
112
|
|
113
|
+
def method_missing(method, arg = nil)
|
114
|
+
if method.to_s =~ /(.*?)=/
|
115
|
+
@options[$1.to_sym] = arg
|
116
|
+
else
|
117
|
+
@options[method]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
104
121
|
end
|
data/lib/open_exception/rails.rb
CHANGED
@@ -18,5 +18,5 @@ end
|
|
18
18
|
|
19
19
|
if !ActionController::Base.ancestors.include?(OpenException::ActionControllerExtensions)
|
20
20
|
ActionController::Base.send(:include, OpenException::ActionControllerExtensions)
|
21
|
-
OpenException.options[:
|
21
|
+
OpenException.options[:backtrace_line_filters] << %r{#{Rails.root}/(app|lib)}
|
22
22
|
end
|
data/open_exception.gemspec
CHANGED
@@ -5,35 +5,31 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{open_exception}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Tobias Crawley"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-26}
|
13
13
|
s.description = %q{}
|
14
14
|
s.email = %q{tcrawley@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
"README.
|
17
|
+
"README.md"
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
21
|
".gitignore",
|
22
22
|
"LICENSE",
|
23
|
-
"README.rdoc",
|
24
23
|
"Rakefile",
|
25
24
|
"VERSION",
|
26
|
-
"init.rb",
|
27
25
|
"lib/open_exception.rb",
|
28
26
|
"lib/open_exception/growl_support.rb",
|
29
27
|
"lib/open_exception/open_exception.rb",
|
30
28
|
"lib/open_exception/rails.rb",
|
31
29
|
"open_exception.gemspec",
|
32
|
-
"rails/init.rb",
|
33
30
|
"spec/open_exception_spec.rb",
|
34
31
|
"spec/spec.opts",
|
35
|
-
"spec/spec_helper.rb"
|
36
|
-
"test_data/raiser.rb"
|
32
|
+
"spec/spec_helper.rb"
|
37
33
|
]
|
38
34
|
s.homepage = %q{http://github.com/tobias/open_exception}
|
39
35
|
s.rdoc_options = ["--charset=UTF-8"]
|
data/spec/open_exception_spec.rb
CHANGED
@@ -9,19 +9,19 @@ describe "OpenException" do
|
|
9
9
|
|
10
10
|
it "should filter with a regex" do
|
11
11
|
@opener = opener(stub_exception,
|
12
|
-
:
|
12
|
+
:backtrace_line_filters => [/other_file/])
|
13
13
|
@opener.send(:extract_file_and_line).should == ["/some/other_file.rb", '22']
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should filter with a lambda" do
|
17
17
|
@opener = opener(stub_exception,
|
18
|
-
:
|
18
|
+
:backtrace_line_filters => [lambda { |line| line =~ /other_file/ }])
|
19
19
|
@opener.send(:extract_file_and_line).should == ["/some/other_file.rb", '22']
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should filter with an array of filters" do
|
23
23
|
@opener = opener(stub_exception,
|
24
|
-
:
|
24
|
+
:backtrace_line_filters => [/not gonna match/,
|
25
25
|
/other_file/])
|
26
26
|
@opener.send(:extract_file_and_line).should == ["/some/other_file.rb", '22']
|
27
27
|
end
|
@@ -50,19 +50,19 @@ describe "OpenException" do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should exclude based on exception class" do
|
53
|
-
@opener = opener(Exception.new, :
|
53
|
+
@opener = opener(Exception.new, :exclusion_filters => [Exception])
|
54
54
|
@opener.should_not_receive(:extract_file_and_line)
|
55
55
|
@opener.open
|
56
56
|
end
|
57
57
|
|
58
58
|
it "should exclude based on a lambda" do
|
59
|
-
@opener = opener(Exception.new, :
|
59
|
+
@opener = opener(Exception.new, :exclusion_filters => [lambda { |ex| true }])
|
60
60
|
@opener.should_not_receive(:extract_file_and_line)
|
61
61
|
@opener.open
|
62
62
|
end
|
63
63
|
|
64
64
|
it "should exclude based on an array of filters" do
|
65
|
-
@opener = opener(Exception.new, :
|
65
|
+
@opener = opener(Exception.new, :exclusion_filters => [StandardError, Exception])
|
66
66
|
@opener.should_not_receive(:extract_file_and_line)
|
67
67
|
@opener.open
|
68
68
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 1
|
9
|
+
version: 0.2.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Tobias Crawley
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-26 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -39,25 +39,22 @@ extensions: []
|
|
39
39
|
|
40
40
|
extra_rdoc_files:
|
41
41
|
- LICENSE
|
42
|
-
- README.
|
42
|
+
- README.md
|
43
43
|
files:
|
44
44
|
- .document
|
45
45
|
- .gitignore
|
46
46
|
- LICENSE
|
47
|
-
- README.rdoc
|
48
47
|
- Rakefile
|
49
48
|
- VERSION
|
50
|
-
- init.rb
|
51
49
|
- lib/open_exception.rb
|
52
50
|
- lib/open_exception/growl_support.rb
|
53
51
|
- lib/open_exception/open_exception.rb
|
54
52
|
- lib/open_exception/rails.rb
|
55
53
|
- open_exception.gemspec
|
56
|
-
- rails/init.rb
|
57
54
|
- spec/open_exception_spec.rb
|
58
55
|
- spec/spec.opts
|
59
56
|
- spec/spec_helper.rb
|
60
|
-
-
|
57
|
+
- README.md
|
61
58
|
has_rdoc: true
|
62
59
|
homepage: http://github.com/tobias/open_exception
|
63
60
|
licenses: []
|
data/README.rdoc
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
= open_exception
|
2
|
-
|
3
|
-
Description goes here.
|
4
|
-
|
5
|
-
== Note on Patches/Pull Requests
|
6
|
-
|
7
|
-
* Fork the project.
|
8
|
-
* Make your feature addition or bug fix.
|
9
|
-
* Add tests for it. This is important so I don't break it in a
|
10
|
-
future version unintentionally.
|
11
|
-
* Commit, do not mess with rakefile, version, or history.
|
12
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
13
|
-
* Send me a pull request. Bonus points for topic branches.
|
14
|
-
|
15
|
-
== Copyright
|
16
|
-
|
17
|
-
Copyright (c) 2010 Tobias Crawley. See LICENSE for details.
|
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), "lib", "open_exception")
|
data/rails/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), "..", "init")
|
data/test_data/raiser.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../lib/open_exception')
|
2
|
-
|
3
|
-
class Raiser
|
4
|
-
def raise_now
|
5
|
-
raise Exception.new
|
6
|
-
end
|
7
|
-
|
8
|
-
def raise_first_level
|
9
|
-
raise_now
|
10
|
-
end
|
11
|
-
|
12
|
-
def raise_second_level
|
13
|
-
raise_first_level
|
14
|
-
end
|
15
|
-
|
16
|
-
def file
|
17
|
-
__FILE__
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.raise_and_open(options = {})
|
21
|
-
Raiser.new.raise_now
|
22
|
-
rescue Exception
|
23
|
-
OpenException.open($!, options)
|
24
|
-
end
|
25
|
-
end
|