Permalink
Browse files

Implement "livereload:" URL scheme API

  • Loading branch information...
1 parent ea3fc0d commit 454717f49348bb85449a2311cc897263542daec8 @andreyvit andreyvit committed Oct 22, 2011
@@ -1,6 +1,8 @@
#import "LiveReloadAppDelegate.h"
+#import "Project.h"
#import "Workspace.h"
+#import "CompilationOptions.h"
#import "StatusItemController.h"
#import "MainWindowController.h"
#import "PreferencesWindowController.h"
@@ -29,6 +31,10 @@ @implementation LiveReloadAppDelegate
@synthesize mainWindowController=_mainWindowController;
@synthesize preferencesWindowController = _preferencesWindowController;
+- (void)awakeFromNib {
+ [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
+}
+
// just to make XDry happy; won't ever be deallocated
- (void)dealloc {
[super dealloc];
@@ -213,4 +219,80 @@ - (IBAction)sendFeedback:(id)sender {
}
+#pragma mark -
+
+- (void)handleCommand:(NSString *)command params:(NSDictionary *)params {
+ NSLog(@"Received command %@ with params %@", command, params);
+ if ([command isEqualToString:@"add"]) {
+ NSString *path = [[[params objectForKey:@"path"] stringByExpandingTildeInPath] stringByStandardizingPath];
+ BOOL isDir = NO;
+ if (path && [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir] && isDir) {
+ Project *project = [[Workspace sharedWorkspace] projectWithPath:path create:YES];
+
+ NSMutableSet *compilerIds = [NSMutableSet set];
+ [params enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
+ NSString *prefix = @"compiler-";
+ if ([key length] > [prefix length] && [[key substringToIndex:[prefix length]] isEqualToString:prefix]) {
+ NSString *compilerId = [key substringFromIndex:[prefix length]];
+ NSRange r = [compilerId rangeOfString:@"-" options:NSBackwardsSearch];
+ if (r.length > 0) {
+ compilerId = [compilerId substringToIndex:r.location];
+ [compilerIds addObject:compilerId];
+ }
+ }
+ }];
+
+ for (NSString *compilerId in compilerIds) {
+ Compiler *compiler = [[PluginManager sharedPluginManager] compilerWithUniqueId:compilerId];
+ if (compiler) {
+ NSString *mode = [params objectForKey:[NSString stringWithFormat:@"compiler-%@-mode", compilerId]];
+ if ([mode length] > 0) {
+ CompilationOptions *options = [project optionsForCompiler:compiler create:YES];
+ options.mode = CompilationModeFromNSString(mode);
+ }
+ } else {
+ NSLog(@"Ignoring options for unknown compiler: '%@'", compilerId);
+ }
+ }
+ } else {
+ NSLog(@"Refusing to add '%@' -- the directory does not exist.", path);
+ }
+ } else if ([command isEqualToString:@"remove"]) {
+ NSString *path = [[[params objectForKey:@"path"] stringByExpandingTildeInPath] stringByStandardizingPath];
+ Project *project = [[Workspace sharedWorkspace] projectWithPath:path create:NO];
+ if (project) {
+ [[Workspace sharedWorkspace] removeProjectsObject:project];
+ } else {
+ NSLog(@"Could not find an existing project at '%@'", path);
+ }
+ }
+}
+
+- (void)handleURLEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent {
+ NSString *url = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
+ NSString *prefix = @"livereload:";
+ if ([url length] < [prefix length] || ![[url substringToIndex:[prefix length]] isEqualToString:prefix])
+ return;
+ url = [url substringFromIndex:[prefix length]];
+
+ NSRange range = [url rangeOfString:@"?"];
+ NSMutableDictionary *params = [NSMutableDictionary dictionary];
+ NSString *command;
+ if (range.length > 0) {
+ command = [url substringToIndex:range.location];
+ NSString *query = [url substringFromIndex:range.location+1];
+ [[query componentsSeparatedByString:@"&"] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+ NSRange eq = [obj rangeOfString:@"="];
+ if (eq.length > 0) {
+ NSString *key = [obj substringToIndex:eq.location];
+ NSString *value = [[obj substringFromIndex:eq.location + 1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+ [params setObject:value forKey:key];
+ }
+ }];
+ } else {
+ command = url;
+ }
+ [self handleCommand:command params:params];
+}
+
@end
@@ -18,6 +18,8 @@ typedef enum {
CompilationModeMiddleware,
} CompilationMode;
+CompilationMode CompilationModeFromNSString(NSString *string);
+
@interface CompilationOptions : NSObject {
@private
@@ -14,6 +14,19 @@
NSString *DisplayModeNames[] = { @"disabled", @"compile", @"on-the-fly" };
+CompilationMode CompilationModeFromNSString(NSString *raw) {
+ if ([raw isEqualToString:@"compile"])
+ return CompilationModeCompile;
+ else if ([raw isEqualToString:@"middleware"])
+ return CompilationModeMiddleware;
+ else if ([raw isEqualToString:@"disabled"] || [raw isEqualToString:@"ignore"])
+ return CompilationModeDisabled;
+ else {
+ NSLog(@"Ignoring unknown value of mode: '%@'", raw);
+ return CompilationModeDisabled;
+ }
+}
+
@implementation CompilationOptions
@@ -42,16 +55,7 @@ - (id)initWithCompiler:(Compiler *)compiler memento:(NSDictionary *)memento {
else
_mode = CompilationModeDisabled;
} else if ((raw = [memento objectForKey:@"mode"])) {
- if ([raw isEqualToString:@"compile"])
- _mode = CompilationModeCompile;
- else if ([raw isEqualToString:@"middleware"])
- _mode = CompilationModeMiddleware;
- else if ([raw isEqualToString:@"disabled"] || [raw isEqualToString:@"ignore"])
- _mode = CompilationModeDisabled;
- else {
- NSLog(@"Ignoring unknown value of mode: '%@'", raw);
- _mode = CompilationModeDisabled;
- }
+ _mode = CompilationModeFromNSString(raw);
} else {
_mode = CompilationModeDisabled;
}
@@ -18,6 +18,8 @@
- (void)addProjectsObject:(Project *)project;
- (void)removeProjectsObject:(Project *)project;
+- (Project *)projectWithPath:(NSString *)path create:(BOOL)create;
+
@property(nonatomic, readonly, copy) NSArray *sortedProjects;
@property(nonatomic, getter=isMonitoringEnabled) BOOL monitoringEnabled;
@@ -110,6 +110,22 @@ - (NSArray *)sortedProjects {
return [[self.projects allObjects] sortedArrayUsingSelector:@selector(compareByDisplayPath:)];
}
+- (Project *)projectWithPath:(NSString *)path create:(BOOL)create {
+ path = [[[path stringByExpandingTildeInPath] stringByStandardizingPath] stringByResolvingSymlinksInPath];
+ for (Project *project in _projects) {
+ if ([[[project.path stringByStandardizingPath] stringByResolvingSymlinksInPath] isEqualToString:path]) {
+ return project;
+ }
+ }
+ if (create) {
+ Project *project = [[[Project alloc] initWithPath:path memento:nil] autorelease];
+ [self addProjectsObject:project];
+ return project;
+ } else {
+ return nil;
+ }
+}
+
#pragma mark -
#pragma mark File System Monitoring
@@ -23,7 +23,18 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
- <array/>
+ <array>
+ <dict>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>CFBundleURLName</key>
+ <string>com.livereload.LiveReloadControlProtocol</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>livereload</string>
+ </array>
+ </dict>
+ </array>
<key>CFBundleVersion</key>
<string>2.0.0.8</string>
<key>LSApplicationCategoryType</key>

0 comments on commit 454717f

Please sign in to comment.