hammertime19 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Avdi Grimm
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,109 @@
1
+ = hammertime19
2
+
3
+ An interactive error console similar to those found in Lisp and Smalltalk environments.
4
+
5
+ hammertime19 is a fork of Avid Grimm's hammertime gem: https://github.com/avdi/hammertime
6
+
7
+ hammertime19 is a Ruby 1.9.2+ (MRI and RBX) only version that adds support for starting a pry (https://github.com/pry/pry)
8
+ session at the exception raise site.
9
+
10
+ == Install
11
+
12
+ gem install hammertime19
13
+
14
+ == Synopsis
15
+
16
+ Simply require the Hammertime library:
17
+
18
+ require 'hammertime19'
19
+
20
+ $broken = true
21
+
22
+ def faulty_method
23
+ raise "Oh no!" if $broken
24
+ end
25
+
26
+ 3.times do |n|
27
+ puts "Attempt (#{n+1}/3)"
28
+ begin
29
+ faulty_method
30
+ puts "No error raised"
31
+ rescue => error
32
+ puts "Error raised: #{error.inspect}"
33
+ end
34
+ end
35
+
36
+ When an error is raised, a menu of possible actions will be presented at the console:
37
+
38
+ === Stop! Hammertime. ===
39
+ An error has occurred at example.rb:4:in `raise_runtime_error'
40
+ The error is: #<RuntimeError: Oh no!>
41
+ 1. Continue (process the exception normally)
42
+ 2. Ignore (proceed without raising an exception)
43
+ 3. Permit by type (don't ask about future errors of this type)
44
+ 4. Permit by line (don't ask about future errors raised from this point)
45
+ 5. Backtrace (show the call stack leading up to the error)
46
+ 6. Debug (start a debugger)
47
+ 7. Console (start a pry session)
48
+ What now?
49
+
50
+ This enables a fix-and-continue style of development:
51
+
52
+ $ ruby example.rb
53
+ Attempt (1/3)
54
+
55
+ === Stop! Hammertime. ===
56
+ An error has occurred at example.rb:6:in `faulty_method'
57
+ The error is: #<RuntimeError: Oh no!>
58
+ 1. Continue (process the exception normally)
59
+ 2. Ignore (proceed without raising an exception)
60
+ 3. Permit by type (don't ask about future errors of this type)
61
+ 4. Permit by line (don't ask about future errors raised from this point)
62
+ 5. Backtrace (show the call stack leading up to the error)
63
+ 6. Debug (start a debugger)
64
+ 7. Console (start a pry session)
65
+ What now?
66
+ 7
67
+
68
+ From: test.rb @ line 5 Object#faulty_method:
69
+
70
+ 5: def faulty_method
71
+ => 6: raise "Oh no!" if $broken
72
+ 7: end
73
+
74
+ [1] pry(main)> $broken = false
75
+ => false
76
+ [2] pry(main)> exit
77
+
78
+ 1. Continue (process the exception normally)
79
+ 2. Ignore (proceed without raising an exception)
80
+ 3. Permit by type (don't ask about future errors of this type)
81
+ 4. Permit by line (don't ask about future errors raised from this point)
82
+ 5. Backtrace (show the call stack leading up to the error)
83
+ 6. Debug (start a debugger)
84
+ 7. Console (start an IRB session)
85
+ What now?
86
+ 2
87
+ No error raised
88
+ Attempt (2/3)
89
+ No error raised
90
+ Attempt (3/3)
91
+ No error raised
92
+
93
+ == Known Bugs
94
+
95
+ * Hammertime cannot intercept exceptions which are raised from native code.
96
+
97
+ == TODO
98
+
99
+ * Better integration with IRB to enable a "Retry" option.
100
+ * Tests
101
+
102
+ == Dependencies
103
+
104
+ * pry (https://github.com/pry/pry)
105
+ * binding_of_caller (https://github.com/banister/binding_of_caller)
106
+
107
+ == Copyright
108
+
109
+ Copyright (c) 2010 Avdi Grimm. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #encoding: utf-8
2
+
3
+ require 'rake'
4
+ require 'rake/rdoctask'
5
+
6
+ Rake::RDocTask.new do |rdoc|
7
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
8
+
9
+ rdoc.rdoc_dir = 'rdoc'
10
+ rdoc.title = "hammertime #{version}"
11
+ rdoc.rdoc_files.include('README*')
12
+ rdoc.rdoc_files.include('lib/**/*.rb')
13
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.4
data/example.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'lib/hammertime'
2
+
3
+ $broken = true
4
+
5
+ def faulty_method
6
+ raise "Oh no!" if $broken
7
+ end
8
+
9
+ 3.times do |n|
10
+ puts "Attempt (#{n+1}/3)"
11
+ begin
12
+ faulty_method
13
+ puts "No error raised"
14
+ rescue => error
15
+ puts "Error raised: #{error.inspect}"
16
+ end
17
+ end
18
+
19
+
@@ -0,0 +1,11 @@
1
+ # IN A WORLD... where ruby-debug and IRB is not in the load
2
+ # path... one man will raise an exception.
3
+ require 'rubygems'
4
+ require '../lib/hammertime'
5
+
6
+ # Clear out load path. Now LoadError will be raised when
7
+ # Hammertime tries to load IRB or the debugger.
8
+ $:.clear
9
+
10
+ include Hammertime
11
+ raise "Holy smokes!"
@@ -0,0 +1,33 @@
1
+ #encoding: utf-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "hammertime19"
5
+ s.version = "0.0.4"
6
+
7
+ s.authors = ["Kalle Lindstrom"]
8
+ s.date = "2012-08-20"
9
+ s.description = "When this library is required, it replaces the default Ruby exception-raising\nbehavior. When an error is raised, the developer is presented with a menu\nenabling them to ignore the error, view a stack trace, debug the error using IRB\nor ruby-debug, and more.\n"
10
+ s.email = "lindstrom.kalle@gmail.com"
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ "LICENSE",
18
+ "README.rdoc",
19
+ "Rakefile",
20
+ "VERSION",
21
+ "example.rb",
22
+ "examples/loaderror.rb",
23
+ "hammertime19.gemspec",
24
+ "lib/hammertime19.rb"
25
+ ]
26
+ s.homepage = "http://github.com/kl/hammertime19"
27
+ s.require_paths = ["lib"]
28
+ s.summary = "Exception debugging console for Ruby"
29
+
30
+ s.add_dependency("highline", ["~> 1.5"])
31
+ s.add_dependency("pry", ">= 0.9.10")
32
+ s.add_dependency("binding_of_caller", ">= 0.6.7")
33
+ end
@@ -0,0 +1,171 @@
1
+ #encoding: utf-8
2
+
3
+ # https://github.com/kl/hammertime
4
+ # Forked from https://github.com/avdi/hammertime
5
+ # This fork works only with MRI 1.9.2+ and RBX
6
+ # Adds support for starting a Pry session at the call site of the exception.
7
+
8
+ require 'thread'
9
+ require 'highline'
10
+ require 'pry'
11
+ require 'binding_of_caller'
12
+
13
+ module Hammertime
14
+ def self.ignored_errors
15
+ @ignored_errors ||= [LoadError]
16
+ end
17
+
18
+ def self.ignored_lines
19
+ @ignored_lines ||= []
20
+ end
21
+
22
+ def self.stopped
23
+ @stopped ||= false
24
+ end
25
+
26
+ def self.stopped=(value)
27
+ @stopped = value
28
+ end
29
+
30
+ def self.debug_supported?
31
+ require 'ruby-debug'
32
+ @debug_support = true
33
+ rescue LoadError
34
+ warn "Unable to load ruby-debug"
35
+ warn "Gem not installed or debugging not supported on your platform"
36
+ @debug_support = false
37
+ end
38
+
39
+ def hammertime_raise(*args)
40
+ backtrace = caller(2)
41
+ fallback = lambda do
42
+ hammertime_original_raise(*args)
43
+ end
44
+ exclusive_and_non_reentrant(fallback) do
45
+ error, backtrace =
46
+ case args.size
47
+ when 0 then [($!.nil? ? RuntimeError.new : $!), backtrace]
48
+ when 1 then
49
+ if args[0].is_a?(String)
50
+ [RuntimeError.exception(args[0]), backtrace]
51
+ else
52
+ [args[0].exception, backtrace]
53
+ end
54
+ when 2 then
55
+ [args[0].exception(args[1]), backtrace]
56
+ when 3 then
57
+ [args[0].exception(args[1]), args[2]]
58
+ else
59
+ super(ArgumentError, "wrong number of arguments", backtrace)
60
+ end
61
+ error.set_backtrace(backtrace)
62
+
63
+ if hammertime_ignore_error?(error, backtrace)
64
+ hammertime_original_raise(error)
65
+ else
66
+ ::Hammertime.stopped = true
67
+ end
68
+
69
+ c = ::Hammertime.hammertime_console
70
+ c.say "\n"
71
+ c.say "=== Stop! Hammertime. ==="
72
+ c.say "An error has occurred at #{backtrace.first}"
73
+ c.say "The error is: #{error.inspect}"
74
+ menu_config = lambda do |menu|
75
+ menu.prompt = "What now?"
76
+ menu.default = "Continue"
77
+ menu.select_by = :index_or_name
78
+
79
+ menu.choice "Continue (process the exception normally)" do
80
+ hammertime_original_raise(error)
81
+ true
82
+ end
83
+ menu.choice "Ignore (proceed without raising an exception)" do
84
+ true
85
+ end
86
+ menu.choice "Permit by type (don't ask about future errors of this type)" do
87
+ ::Hammertime.ignored_errors << error.class
88
+ c.say "Added #{error.class} to permitted error types"
89
+ hammertime_original_raise(error)
90
+ true
91
+ end
92
+ menu.choice "Permit by line (don't ask about future errors raised from this point)" do
93
+ ::Hammertime.ignored_lines << backtrace.first
94
+ c.say "Added #{backtrace.first} to permitted error lines"
95
+ hammertime_original_raise(error)
96
+ true
97
+ end
98
+ menu.choice "Backtrace (show the call stack leading up to the error)" do
99
+ backtrace.each do |frame| c.say frame end
100
+ false
101
+ end
102
+ if Hammertime.debug_supported?
103
+ menu.choice "Debug (start a debugger)" do
104
+ debugger
105
+ false
106
+ end
107
+ end
108
+ menu.choice "Console (start a pry session)" do
109
+ yield.pry
110
+ false
111
+ end
112
+ end
113
+ continue = c.choose(&menu_config) until continue
114
+ end
115
+ ensure
116
+ ::Hammertime.stopped = false
117
+ end
118
+
119
+ def hammertime_original_raise(*args)
120
+ Kernel.instance_method(:raise).bind(self).call(*args)
121
+ end
122
+
123
+ def fail(*args)
124
+ caller_binding = binding.of_caller(1)
125
+ hammertime_raise(*args) { caller_binding }
126
+ end
127
+
128
+ def raise(*args)
129
+ caller_binding = binding.of_caller(1)
130
+ hammertime_raise(*args) { caller_binding }
131
+ end
132
+
133
+ private
134
+
135
+ # No lazy initialization where threads are concerned. We still use
136
+ # ||= on the off chance that this file gets loaded twice in 1.8.
137
+ @mutex ||= Mutex.new
138
+
139
+ def self.mutex
140
+ @mutex
141
+ end
142
+
143
+ def self.hammertime_console
144
+ @console ||= HighLine.new($stdin, $stderr)
145
+ end
146
+
147
+ def hammertime_ignore_error?(error, backtrace)
148
+ return true if ::Hammertime.stopped
149
+ return true if ::Hammertime.ignored_errors.any?{|e| error.is_a?(e)}
150
+ return true if ::Hammertime.ignored_lines.include?(backtrace.first)
151
+ return false
152
+ end
153
+
154
+ def exclusive_and_non_reentrant(fallback, &block)
155
+ lock_acquired = ::Hammertime.mutex.try_lock
156
+ if lock_acquired
157
+ yield
158
+ ::Hammertime.mutex.unlock
159
+ else
160
+ fallback.call
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ unless ::Object < Hammertime
167
+ class ::Object
168
+ include ::Hammertime
169
+ end
170
+ Debugger.start if $hammertime_debug_support
171
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hammertime19
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kalle Lindstrom
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: highline
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.5'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.5'
30
+ - !ruby/object:Gem::Dependency
31
+ name: pry
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.9.10
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.9.10
46
+ - !ruby/object:Gem::Dependency
47
+ name: binding_of_caller
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.6.7
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.6.7
62
+ description: ! 'When this library is required, it replaces the default Ruby exception-raising
63
+
64
+ behavior. When an error is raised, the developer is presented with a menu
65
+
66
+ enabling them to ignore the error, view a stack trace, debug the error using IRB
67
+
68
+ or ruby-debug, and more.
69
+
70
+ '
71
+ email: lindstrom.kalle@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files:
75
+ - LICENSE
76
+ - README.rdoc
77
+ files:
78
+ - .document
79
+ - LICENSE
80
+ - README.rdoc
81
+ - Rakefile
82
+ - VERSION
83
+ - example.rb
84
+ - examples/loaderror.rb
85
+ - hammertime19.gemspec
86
+ - lib/hammertime19.rb
87
+ homepage: http://github.com/kl/hammertime19
88
+ licenses: []
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 1.8.24
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Exception debugging console for Ruby
111
+ test_files: []