aboutsummaryrefslogtreecommitdiffhomepage
path: root/osx/osx_fish_launcher.m
diff options
context:
space:
mode:
Diffstat (limited to 'osx/osx_fish_launcher.m')
-rw-r--r--osx/osx_fish_launcher.m98
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;
+}