aboutsummaryrefslogtreecommitdiffhomepage
path: root/osx/osx_fish_launcher.m
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2012-07-08 15:20:39 -0700
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2012-07-08 15:20:39 -0700
commit4912967eabc447c31847566f03c50433015e9e9c (patch)
tree939f1d16354f08da8f11b4489e31b38a57022df9 /osx/osx_fish_launcher.m
parent76e1cda495d6e88cea383d387375588cdf9297bc (diff)
Large set of changes related to making fish relocatable, and improving the build and install story.
- etc/config.fish and share/config.fish are now "universal" and no longer reference install paths or need to be touched by autotools. They've been removed from config.fish.in to config.fish. - fish now attempts to determine __fish_datadir and __fish_sysconfdir relative to the path of the fish executable itself (typically by walking up one directory). This means that you can copy the directory hierarchy around and things will still work. The compiled-in paths are used as a backup. - The fish Xcode project now can build fish natively, without needing autotools. - Version bumped to 2.0
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;
+}