config: factor out exception_handler hook to a separate class
This commit is contained in:
parent
9306e69bda
commit
95d3a74e9b
|
@ -21,6 +21,7 @@ require 'pry/syntax_highlighter'
|
||||||
require 'pry/editor'
|
require 'pry/editor'
|
||||||
require 'pry/history'
|
require 'pry/history'
|
||||||
require 'pry/color_printer'
|
require 'pry/color_printer'
|
||||||
|
require 'pry/exception_handler'
|
||||||
|
|
||||||
Pry::Commands = Pry::CommandSet.new unless defined?(Pry::Commands)
|
Pry::Commands = Pry::CommandSet.new unless defined?(Pry::Commands)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ class Pry
|
||||||
# @return [Pry::Config]
|
# @return [Pry::Config]
|
||||||
# An object who implements the default configuration for all
|
# An object who implements the default configuration for all
|
||||||
# Pry sessions.
|
# Pry sessions.
|
||||||
# rubocop:disable Metrics/AbcSize
|
|
||||||
def self.defaults
|
def self.defaults
|
||||||
defaults = from_hash(
|
defaults = from_hash(
|
||||||
input: Pry.lazy { lazy_readline(defaults) },
|
input: Pry.lazy { lazy_readline(defaults) },
|
||||||
|
@ -18,26 +17,7 @@ class Pry
|
||||||
prompt_safe_contexts: Pry::Prompt::SAFE_CONTEXTS,
|
prompt_safe_contexts: Pry::Prompt::SAFE_CONTEXTS,
|
||||||
print: Pry::ColorPrinter.method(:default),
|
print: Pry::ColorPrinter.method(:default),
|
||||||
quiet: false,
|
quiet: false,
|
||||||
|
exception_handler: Pry::ExceptionHandler.method(:handle_exception),
|
||||||
# Will only show the first line of the backtrace
|
|
||||||
exception_handler: proc do |output, exception, _|
|
|
||||||
if exception.is_a?(UserError) && exception.is_a?(SyntaxError)
|
|
||||||
output.puts "SyntaxError: #{exception.message.sub(/.*syntax error, */m, '')}"
|
|
||||||
else
|
|
||||||
output.puts "#{exception.class}: #{exception.message}"
|
|
||||||
output.puts "from #{exception.backtrace.first}"
|
|
||||||
|
|
||||||
if exception.respond_to? :cause
|
|
||||||
cause = exception.cause
|
|
||||||
while cause
|
|
||||||
output.puts "Caused by #{cause.class}: #{cause}\n"
|
|
||||||
output.puts "from #{cause.backtrace.first}"
|
|
||||||
cause = cause.cause
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
|
|
||||||
unrescued_exceptions: [
|
unrescued_exceptions: [
|
||||||
::SystemExit, ::SignalException, Pry::TooSafeException
|
::SystemExit, ::SignalException, Pry::TooSafeException
|
||||||
],
|
],
|
||||||
|
@ -113,7 +93,6 @@ class Pry
|
||||||
exec_string: ""
|
exec_string: ""
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/AbcSize
|
|
||||||
|
|
||||||
def self.shortcuts
|
def self.shortcuts
|
||||||
Convenience::SHORTCUTS
|
Convenience::SHORTCUTS
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
class Pry
|
||||||
|
# @api private
|
||||||
|
# @since ?.?.?
|
||||||
|
module ExceptionHandler
|
||||||
|
class << self
|
||||||
|
# Will only show the first line of the backtrace.
|
||||||
|
def handle_exception(output, exception, _pry_instance)
|
||||||
|
if exception.is_a?(UserError) && exception.is_a?(SyntaxError)
|
||||||
|
output.puts "SyntaxError: #{exception.message.sub(/.*syntax error, */m, '')}"
|
||||||
|
else
|
||||||
|
output.puts standard_error_text_for(exception)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def standard_error_text_for(exception)
|
||||||
|
text = exception_text(exception)
|
||||||
|
return text unless exception.respond_to?(:cause)
|
||||||
|
|
||||||
|
cause = exception.cause
|
||||||
|
while cause
|
||||||
|
text += cause_text(cause)
|
||||||
|
cause = cause.cause
|
||||||
|
end
|
||||||
|
|
||||||
|
text
|
||||||
|
end
|
||||||
|
|
||||||
|
def exception_text(exception)
|
||||||
|
"#{exception.class}: #{exception.message}\n" \
|
||||||
|
"from #{exception.backtrace.first}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def cause_text(cause)
|
||||||
|
"Caused by #{cause.class}: #{cause}\n" \
|
||||||
|
"from #{cause.backtrace.first}\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,64 @@
|
||||||
|
RSpec.describe Pry::ExceptionHandler do
|
||||||
|
describe ".handle_exception" do
|
||||||
|
let(:output) { StringIO.new }
|
||||||
|
let(:pry_instance) { Pry.new }
|
||||||
|
|
||||||
|
context "when exception is a UserError and a SyntaxError" do
|
||||||
|
let(:exception) do
|
||||||
|
SyntaxError.new('cool syntax error, dude').extend(Pry::UserError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "prints the syntax error with customized message" do
|
||||||
|
described_class.handle_exception(output, exception, pry_instance)
|
||||||
|
expect(output.string).to start_with("SyntaxError: dude\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when exception is a standard error" do
|
||||||
|
let(:exception) do
|
||||||
|
error = StandardError.new('oops')
|
||||||
|
error.set_backtrace(["/bin/pry:23:in `<main>'"])
|
||||||
|
error
|
||||||
|
end
|
||||||
|
|
||||||
|
it "prints standard error message" do
|
||||||
|
described_class.handle_exception(output, exception, pry_instance)
|
||||||
|
expect(output.string)
|
||||||
|
.to eq("StandardError: oops\nfrom /bin/pry:23:in `<main>'\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when exception is a nested standard error" do
|
||||||
|
let(:exception) do
|
||||||
|
error = nil
|
||||||
|
begin
|
||||||
|
begin
|
||||||
|
raise 'nested oops'
|
||||||
|
rescue # rubocop:disable Style/RescueStandardError
|
||||||
|
raise 'outer oops'
|
||||||
|
end
|
||||||
|
rescue StandardError => outer_error
|
||||||
|
error = outer_error
|
||||||
|
end
|
||||||
|
|
||||||
|
error
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
if RUBY_VERSION.start_with?('1.9', '2.0')
|
||||||
|
skip("Ruby #{RUBY_VERSION} doesn't support nested exceptions")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "prints standard error message" do
|
||||||
|
described_class.handle_exception(output, exception, pry_instance)
|
||||||
|
expect(output.string).to match(
|
||||||
|
/RuntimeError:\souter\soops\n
|
||||||
|
from\s.+\n
|
||||||
|
Caused\sby\sRuntimeError:\snested\soops\n
|
||||||
|
from.+/x
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue