diff options
Diffstat (limited to 'osx/osx_fish_launcher.m')
-rw-r--r-- | osx/osx_fish_launcher.m | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/osx/osx_fish_launcher.m b/osx/osx_fish_launcher.m new file mode 100644 index 00000000..8b24d2ec --- /dev/null +++ b/osx/osx_fish_launcher.m @@ -0,0 +1,98 @@ +#import <Foundation/Foundation.h> +#import <CoreServices/CoreServices.h> +#import <Carbon/Carbon.h> +#import <stdlib.h> +#import <stdio.h> +#import <unistd.h> +#import <errno.h> +#import <sys/types.h> +#import <sys/stat.h> + + +// The path to the command file, which we'll delete on death (if it exists) +static char s_command_path[PATH_MAX]; + +static void die(const char *format, ...) { + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc('\n', stderr); + + if (s_command_path[0] != '\0') { + unlink(s_command_path); + } + + exit(EXIT_FAILURE); +} + +static void launch_fish_with_applescript(NSString *fish_binary_path) +{ + // load the script from a resource by fetching its URL from within our bundle + NSString *path = [[NSBundle mainBundle] pathForResource:@"launch_fish" ofType:@"scpt"]; + if (! path) die("Couldn't get path to launch_fish.scpt"); + + NSURL *url = [NSURL fileURLWithPath:path isDirectory:NO]; + if (! url) die("Couldn't get URL to launch_fish.scpt"); + + NSDictionary *errors = nil; + NSAppleScript *appleScript = [[NSAppleScript alloc] initWithContentsOfURL:url error:&errors]; + if (! appleScript) die("Couldn't load AppleScript"); + + // create the first parameter + NSAppleEventDescriptor *firstParameter = + [NSAppleEventDescriptor descriptorWithString:fish_binary_path]; + + // create and populate the list of parameters (in our case just one) + NSAppleEventDescriptor *parameters = [NSAppleEventDescriptor listDescriptor]; + [parameters insertDescriptor:firstParameter atIndex:1]; + + // create the AppleEvent target + ProcessSerialNumber psn = {0, kCurrentProcess}; + NSAppleEventDescriptor *target = + [NSAppleEventDescriptor + descriptorWithDescriptorType:typeProcessSerialNumber + bytes:&psn + length:sizeof(ProcessSerialNumber)]; + + // create an NSAppleEventDescriptor with the script's method name to call, + // this is used for the script statement: "on show_message(user_message)" + // Note that the routine name must be in lower case. + NSAppleEventDescriptor *handler = [NSAppleEventDescriptor descriptorWithString: + [@"launch_fish" lowercaseString]]; + + // create the event for an AppleScript subroutine, + // set the method name and the list of parameters + NSAppleEventDescriptor *event = + [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite + eventID:kASSubroutineEvent + targetDescriptor:target + returnID:kAutoGenerateReturnID + transactionID:kAnyTransactionID]; + [event setParamDescriptor:handler forKeyword:keyASSubroutineName]; + [event setParamDescriptor:parameters forKeyword:keyDirectObject]; + + // call the event in AppleScript + if (![appleScript executeAppleEvent:event error:&errors]) + { + // report any errors from 'errors' + NSLog(@"Oops: %@", errors); + } + + [appleScript release]; +} + +/* This approach asks Terminal to open a script that we control */ +int main(void) { + [[NSAutoreleasePool alloc] init]; + + /* Get the fish executable. Make sure it's absolute. */ + NSURL *fish_executable = [[NSBundle mainBundle] URLForResource:@"fish" withExtension:@"" subdirectory:@"base/bin"]; + if (! fish_executable) + die("Could not find fish executable in bundle"); + + launch_fish_with_applescript([fish_executable path]); + + /* If we succeeded, it will clean itself up */ + return 0; +} |