hammertime19 0.0.4

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/.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: []