lib/eturem/base.rb in eturem-0.2.0 vs lib/eturem/base.rb in eturem-0.3.0
- old
+ new
@@ -1,16 +1,12 @@
require "eturem/version"
module Eturem
- def self.eturem_class
- @eturem_class
- end
-
- def self.eturem_class=(klass)
- @eturem_class = klass
- end
-
+ # load script and return eturem_exception if exception raised
+ # @param [String] file script file
+ # @return [Eturem::Base] if exception raised
+ # @return [nil] if exception did not raise
def self.load(file)
begin
Kernel.load file
rescue Exception => exception
return @eturem_class.new(exception) unless exception.is_a? SystemExit
@@ -25,16 +21,25 @@
return @eturem_class.new(exception) unless exception.is_a? SystemExit
end
return nil
end
+ def self.eturem_class
+ @eturem_class
+ end
+
+ def self.eturem_class=(klass)
+ @eturem_class = klass
+ end
+
class Base
attr_reader :exception
@@output_backtrace = true
@@output_original = true
@@output_script = true
+ @@use_coderay = false
@@max_backtrace = 16
@@before_line_num = 2
@@after_line_num = 2
@inspect_methods = {}
@@ -53,10 +58,14 @@
def self.output_script=(value)
@@output_script = value
end
+ def self.use_coderay=(value)
+ @@use_coderay = value
+ end
+
def self.max_backtrace=(value)
@@max_backtrace = value
end
def self.before_line_num=(value)
@@ -65,11 +74,10 @@
def self.after_line_num=(value)
@@after_line_num = value
end
- # prepare
def initialize(exception)
@exception = exception
@exception_s = exception.to_s
eturem_path = File.dirname(File.absolute_path(__FILE__))
@@ -94,25 +102,76 @@
load_script
prepare
end
- def load_script
- @script = ""
- if @path && File.exist?(@path)
- @script = File.binread(@path)
- encoding = "utf-8"
- if @script.match(/\A(?:#!.*\R)?#.*coding *[:=] *(?<encoding>[^\s:]+)/)
- encoding = Regexp.last_match(:encoding)
+ # output backtrace + error message + script
+ def output
+ output_backtrace if @@output_backtrace
+ error_message = exception_inspect
+ if error_message.to_s.empty?
+ puts original_exception_inspect
+ else
+ puts original_exception_inspect if @@output_original
+ puts error_message
+ end
+ output_script if @@output_script
+ end
+
+ def output_backtrace
+ return if @backtrace_locations.empty?
+
+ puts traceback_most_recent_call_last
+ @backtrace_locations[0, @@max_backtrace].reverse.each_with_index do |location, i|
+ puts sprintf("%9d: %s", @backtrace_locations.size - i, location_inspect(location))
+ end
+ end
+
+ def exception_inspect
+ inspect_methods = self.class.inspect_methods
+ inspect_methods.keys.reverse_each do |key|
+ case key
+ when Class
+ return public_send(inspect_methods[key]) if @exception.is_a? key
+ when String
+ return public_send(inspect_methods[key]) if @exception.class.to_s == key
end
- @script.force_encoding(encoding)
end
- @script_lines = @script.lines
- @script_lines.unshift("")
- @output_lines = default_output_lines
+ return nil
end
+ def original_exception_inspect
+ if @exception.is_a? SyntaxError
+ return @exception_s
+ else
+ location_str = "#{@path}:#{@lineno}:in `#{@label}'"
+ if @exception_s.match(/\A(?<first_line>.*?)\n/)
+ return "#{location_str}: #{Regexp.last_match(:first_line)} (#{@exception.class})\n" +
+ "#{Regexp.last_match.post_match}"
+ else
+ return "#{location_str}: #{@exception_s} (#{@exception.class})"
+ end
+ end
+ end
+
+ def output_script
+ return if @script.empty?
+
+ max_lineno_length = @output_lines.compact.max.to_s.length
+ @output_lines.each do |i|
+ if @lineno == i
+ puts sprintf("\e[0m => \e[1;34m%#{max_lineno_length}d\e[0m: %s", i, @script_lines[i])
+ elsif i
+ puts sprintf("\e[0m \e[1;34m%#{max_lineno_length}d\e[0m: %s", i, @script_lines[i])
+ else
+ puts "\e[0m #{" " * max_lineno_length} :"
+ end
+ end
+ end
+
+ private
+
def prepare
case @exception
when SyntaxError then prepare_syntax_error
when NameError then prepare_name_error
when ArgumentError then prepare_argument_error
@@ -126,20 +185,20 @@
@expected = @exception_s.match(/[,\s]expecting (?<expected>\S+)/) ?
Regexp.last_match(:expected) : "end-of-input"
end
def prepare_name_error
- highlight!(@script_lines[@lineno], @exception.name.to_s, "\e[31m\e[4m")
+ highlight!(@script_lines[@lineno], @exception.name.to_s, "\e[1;31m\e[4m")
return unless @exception_s.match(/Did you mean\?/)
@did_you_mean = Regexp.last_match.post_match.strip.scan(/\S+/)
return if @script.empty?
new_range = []
@did_you_mean.each do |name|
index = @script_lines.index { |line| line.include?(name) }
next unless index
- highlight!(@script_lines[index], name, "\e[33m")
+ highlight!(@script_lines[index], name, "\e[1;33m")
new_range.push(index)
end
new_range.sort!
before = new_range.select { |i| i < @output_lines.first }
after = new_range.select { |i| i > @output_lines.last }
@@ -167,33 +226,10 @@
def prepare_type_error
@method = @label
end
- # main
- def output_error
- output_backtrace if @@output_backtrace
- error_message = exception_inspect
- if error_message.to_s.empty?
- puts original_exception_inspect
- else
- puts original_exception_inspect if @@output_original
- puts error_message
- end
- output_script if @@output_script
- end
-
- # backtrace
- def output_backtrace
- return if @backtrace_locations.empty?
-
- puts traceback_most_recent_call_last
- @backtrace_locations[0, @@max_backtrace].reverse.each_with_index do |location, i|
- puts sprintf("%9d: %s", @backtrace_locations.size - i, location_inspect(location))
- end
- end
-
def backtrace_locations_shift
@label = @backtrace_locations.first.label
@path = @backtrace_locations.first.path
@lineno = @backtrace_locations.first.lineno
@backtrace_locations.shift
@@ -205,51 +241,23 @@
def location_inspect(location)
"from #{location.path}:#{location.lineno}:in `#{location.label}'"
end
- # exception
- def exception_inspect
- inspect_methods = self.class.inspect_methods
- inspect_methods.keys.reverse_each do |key|
- case key
- when Class
- return public_send(inspect_methods[key]) if @exception.is_a? key
- when String
- return public_send(inspect_methods[key]) if @exception.class.to_s == key
+ def load_script
+ @script = ""
+ if @path && File.exist?(@path)
+ @script = File.binread(@path)
+ encoding = "utf-8"
+ if @script.match(/\A(?:#!.*\R)?#.*coding *[:=] *(?<encoding>[^\s:]+)/)
+ encoding = Regexp.last_match(:encoding)
end
+ @script.force_encoding(encoding)
end
- return nil
- end
-
- def original_exception_inspect
- if @exception.is_a? SyntaxError
- return @exception_s
- else
- location_str = "#{@path}:#{@lineno}:in `#{@label}'"
- if @exception_s.match(/\A(?<first_line>.*?)\n/)
- return "#{location_str}: #{Regexp.last_match(:first_line)} (#{@exception.class})\n" +
- "#{Regexp.last_match.post_match}"
- else
- return "#{location_str}: #{@exception_s} (#{@exception.class})"
- end
- end
- end
-
- # script
- def output_script
- return if @script.empty?
-
- max_lineno_length = @output_lines.compact.max.to_s.length
- @output_lines.each do |i|
- if @lineno == i
- puts sprintf(" => \e[34m%#{max_lineno_length}d:\e[0m %s", i, @script_lines[i])
- elsif i
- puts sprintf(" \e[34m%#{max_lineno_length}d:\e[0m %s", i, @script_lines[i])
- else
- puts " \e[34m#{" " * max_lineno_length} :\e[0m"
- end
- end
+ @script = CodeRay.scan(@script, :ruby).terminal if @@use_coderay
+ @script_lines = @script.lines
+ @script_lines.unshift("")
+ @output_lines = default_output_lines
end
def highlight(str, keyword, color)
str.to_s.gsub(keyword){ color + ($1 || $&) + "\e[0m" }
end