lib/superscript/runner.rb in superscript-0.5.0 vs lib/superscript/runner.rb in superscript-0.6.0
- old
+ new
@@ -1,43 +1,46 @@
module Superscript
- def self.error(where, *args)
- puts "-- [ superscript error ] --"
- error_message = ""
- case where
- when :exception
- exception = args.first
- pp exception
- pp exception.backtrace_locations
- error_message = exception
- when :tp_call_superscript
- error_message = "Can't touch this"
- when :ctx_method_missing, :tp_singleton_method_added, :tp_command_not_found
- error_message = args.first
- when :tp_class_define, :tp_module_define
- error_message = args.first
- else
- pp [:unknown_where, where, args]
- error_message = args.join(" ")
- end
-
- puts error_message
- if ENV["SUPERSCRIPT_ERROR_EXEC"]
- error_exec_pid = spawn ENV["SUPERSCRIPT_ERROR_EXEC"], error_message
- Process.wait error_exec_pid
- end
- exit 1
- end
class Runner
- def initialize path=nil
+ def initialize path=nil, opts={}
+ @methods = opts[:methods] || false
+ @on_error_exec = opts[:on_error_exec]
+
@armed = false
@path = if path
path
else
"<interactive>"
end
end
+ def error!(where, *args)
+ puts "-- [ superscript error ] --"
+ error_message = ""
+ case where
+ when :exception
+ exception = args.first
+ pp exception
+ pp exception.backtrace_locations
+ error_message = exception
+ when :tp_call_superscript
+ error_message = "Can't touch this"
+ when :ctx_method_missing, :tp_singleton_method_added, :tp_command_not_found
+ error_message = args.first
+ when :tp_class_define, :tp_module_define
+ error_message = args.first
+ else
+ pp [:unknown_where, where, args]
+ error_message = args.join(" ")
+ end
+
+ puts error_message
+ if @on_error_exec
+ system("#{@on_error_exec} #{error_message}")
+ end
+ exit 1
+ end
+
def arm!(reason=nil)
p [:arm!, reason] if ENV["SUPERSCRIPT_DEBUG"]
@armed = true
end
def disarm!(reason=nil)
@@ -72,11 +75,11 @@
next unless @armed
case tp.event
when :class
- ::Superscript.error :tp_module_define, "Defining modules is not allowed"
+ error! :tp_module_define, "Defining modules is not allowed"
when :line
lines = if tp.path == "<interactive>"
contents.split("\n")
else
File.read(tp.path).split("\n")
@@ -84,25 +87,32 @@
line = lines[tp.lineno-1].lstrip
puts "< #{tp.path}:#{tp.lineno-1}"
puts line
when :c_call
- # allow calls to these classes
+ # allow calls to these instances
+ if tp.defined_class.ancestors.at(1) == Struct
+ disarm! :safe_instance
+ next
+ end
if ["Array", "String","Float", "Integer"].include? tp.defined_class.name
- disarm! :safe_class
+ disarm! :safe_instance
next
end
case tp.method_id
when :singleton_method_added
+ if @methods
+ next
+ end
trace.disable
- ::Superscript.error :tp_singleton_method_added, "Deffining methods is not allowed"
+ error! :tp_singleton_method_added, "Deffining methods is not allowed"
else
trace.disable
case tp.defined_class.name
when "Class"
- ::Superscript.error :tp_class_define, "Defining classes is not allowed"
+ error! :tp_class_define, "Defining classes is not allowed"
else
class_name = case tp.defined_class.inspect
when "Kernel"
"Kernel"
when "Module"
@@ -119,17 +129,17 @@
tp.method_id
else
"#{class_name}.#{tp.method_id}"
end
- ::Superscript.error :tp_command_not_found, "Command not found '#{command_name}'"
+ error! :tp_command_not_found, "Command not found '#{command_name}'"
end
end
when :call
if tp.defined_class.ancestors.first.to_s == "#<Class:Superscript>"
tp.disable
- ::Superscript.error :tp_call_superscript
+ error! :tp_call_superscript
end
# disable if calling some other file
# but do not allow call to Superscript.error etc
if tp.path != @path
disarm! :calling_other_file
@@ -155,10 +165,10 @@
exit ex.status
when "NameError"
print "#{@path}:#{ex.backtrace_locations.first.lineno} "
puts ex.message.split(" for ").first
else
- ::Superscript.error :exception, ex
+ error! :exception, ex
end
ensure
trace.disable
end