|
From: Jonathan P. <jp...@dc...> - 2005-09-16 13:47:52
|
Hi all,
My patch for bridging exceptions between Ruby and Objective C appears
to be in the CVS trunk. To go along with this, here's a base-class to
be used in place of NSApplication that will pop up an NSAlert when a
ruby exception occurs. The alert has 'Continue' and 'Abort' buttons.
To use this class, it's necessary to adjust 'rb_main.rb to use
RBCApplication in place of NSApplication:
if $0 == __FILE__ then
rb_main_init
OSX::ns_import "RBCApplication"
OSX::RBCApplication.sharedApplication
OSX.NSApplicationMain(0, nil)
end
Hope this is of some use.
Jonathan
// RBCApplication.h
#import <Cocoa/Cocoa.h>
@interface RBCApplication : NSApplication {
}
@end
// RBCApplication.m
@implementation RBCApplication
-(void)notifyRubyException:(NSException*)exc
{
static BOOL handling;
if (handling) {
NSLog(@"Got an exception %@ while handling another one!",exc);
return;
}
handling = YES;
NSMutableString *bs = nil;
NSArray *backtrace = [[exc userInfo] objectForKey: @"backtrace"];
if (backtrace) {
bs = [NSMutableString string];;
[bs appendString: @"Backtrace: \n"];
NSString *resources = [[NSBundle mainBundle] resourcePath];
unsigned int i, count = [backtrace count];
for (i = 0; i < count; i++) {
NSString *path = [backtrace objectAtIndex:i];
if ([path hasPrefix: resources]) {
path = [path substringFromIndex:[resources length]+1];
}
[bs appendFormat: @" %@\n", path];
}
}
NSString *s = [NSString stringWithFormat: @"An unhandled Ruby
exception occurred:\nName: %@\nReason: %@\n%@",
[[exc name] substringFromIndex: [@"RBException_" length]],
[exc reason],
bs ? (NSString*)bs : @""];
NSAlert *alert = [[NSAlert alloc] init];
[alert addButtonWithTitle: @"Continue"];
[alert addButtonWithTitle: @"Abort"];
[alert setMessageText: @"Ruby Exception"];
[alert setInformativeText: s];
if ([alert runModal] == NSAlertSecondButtonReturn) {
exit(1);
}
[alert release];
handling = NO;
}
-(void)run
{
while (1) {
NS_DURING
[super run];
NS_VOIDRETURN;
NS_HANDLER
if ([[localException name] hasPrefix: @"RBException_"]) {
[self notifyRubyException: localException];
} else {
[localException raise];
}
NS_ENDHANDLER;
}
}
@end
|