hammertime 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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,22 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+
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.
@@ -0,0 +1,88 @@
1
+ = hammertime
2
+
3
+ An interactive error console similar to those found in Lisp and Smalltalk environments.
4
+
5
+ == Synopsis
6
+
7
+ Simply require the Hammertime library:
8
+
9
+ require 'hammertime'
10
+
11
+ $broken = true
12
+
13
+ def faulty_method
14
+ raise "Oh no!" if $broken
15
+ end
16
+
17
+ 3.times do |n|
18
+ puts "Attempt (#{n+1}/3)"
19
+ begin
20
+ faulty_method
21
+ puts "No error raised"
22
+ rescue => error
23
+ puts "Error raised: #{error.inspect}"
24
+ end
25
+ end
26
+
27
+ When an error is raised, a menu of possible actions will be presented at the console:
28
+
29
+ === Stop! Hammertime. ===
30
+ An error has occurred at example.rb:4:in `raise_runtime_error'
31
+ The error is: #<RuntimeError: Oh no!>
32
+ 1. Continue (process the exception normally)
33
+ 2. Ignore (proceed without raising an exception)
34
+ 3. Permit by type (don't ask about future errors of this type)
35
+ 4. Permit by line (don't ask about future errors raised from this point)
36
+ 5. Backtrace (show the call stack leading up to the error)
37
+ 6. Debug (start a debugger)
38
+ 7. Console (start an IRB session)
39
+ What now?
40
+
41
+ This enables a fix-and-continue style of development:
42
+
43
+ $ ruby example.rb
44
+ Attempt (1/3)
45
+
46
+ === Stop! Hammertime. ===
47
+ An error has occurred at example.rb:6:in `faulty_method'
48
+ The error is: #<RuntimeError: Oh no!>
49
+ 1. Continue (process the exception normally)
50
+ 2. Ignore (proceed without raising an exception)
51
+ 3. Permit by type (don't ask about future errors of this type)
52
+ 4. Permit by line (don't ask about future errors raised from this point)
53
+ 5. Backtrace (show the call stack leading up to the error)
54
+ 6. Debug (start a debugger)
55
+ 7. Console (start an IRB session)
56
+ What now?
57
+ 7
58
+
59
+ >> $broken = false
60
+ => false
61
+ >> exit
62
+
63
+ 1. Continue (process the exception normally)
64
+ 2. Ignore (proceed without raising an exception)
65
+ 3. Permit by type (don't ask about future errors of this type)
66
+ 4. Permit by line (don't ask about future errors raised from this point)
67
+ 5. Backtrace (show the call stack leading up to the error)
68
+ 6. Debug (start a debugger)
69
+ 7. Console (start an IRB session)
70
+ What now?
71
+ 2
72
+ No error raised
73
+ Attempt (2/3)
74
+ No error raised
75
+ Attempt (3/3)
76
+ No error raised
77
+
78
+ == Known Bugs
79
+
80
+ * Hammertime cannot intercept exceptions which are raised from native code.
81
+
82
+ == TODO
83
+
84
+ * Better integration with IRB to enable a "Retry" option.
85
+
86
+ == Copyright
87
+
88
+ Copyright (c) 2010 Avdi Grimm. See LICENSE for details.
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "hammertime"
8
+ gem.summary = %Q{Exception debugging console for Ruby}
9
+ gem.description = <<END
10
+ When this library is required, it replaces the default Ruby exception-raising
11
+ behavior. When an error is raised, the developer is presented with a menu
12
+ enabling them to ignore the error, view a stack trace, debug the error using IRB
13
+ or ruby-debug, and more.
14
+ END
15
+ gem.email = "avdi@avdi.org"
16
+ gem.homepage = "http://github.com/avdi/hammertime"
17
+ gem.authors = ["Avdi Grimm"]
18
+ gem.add_dependency "ruby-debug", "~> 0.10"
19
+ gem.add_dependency "highline", "~> 1.5"
20
+ gem.add_development_dependency "rspec", ">= 1.2.9"
21
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
22
+ end
23
+ Jeweler::GemcutterTasks.new
24
+ rescue LoadError
25
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
26
+ end
27
+
28
+ require 'spec/rake/spectask'
29
+ Spec::Rake::SpecTask.new(:spec) do |spec|
30
+ spec.libs << 'lib' << 'spec'
31
+ spec.spec_files = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
35
+ spec.libs << 'lib' << 'spec'
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :spec => :check_dependencies
41
+
42
+ task :default => :spec
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "hammertime #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -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,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{hammertime}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Avdi Grimm"]
12
+ s.date = %q{2010-01-17}
13
+ s.description = %q{When this library is required, it replaces the default Ruby exception-raising
14
+ behavior. When an error is raised, the developer is presented with a menu
15
+ enabling them to ignore the error, view a stack trace, debug the error using IRB
16
+ or ruby-debug, and more.
17
+ }
18
+ s.email = %q{avdi@avdi.org}
19
+ s.extra_rdoc_files = [
20
+ "LICENSE",
21
+ "README.rdoc"
22
+ ]
23
+ s.files = [
24
+ ".document",
25
+ ".gitignore",
26
+ "LICENSE",
27
+ "README.rdoc",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "example.rb",
31
+ "hammertime.gemspec",
32
+ "lib/hammertime.rb",
33
+ "spec/hammertime_spec.rb",
34
+ "spec/spec.opts",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/avdi/hammertime}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.5}
41
+ s.summary = %q{Exception debugging console for Ruby}
42
+ s.test_files = [
43
+ "spec/hammertime_spec.rb",
44
+ "spec/spec_helper.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
52
+ s.add_runtime_dependency(%q<ruby-debug>, ["~> 0.10"])
53
+ s.add_runtime_dependency(%q<highline>, ["~> 1.5"])
54
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
55
+ else
56
+ s.add_dependency(%q<ruby-debug>, ["~> 0.10"])
57
+ s.add_dependency(%q<highline>, ["~> 1.5"])
58
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<ruby-debug>, ["~> 0.10"])
62
+ s.add_dependency(%q<highline>, ["~> 1.5"])
63
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
64
+ end
65
+ end
66
+
@@ -0,0 +1,128 @@
1
+ require 'highline'
2
+ require 'ruby-debug'
3
+
4
+ module Hammertime
5
+ def self.ignored_errors
6
+ @ignored_errors ||= [LoadError]
7
+ end
8
+
9
+ def self.ignored_lines
10
+ @ignored_lines ||= []
11
+ end
12
+
13
+ def self.stopped
14
+ @stopped ||= false
15
+ end
16
+
17
+ def self.stopped=(value)
18
+ @stopped = value
19
+ end
20
+
21
+ def hammertime_raise(*args)
22
+ backtrace = caller(2)
23
+ Thread.exclusive do
24
+ error, backtrace =
25
+ case args.size
26
+ when 0 then [($!.nil? ? RuntimeError.new : $!), backtrace]
27
+ when 1 then
28
+ if args[0].is_a?(String)
29
+ [RuntimeError.exception(args[0]), backtrace]
30
+ else
31
+ [args[0].exception, backtrace]
32
+ end
33
+ when 2 then
34
+ [args[0].exception(args[1]), backtrace]
35
+ when 3 then
36
+ [args[0].exception(args[1]), args[2]]
37
+ else
38
+ super(ArgumentError, "wrong number of arguments", backtrace)
39
+ end
40
+ error.set_backtrace(backtrace)
41
+
42
+ if hammertime_ignore_error?(error, backtrace)
43
+ hammertime_original_raise(error)
44
+ else
45
+ ::Hammertime.stopped = true
46
+ end
47
+
48
+ c = ::Hammertime.hammertime_console
49
+ c.say "\n"
50
+ c.say "=== Stop! Hammertime. ==="
51
+ c.say "An error has occurred at #{backtrace.first}"
52
+ c.say "The error is: #{error.inspect}"
53
+ menu_config = lambda do |menu|
54
+ menu.prompt = "What now?"
55
+ menu.default = "Continue"
56
+ menu.select_by = :index_or_name
57
+
58
+ menu.choice "Continue (process the exception normally)" do
59
+ hammertime_original_raise(error)
60
+ true
61
+ end
62
+ menu.choice "Ignore (proceed without raising an exception)" do
63
+ true
64
+ end
65
+ menu.choice "Permit by type (don't ask about future errors of this type)" do
66
+ ::Hammertime.ignored_errors << error.class
67
+ c.say "Added #{error.class} to permitted error types"
68
+ hammertime_original_raise(error)
69
+ true
70
+ end
71
+ menu.choice "Permit by line (don't ask about future errors raised from this point)" do
72
+ ::Hammertime.ignored_lines << backtrace.first
73
+ c.say "Added #{backtrace.first} to permitted error lines"
74
+ hammertime_original_raise(error)
75
+ true
76
+ end
77
+ menu.choice "Backtrace (show the call stack leading up to the error)" do
78
+ backtrace.each do |frame| c.say frame end
79
+ false
80
+ end
81
+ menu.choice "Debug (start a debugger)" do
82
+ debugger
83
+ false
84
+ end
85
+ menu.choice "Console (start an IRB session)" do
86
+ require 'irb'
87
+ IRB.start
88
+ false
89
+ end
90
+ end
91
+ continue = c.choose(&menu_config) until continue
92
+ end
93
+ ensure
94
+ ::Hammertime.stopped = false
95
+ end
96
+
97
+ def hammertime_original_raise(*args)
98
+ Kernel.instance_method(:raise).bind(self).call(*args)
99
+ end
100
+
101
+ def fail(*args)
102
+ hammertime_raise(*args)
103
+ end
104
+
105
+ def raise(*args)
106
+ hammertime_raise(*args)
107
+ end
108
+
109
+ private
110
+
111
+ def self.hammertime_console
112
+ @console ||= HighLine.new($stdin, $stderr)
113
+ end
114
+
115
+ def hammertime_ignore_error?(error, backtrace)
116
+ return true if ::Hammertime.stopped
117
+ return true if ::Hammertime.ignored_errors.any?{|e| error.is_a?(e)}
118
+ return true if ::Hammertime.ignored_lines.include?(backtrace.first)
119
+ return false
120
+ end
121
+ end
122
+
123
+ unless ::Object < Hammertime
124
+ class ::Object
125
+ include ::Hammertime
126
+ end
127
+ Debugger.start
128
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Hammertime" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'hammertime'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hammertime
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Avdi Grimm
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-17 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ruby-debug
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: "0.10"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: highline
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: "1.5"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.9
44
+ version:
45
+ description: |
46
+ When this library is required, it replaces the default Ruby exception-raising
47
+ behavior. When an error is raised, the developer is presented with a menu
48
+ enabling them to ignore the error, view a stack trace, debug the error using IRB
49
+ or ruby-debug, and more.
50
+
51
+ email: avdi@avdi.org
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files:
57
+ - LICENSE
58
+ - README.rdoc
59
+ files:
60
+ - .document
61
+ - .gitignore
62
+ - LICENSE
63
+ - README.rdoc
64
+ - Rakefile
65
+ - VERSION
66
+ - example.rb
67
+ - hammertime.gemspec
68
+ - lib/hammertime.rb
69
+ - spec/hammertime_spec.rb
70
+ - spec/spec.opts
71
+ - spec/spec_helper.rb
72
+ has_rdoc: true
73
+ homepage: http://github.com/avdi/hammertime
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --charset=UTF-8
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ version:
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ version:
93
+ requirements: []
94
+
95
+ rubyforge_project:
96
+ rubygems_version: 1.3.5
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: Exception debugging console for Ruby
100
+ test_files:
101
+ - spec/hammertime_spec.rb
102
+ - spec/spec_helper.rb