Merge branch 'xcc-improvments'

This commit is contained in:
Antoine Mercadal committed 2011-11-10 14:10:45 +01:00
commit 0781e932c6
69 files changed
+3550 -5401

No files matched your search

@@ -134,9 +134,10 @@
9EEC448A135749D200615446 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
ORGANIZATIONNAME = "280 North, Inc.";
};
buildConfigurationList = 9EEC448D135749D200615446 /* Build configuration list for PBXProject "Another" */;
buildConfigurationList = 9EEC448D135749D200615446 /* Build configuration list for PBXProject "scrollview" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
@@ -323,7 +324,7 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9EEC448D135749D200615446 /* Build configuration list for PBXProject "Another" */ = {
9EEC448D135749D200615446 /* Build configuration list for PBXProject "scrollview" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9EEC44C3135749D300615446 /* Debug */,
@@ -339,6 +340,7 @@
9EEC44C7135749D300615446 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9EEC44C8135749D300615446 /* Build configuration list for PBXNativeTarget "AnotherTests" */ = {
isa = XCConfigurationList;
@@ -347,6 +349,7 @@
9EEC44CA135749D300615446 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
@@ -134,9 +134,10 @@
9EEC448A135749D200615446 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
ORGANIZATIONNAME = "280 North, Inc.";
};
buildConfigurationList = 9EEC448D135749D200615446 /* Build configuration list for PBXProject "Another" */;
buildConfigurationList = 9EEC448D135749D200615446 /* Build configuration list for PBXProject "NibAppRemixed" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
@@ -323,7 +324,7 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9EEC448D135749D200615446 /* Build configuration list for PBXProject "Another" */ = {
9EEC448D135749D200615446 /* Build configuration list for PBXProject "NibAppRemixed" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9EEC44C3135749D300615446 /* Debug */,
@@ -339,6 +340,7 @@
9EEC44C7135749D300615446 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9EEC44C8135749D300615446 /* Build configuration list for PBXNativeTarget "AnotherTests" */ = {
isa = XCConfigurationList;
@@ -347,6 +349,7 @@
9EEC44CA135749D300615446 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
+1 -1
View File
@@ -2,6 +2,6 @@
require("../common.jake");
// nib2cib uses fontinfo and capp uses nib2cib
subtasks(["fontinfo", "nib2cib", "capp", "NativeHost", "xcodecapp", "xcodecapp-cocoa"], ["build"/*, "clean", "clobber"*/]);
subtasks(["fontinfo", "nib2cib", "capp", "NativeHost", "XcodeCapp"], ["build"/*, "clean", "clobber"*/]);
subtasks(["fontinfo"], ["clean", "clobber"]);
File renamed without changes.
+75
View File
@@ -0,0 +1,75 @@
/*
* This file is a part of program XcodeCapp
* Copyright (C) 2011 Antoine Mercadal (<primalmotion@archipelproject.org>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#import <CoreServices/CoreServices.h>
#import "PRHEmptyGrowlDelegate.h"
#import "TNXCodeCapp.h"
@interface AppController : NSObject <NSMenuDelegate>
{
IBOutlet NSMenu *statusMenu;
IBOutlet NSMenuItem *menuItemOpenXCode;
IBOutlet NSMenuItem *menuItemStartStop;
IBOutlet NSPanel *errorsPanel;
IBOutlet NSTableView *errorsTable;
IBOutlet NSPanel *aboutWindow;
IBOutlet NSWindow *helpWindow;
IBOutlet NSTextView *helpTextView;
IBOutlet NSTextField *labelVersion;
IBOutlet NSPopUpButton *buttonPreferencesAPIMode;
IBOutlet NSButton *checkBoxPreferencesReactMode;
IBOutlet NSUserDefaultsController *preferencesController;
IBOutlet TNXCodeCapp *xcc;
IBOutlet NSWindow *windowDebug;
IBOutlet NSMenuItem *menuDebug;
NSImage *_iconActive;
NSImage *_iconInactive;
NSImage *_iconWorking;
NSStatusItem *_statusItem;
PRHEmptyGrowlDelegate *growlDelegateRef;
}
@property BOOL supportsFileModeListening;
@property (assign) TNXCodeCapp *xcc;
+ (AppController *)sharedAppController;
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem;
- (void)registerDefaults;
- (void)updateErrorTable;
- (void)growlWithTitle:(NSString *)aTitle message:(NSString *)aMessage;
- (void)openCenteredWindow:(NSWindow *)aWindow;
- (IBAction)chooseFolder:(id)aSender;
- (IBAction)openErrors:(id)sender;
- (IBAction)clearErrors:(id)sender;
- (IBAction)openXCode:(id)aSender;
- (IBAction)stopListener:(id)aSender;
- (IBAction)openHelp:(id)aSender;
- (IBAction)openAbout:(id)aSender;
- (IBAction)updatePreferences:(id)aSender;
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(int)aRow;
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView;
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView;
@end
+380
View File
@@ -0,0 +1,380 @@
/*
* This file is a part of program XcodeCapp
* Copyright (C) 2011 Antoine Mercadal (<primalmotion@archipelproject.org>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <AppKit/NSApplication.h>
#import "AppController.h"
#include "macros.h"
AppController *SharedAppControllerInstance = nil;
@implementation AppController
@synthesize supportsFileModeListening;
@synthesize xcc;
+ (AppController *)sharedAppController
{
return SharedAppControllerInstance;
}
#pragma mark -
#pragma mark Initialization
/*!
Called when NIB is ready
*/
- (void)awakeFromNib
{
SharedAppControllerInstance = self;
if (!growlDelegateRef)
growlDelegateRef = [[[PRHEmptyGrowlDelegate alloc] init] autorelease];
[GrowlApplicationBridge setGrowlDelegate:growlDelegateRef];
NSBundle *bundle = [NSBundle mainBundle];
[labelVersion setStringValue:[NSString stringWithFormat:@"Version %@", [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]]];
[self registerDefaults];
_iconInactive = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"xcodecapp-icon-inactive" ofType:@"png"]];
_iconActive = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"xcodecapp-icon-active" ofType:@"png"]];
_iconWorking = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"xcodecapp-icon-working" ofType:@"png"]];
[_iconActive setSize:NSMakeSize(14.0, 16.0)];
[_iconInactive setSize:NSMakeSize(14.0, 16.0)];
[_iconWorking setSize:NSMakeSize(14.0, 16.0)];
_statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
[_statusItem setMenu:statusMenu];
[_statusItem setImage:_iconInactive];
[_statusItem setHighlightMode:YES];
[statusMenu setDelegate:self];
if ([[NSUserDefaults standardUserDefaults] integerForKey:@"FirstLaunch"])
{
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:0] forKey:@"FirstLaunch"];
[self openHelp:self];
}
[xcc setDelegate:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(XCodeCappConversionDidStart:) name:XCCConversionStartNotification object:xcc];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(XCodeCappConversionDidStop:) name:XCCConversionStopNotification object:xcc];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(XCodeCappPopulateProject:) name:XCCDidPopulateProjectNotification object:xcc];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(XCodeCappListeningDidStart:) name:XCCListeningStartNotification object:xcc];
[helpTextView setTextContainerInset:NSSizeFromCGSize(CGSizeMake(10.0, 10.0))];
[xcc start];
}
/*!
Checks if aplication should show the debug window
*/
- (void)applicationDidFinishLaunching:(NSNotification *)notif
{
CGEventRef event = CGEventCreate(NULL);
CGEventFlags modifiers = CGEventGetFlags(event);
CFRelease(event);
if (modifiers & kCGEventFlagMaskAlternate)
{
[statusMenu insertItem:menuDebug atIndex:6];
}
}
/*!
Register the application defaults
*/
- (void)registerDefaults
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSNumber *streamEventIdSinceNow = [NSNumber numberWithUnsignedLongLong:kFSEventStreamEventIdSinceNow];
NSMutableDictionary *appDefaults = [NSMutableDictionary new];
[appDefaults setObject:streamEventIdSinceNow forKey:@"lastEventId"];
[appDefaults setObject:[NSNumber numberWithInt:1] forKey:@"FirstLaunch"];
[appDefaults setObject:[NSNumber numberWithInt:0] forKey:@"XCCAPIMode"];
[appDefaults setObject:[NSNumber numberWithInt:1] forKey:@"XCCReactMode"];
[appDefaults setObject:[NSNumber numberWithInt:1] forKey:@"XCCReopenLastProject"];
[defaults registerDefaults:appDefaults];
}
#pragma mark -
#pragma mark Notification handlers
/*!
Handle cleaning operation when application will stop.
It will stop the FSEvent listener, and store the last event id
*/
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
{
[xcc clear];
return NSTerminateNow;
}
/*!
Called when XCC start a conversion
@param aNotification the notification
*/
- (void)XCodeCappConversionDidStart:(NSNotification *)aNotification
{
[_statusItem setImage:_iconWorking];
}
/*!
Called when XCC finish a conversion
@param aNotification the notification
*/
- (void)XCodeCappConversionDidStop:(NSNotification *)aNotification
{
[_statusItem setImage:_iconActive];
}
/*!
Called when XCC has populated a project
@param aNotification the notification
*/
- (void)XCodeCappPopulateProject:(NSNotification *)aNotification
{
[self growlWithTitle:@"Project loaded" message:[[[aNotification userInfo] objectForKey:@"URL"] path]];
}
/*!
Called when XCC start a to listen to a project
@param aNotification the notification
*/
- (void)XCodeCappListeningDidStart:(NSNotification *)aNotification
{
[_statusItem setImage:_iconActive];
[menuItemStartStop setTitle:[NSString stringWithFormat:@"Stop Listening to “%@”", [xcc currentProjectName]]];
[menuItemStartStop setAction:@selector(stopListener:)];
[self growlWithTitle:@"Listening to project" message:[[xcc currentProjectURL] path]];
}
#pragma mark -
#pragma mark Utilities
/*!
Simple growl wrapper
@param aTitle the growl title
@param aMessage the growl message
*/
- (void)growlWithTitle:(NSString *)aTitle message:(NSString *)aMessage
{
[GrowlApplicationBridge notifyWithTitle:aTitle
description:aMessage
notificationName:@"DefaultNotifications"
iconData:nil
priority:0
isSticky:NO
clickContext:nil];
}
#pragma mark -
#pragma mark Actions
/*!
Save preferences
@param aSender the sender of the action
*/
- (IBAction)updatePreferences:(id)aSender
{
[preferencesController save:aSender];
NSLog(@"Preferences change notified");
[xcc configure];
}
/*!
Open the folder chooser and eventually start to listen
@param aSender the sender of the action
*/
- (IBAction)chooseFolder:(id)aSender
{
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setCanChooseDirectories:YES];
[openPanel setCanCreateDirectories:YES];
[openPanel setTitle:@"Choose Cappuccino Project"];
[openPanel setCanChooseFiles:NO];
if ([openPanel runModal] != NSFileHandlingPanelOKButton)
return;
[xcc listenProjectAtPath:[NSString stringWithFormat:@"%@/", [[[openPanel URLs] objectAtIndex:0] path]]];
}
/*!
Stop listening to a project
@param aSender the sender of the action
*/
- (IBAction)stopListener:(id)aSender
{
[xcc clear];
[_statusItem setImage:_iconInactive];
[menuItemStartStop setTitle:@"Listen to Project…"];
[menuItemStartStop setAction:@selector(chooseFolder:)];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"LastOpenedPath"];
}
/*!
Open the xCode support project in xCode
@param aSender the sender of the action
*/
- (IBAction)openXCode:(id)aSender
{
if (![xcc currentProjectURL])
return;
DLog(@"Opening Xcode project at URL: '%@'", [[xcc XCodeSupportProject] path]);
system([[NSString stringWithFormat:@"open \"%@\"", [[xcc XCodeSupportProject] path]] UTF8String]);
}
/*!
reload error table data and show it
@param aSender the sender of the action
*/
- (void)updateErrorTable
{
[errorsTable reloadData];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
[errorsPanel orderFront:self];
}
/*!
Open the errors window
@param aSender the sender of the action
*/
- (IBAction)openErrors:(id)aSender
{
[self openCenteredWindow:errorsPanel];
}
/*!
Clear all errors in errors table
@param aSender the sender of the action
*/
- (IBAction)clearErrors:(id)sender
{
[[xcc errorList] removeAllObjects];
[errorsTable reloadData];
}
/*!
Open the help file
@param aSender the sender of the action
*/
- (IBAction)openHelp:(id)aSender
{
[helpTextView readRTFDFromFile:[[NSBundle mainBundle] pathForResource:@"help" ofType:@"rtfd"]];
[self openCenteredWindow:helpWindow];
}
/*!
Open the about window
@param aSender the sender of the action
*/
- (IBAction)openAbout:(id)aSender
{
[self openCenteredWindow:aboutWindow];
}
/*!
Open the preferences window
@param aSender the sender of the action
*/
- (IBAction)openPreferences:(id)aSender
{
[self openCenteredWindow:windowDebug];
}
/*!
Open a centered window.
*/
- (void)openCenteredWindow:(NSWindow *)aWindow
{
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
[aWindow center];
[aWindow makeKeyAndOrderFront:nil];
}
#pragma mark -
#pragma mark Delegates
- (BOOL)validateMenuItem:(NSMenuItem *)aMenuItem
{
if (aMenuItem == menuItemOpenXCode)
return !![xcc currentProjectURL];
return YES;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [[xcc errorList] count];
}
- (id)tableView:(NSTableView*)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
return [[xcc errorList] objectAtIndex:row];
}
- (void)tableViewColumnDidResize:(NSNotification *)tableView
{
[errorsTable noteHeightOfRowsWithIndexesChanged:
[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [[xcc errorList] count])]];
}
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(int)aRow
{
// Get column you want - first in this case:
NSTableColumn *tabCol = [[tableView tableColumns] objectAtIndex:0];
float width = [tabCol width];
NSRect r = NSMakeRect(0,0,width,1000.0);
NSCell *cell = [tabCol dataCellForRow:aRow];
NSString *content = [[xcc errorList] objectAtIndex:aRow];
[cell setObjectValue:content];
float height = [cell cellSizeForBounds:r].height;
if (height <= 0)
height = 16.0; // Ensure miniumum height is 16.0
return height;
}
@end
File diff suppressed because it is too large. Load diff
Binary file not shown.
+63
View File
@@ -0,0 +1,63 @@
/*
* This file is a part of program xcodecapp-cocoa
* Copyright (C) 2011 Antoine Mercadal (primalmotion@archipelproject.org)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "FSEventCallback.h"
/*!
This is the FSEvent callback
*/
void fsevents_callback(ConstFSEventStreamRef streamRef,
void *userData,
size_t numEvents,
void *eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
TNXCodeCapp *xcc = (TNXCodeCapp *)userData;
size_t i;
for(i = 0; i < numEvents; i++)
{
NSString *path = [(NSArray *)eventPaths objectAtIndex:i];
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
// kFSEventStreamEventFlagItemIsFile = 0x00010000
if (!(eventFlags[i] & 0x00010000)
|| [xcc isPathMatchingIgnoredPaths:path]
|| (![xcc isXIBFile:path] && ![xcc isObjJFile:path] && ![xcc isXCCIgnoreFile:path]))
continue;
// kFSEventStreamEventFlagItemRemoved = 0x00000200
if (eventFlags[i] & 0x00000200)
{
[xcc handleFileRemoval:path];
}
else
{
NSLog(@"this file has been modified or created");
[xcc handleFileModification:path notify:YES];
}
#else
NSArray *subpaths = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
for(NSString *currentPath in subpaths)
[xcc handleFileModification:currentPath notify:YES];
#endif
[xcc updateLastEventId:eventIds[i]];
}
}
+40
View File
@@ -0,0 +1,40 @@
/*
* This file is a part of program XcodeCapp
* Copyright (C) 2011 Antoine Mercadal (<primalmotion@archipelproject.org>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef xcodecapp_cocoa_FSEventCallback_h
#define xcodecapp_cocoa_FSEventCallback_h
#import "TNXCodeCapp.h"
#import <Cocoa/Cocoa.h>
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_6
# define kFSEventStreamCreateFlagFileEvents 0x00000010
# define kFSEventStreamEventFlagItemIsFile 0x00010000
# define kFSEventStreamEventFlagItemRemoved 0x00000200
# define kFSEventStreamEventFlagItemCreated 0x00000200
# define kFSEventStreamEventFlagItemModified 0x00001000
# define kFSEventStreamEventFlagItemInodeMetaMod 0x00000400
# define kFSEventStreamEventFlagItemRenamed 0x00000800
# define kFSEventStreamEventFlagItemFinderInfoMod 0x00002000
# define kFSEventStreamEventFlagItemChangeOwner 0x00004000
# define kFSEventStreamEventFlagItemXattrMod 0x00008000
#endif
void fsevents_callback(ConstFSEventStreamRef, void*, size_t, void*, const FSEventStreamEventFlags*, const FSEventStreamEventId*);
#endif
+138
View File
@@ -0,0 +1,138 @@
/*
* This file is a part of program XcodeCapp
* Copyright (C) 2011 Antoine Mercadal (<primalmotion@archipelproject.org>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "AppController.h"
#import "FSEventCallback.h"
#import "macros.h"
/*!
This is the FSEvent callback for 10.7
*/
void fsevents_callback(ConstFSEventStreamRef streamRef,
void *userData,
size_t numEvents,
void *eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
TNXCodeCapp *xcc = (TNXCodeCapp *)userData;
BOOL useFileBasedListening = [xcc supportsFileBasedListening];
size_t i;
for (i = 0; i < numEvents; i++)
{
[xcc updateLastEventId:eventIds[i]];
FSEventStreamEventFlags flags = eventFlags[i];
NSString *path = [[(NSArray *)eventPaths objectAtIndex:i] stringByStandardizingPath];
if (useFileBasedListening)
{
if (flags & kFSEventStreamEventFlagItemIsFile &&
flags & kFSEventStreamEventFlagItemRemoved)
{
[xcc tidyShadowedFiles];
continue;
}
if (!(flags & kFSEventStreamEventFlagItemIsFile) ||
[xcc isPathMatchingIgnoredPaths:path] ||
(![xcc isXIBFile:path] && ![xcc isObjJFile:path] && ![xcc isXCCIgnoreFile:path]))
{
continue;
}
else if (flags & kFSEventStreamEventFlagItemRemoved)
{
DLog(@"event type: kFSEventStreamEventFlagItemRemoved for path %@", path);
[xcc handleFileRemoval:path];
}
else if (flags & kFSEventStreamEventFlagItemCreated ||
flags & kFSEventStreamEventFlagItemModified)
{
DLog(@"event type: kFSEventStreamEventFlagItemCreated or kFSEventStreamEventFlagItemModified for path %@", path);
[xcc handleFileModification:path notify:YES];
}
else if ([xcc reactToInodeModification] &&
(flags & kFSEventStreamEventFlagItemFinderInfoMod ||
flags & kFSEventStreamEventFlagItemXattrMod ||
flags & kFSEventStreamEventFlagItemChangeOwner))
{
DLog(@"event type: %@ for path %@", flags, path);
[xcc handleFileModification:path notify:YES];
}
else if ([xcc reactToInodeModification] &&
flags & kFSEventStreamEventFlagItemInodeMetaMod)
{
DLog(@"event type: kFSEventStreamEventFlagItemInodeMetaMod for path %@", path);
[xcc handleFileModification:path notify:YES];
}
else if (flags & kFSEventStreamEventFlagItemRenamed)
{
if (![[NSFileManager defaultManager] fileExistsAtPath:path])
{
DLog(@"event type: kFSEventStreamEventFlagItemRenamed for path %@ (removed origin)", path);
[xcc handleFileRemoval:path];
}
else
{
DLog(@"event type: kFSEventStreamEventFlagItemRenamed for path %@ (added destination)", path);
[xcc handleFileModification:path notify:YES];
}
}
}
else
{
BOOL isDir = NO;
[[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir];
// If for some reasons the path is not a directory,
// we don't want to deal with it in this mode.
if (!isDir)
continue;
[xcc tidyShadowedFiles];
NSArray *subpaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
for (NSString *subpath in subpaths)
{
NSString *fullPath = [[NSString stringWithFormat:@"%@/%@", path, subpath] stringByStandardizingPath];
if ([xcc isPathMatchingIgnoredPaths:fullPath]
|| (![xcc isXIBFile:fullPath] && ![xcc isObjJFile:fullPath] && ![xcc isXCCIgnoreFile:fullPath]))
continue;
NSDate *lastModifiedDate = [xcc lastModificationDateForPath:fullPath];
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:nil];
NSDate *fileModDate = [fileAttributes objectForKey:NSFileModificationDate];
if ([fileModDate compare:lastModifiedDate] == NSOrderedDescending)
{
[xcc updateLastModificationDate:fileModDate forPath:fullPath];
[xcc handleFileModification:fullPath notify:YES];
}
}
}
}
}
@@ -7,24 +7,28 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>xcodecapp-cocoa.icns</string>
<string>XcodeCapp.icns</string>
<key>CFBundleIdentifier</key>
<string>org.cappuccino.xcodecapp-cocoa</string>
<string>org.cappuccino.xcodecapp</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<string>2.0</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSUIElement</key>
<true/>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSUIElement</key>
<true/>
</dict>
</plist>
@@ -4,7 +4,7 @@ require("../../common.jake");
var OS = require("os"),
task = require("jake").task,
stream = require("narwhal/term").stream,
applicationName = "xcodecapp-cocoa.app";
applicationName = "XcodeCapp.app";
task ("build", function()
{
@@ -19,8 +19,8 @@ task ("build", function()
rm_rf(supportPath);
FILE.mkdirs(supportPath);
cp_r(FILE.join("build", "Release", "xcodecapp-cocoa.app"), supportPath);
FILE.chmod(FILE.join(supportPath, "Contents", "MacOS", "xcodecapp-cocoa"), 0755);
cp_r(FILE.join("build", "Release", "XcodeCapp.app"), supportPath);
FILE.chmod(FILE.join(supportPath, "Contents", "MacOS", "XcodeCapp"), 0755);
OS.system(["ln", "-sf", supportPath, installPath]);
}
@@ -1,6 +1,6 @@
//
// PRHEmptyGrowlDelegate.h
// xcodecapp-cocoa
// XcodeCapp
//
// Created by Andrea D'Amore on 19/06/11.
// Copyright 2011 by author. All rights reserved.
@@ -1,6 +1,6 @@
//
// PRHEmptyGrowlDelegate.h
// xcodecapp-cocoa
// XcodeCapp
//
// Created by Andrea D'Amore on 19/06/11.
// Copyright 2011 by author. All rights reserved.
File renamed without changes.
+98
View File
@@ -0,0 +1,98 @@
/*
* This file is a part of program XcodeCapp
* Copyright (C) 2011 Antoine Mercadal (<primalmotion@archipelproject.org>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
#import "PRHEmptyGrowlDelegate.h"
#import "FSEventCallback.h"
extern NSString * const XCCDidPopulateProjectNotification;
extern NSString * const XCCConversionStartNotification;
extern NSString * const XCCConversionStopNotification;
extern NSString * const XCCListeningStartNotification;
@interface TNXCodeCapp : NSObject
{
FSEventStreamRef stream;
NSFileManager *fm;
NSMutableArray *errorList;
NSMutableSet *ignoredFilePaths;
NSNumber *lastEventId;
NSString *currentAPIMode;
NSString *currentProjectName;
NSString *parserPath;
NSString *XCodeSupportPBXPath;
NSString *XCodeSupportProjectName;
NSString *XCodeTemplatePBXPath;
NSString *profilePath;
NSURL *currentProjectURL;
NSURL *XCodeSupportFolder;
NSURL *XCodeSupportProject;
NSURL *XCodeSupportProjectSources;
PRHEmptyGrowlDelegate *growlDelegateRef;
NSObject *delegate;
NSDate *appStartedTimestamp;
NSMutableDictionary *pathModificationDates;
BOOL supportsFileBasedListening;
BOOL reactToInodeModification;
BOOL isListening;
BOOL isUsingFileLevelAPI;
BOOL supportFileLevelAPI;
}
@property (retain) NSObject* delegate;
@property (retain) NSMutableArray* errorList;
@property (retain) NSURL* XCodeSupportProject;
@property (retain) NSURL* currentProjectURL;
@property (retain) NSString* currentProjectName;
@property (retain) NSString* currentAPIMode;
@property BOOL supportsFileBasedListening;
@property BOOL reactToInodeModification;
@property BOOL isListening;
@property BOOL supportFileLevelAPI;
@property BOOL isUsingFileLevelAPI;
- (BOOL)isObjJFile:(NSString*)path;
- (void)computeIgnoredPaths;
- (BOOL)isPathMatchingIgnoredPaths:(NSString*)aPath;
- (BOOL)isXIBFile:(NSString *)path;
- (BOOL)isXCCIgnoreFile:(NSString *)path;
- (BOOL)prepareXCodeSupportProject;
- (NSURL*)shadowURLForSourceURL:(NSURL*)aSourceURL;
- (NSURL*)sourceURLForShadowName:(NSString *)aString;
- (void)handleFileModification:(NSString*)fullPath notify:(BOOL)shouldNotify;
- (void)handleFileRemoval:(NSString*)fullPath;
- (void)initializeEventStreamWithPath:(NSString*)aPath;
- (void)stopEventStream;
- (void)updateLastEventId:(uint64_t)eventId;
- (void)listenProjectAtPath:(NSString *)path;
- (void)clear;
- (void)start;
- (void)configure;
- (void)tidyShadowedFiles;
@end
@interface TNXCodeCapp (SnowLeopard)
- (void)updateLastModificationDate:(NSDate *)date forPath:(NSString *)path;
- (NSDate*)lastModificationDateForPath:(NSString *)path;
@end
+708
View File
@@ -0,0 +1,708 @@
/*
* This file is a part of program XcodeCapp
* Copyright (C) 2011 Antoine Mercadal (<primalmotion@archipelproject.org>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "TNXCodeCapp.h"
#include "macros.h"
NSString * const XCCDidPopulateProjectNotification = @"XCCDidPopulateProjectNotification";
NSString * const XCCConversionStartNotification = @"XCCConversionStartNotification";
NSString * const XCCConversionStopNotification = @"XCCConversionStopNotification";
NSString * const XCCListeningStartNotification = @"XCCListeningStartNotification";
@implementation TNXCodeCapp
@synthesize delegate;
@synthesize errorList;
@synthesize XCodeSupportProject;
@synthesize currentProjectURL;
@synthesize currentProjectName;
@synthesize supportsFileBasedListening;
@synthesize reactToInodeModification;
@synthesize currentAPIMode;
@synthesize isListening;
@synthesize supportFileLevelAPI;
@synthesize isUsingFileLevelAPI;
#pragma mark -
#pragma mark Initialization
/*!
Initialize the AppController
*/
- (id)init
{
self = [super init];
if (self)
{
errorList = [NSMutableArray arrayWithCapacity:10];
fm = [NSFileManager defaultManager];
ignoredFilePaths = [NSMutableSet new];
parserPath = [[NSBundle mainBundle] pathForResource:@"parser" ofType:@"j"];
lastEventId = [[NSUserDefaults standardUserDefaults] objectForKey:@"lastEventId"];
appStartedTimestamp = [NSDate date];
[self setIsListening:NO];
[self setIsUsingFileLevelAPI:NO];
SInt32 versionMajor = 0;
SInt32 versionMinor = 0;
Gestalt(gestaltSystemVersionMajor, &versionMajor);
Gestalt(gestaltSystemVersionMinor, &versionMinor);
[self setSupportFileLevelAPI:versionMajor >= 10 && versionMinor >= 7];
// Uncomment to simulate 10.6 mode
[self setSupportFileLevelAPI:NO];
[self configure];
if([fm fileExistsAtPath:[@"~/.bash_profile" stringByExpandingTildeInPath]])
profilePath = [@"source ~/.bash_profile" stringByExpandingTildeInPath];
else if([fm fileExistsAtPath:[@"~/.profile" stringByExpandingTildeInPath]])
profilePath = [@"source ~/.profile" stringByExpandingTildeInPath];
else if([fm fileExistsAtPath:[@"~/.bashrc" stringByExpandingTildeInPath]])
profilePath = [@"source ~/.bashrc" stringByExpandingTildeInPath];
else if([fm fileExistsAtPath:[@"~/.zshrc" stringByExpandingTildeInPath]])
profilePath = [@"source ~/.zshrc" stringByExpandingTildeInPath];
else
{
NSAlert *alert = [NSAlert alertWithMessageText:@"Cannot find any valid profile file."
defaultButton:@"OK"
alternateButton:nil
otherButton:nil
informativeTextWithFormat:@"Neither ~/.bash_profile, ~/.profile, ~/.bashrc nor ~/.zshrc can be found.\n\nWithout this XcodeCapp cannot locate nib2cib.\n\nIf you notice any errors or strange behaviour, please look at the system log for messages and open a ticket."];
[alert runModal];
profilePath = @"";
}
}
return self;
}
- (void)start
{
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"XCCReopenLastProject"])
return;
NSString *lastOpenedPath = [[NSUserDefaults standardUserDefaults] objectForKey:@"LastOpenedPath"];
if (lastOpenedPath)
{
if ([fm fileExistsAtPath:lastOpenedPath])
{
[self listenProjectAtPath:[NSString stringWithFormat:@"%@/", lastOpenedPath]];
}
else
{
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"LastOpenedPath"];
}
}
}
/*!
Initializes the FSEvent stream
@param aPath the path of the folder to listen
*/
- (void)initializeEventStreamWithPath:(NSString*)aPath
{
if ([self isListening])
return;
[self stopEventStream];
NSArray *pathsToWatch = [NSArray arrayWithObject:aPath];
void *appPointer = (void *)self;
FSEventStreamContext context = {0, appPointer, NULL, NULL, NULL};
CFTimeInterval latency = 2.0;
FSEventStreamCreateFlags flags = 0;
if (supportsFileBasedListening)
{
DLog(@"Initializing the FSEventStream at file level (clean)");
flags = kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents;
}
else
{
NSLog(@"Initializing the FSEventStream at folder level (dirty)");
flags = kFSEventStreamCreateFlagUseCFTypes;
}
stream = FSEventStreamCreate(NULL, &fsevents_callback, &context, (CFArrayRef) pathsToWatch,
[lastEventId unsignedLongLongValue], latency, flags);
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
FSEventStreamStart(stream);
[self setIsListening:YES];
}
#pragma mark -
#pragma mark Utilities
/*!
Stop listening the FSEvent stream if active
*/
- (void)stopEventStream
{
if (stream)
{
FSEventStreamStop(stream);
FSEventStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
FSEventStreamInvalidate(stream);
FSEventStreamRelease(stream);
stream = NULL;
}
[self setIsListening:NO];
}
/*!
Stops and clear the worker
*/
- (void)clear
{
if (lastEventId && [lastEventId longLongValue] != 0)
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:lastEventId forKey:@"lastEventId"];
[defaults synchronize];
}
currentProjectURL = nil;
currentProjectName = nil;
[ignoredFilePaths removeAllObjects];
[self stopEventStream];
}
/*!
Choose the API mode according to default
*/
- (void)configure
{
if (![self supportFileLevelAPI])
{
DLog(@"System doesn't support file level API");
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:2] forKey:@"XCCAPIMode"];
}
switch ([[NSUserDefaults standardUserDefaults] integerForKey:@"XCCAPIMode"])
{
case 0:
supportsFileBasedListening = [self supportFileLevelAPI] ? YES : NO;
break;
case 1:
supportsFileBasedListening = YES;
break;
case 2:
supportsFileBasedListening = NO;
break;
}
if (supportsFileBasedListening)
{
DLog(@"using 10.7+ mode listening (clean)");
[self setCurrentAPIMode:@"File level (Lion)"];
[self setIsUsingFileLevelAPI:YES];
reactToInodeModification = [[NSUserDefaults standardUserDefaults] boolForKey:@"XCCReactMode"];
}
else
{
DLog(@"using 10.6 mode listening (dirty)");
reactToInodeModification = NO;
[self setCurrentAPIMode:@"Folder level (Snow Leopard)"];
[self setIsUsingFileLevelAPI:NO];
}
}
/*!
Update the last event ID. We use a method because
This is called from outside the class, in the FSEvent callback
@param eventId the current event ID value
*/
- (void)updateLastEventId:(uint64_t)eventId
{
lastEventId = [NSNumber numberWithUnsignedLongLong:eventId];
}
/*!
Run a NSTask with the given arguments
@param arguments NSArray containing the NSTask arguments
@return NSarray containing the return code (int) and the eventual response (string)
*/
- (NSArray *)runTask:(NSArray *)arguments
{
NSTask *task;
NSData *stdOut;
NSString *response;
NSNumber *status;
task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/bash"];
[task setArguments: arguments];
[task setStandardOutput:[NSPipe pipe]];
[task launch];
[task waitUntilExit];
stdOut = [[[task standardOutput] fileHandleForReading] availableData];
response = [[NSString alloc] initWithData:stdOut encoding:NSUTF8StringEncoding];
status = [NSNumber numberWithInt:[task terminationStatus]];
return [NSArray arrayWithObjects:status, response, nil];
}
/*!
Handle a file modification. If it's a .J or XIB or NIB, it will
perform the according conversion. If it's .xcodecapp-ignore, it will
update the list of ignored files.
@param fullPath the full path of the modified file
@param shouldNotify if YES, Growl notifications will be displayed
*/
- (void)handleFileModification:(NSString*)fullPath notify:(BOOL)shouldNotify
{
if ([self isPathMatchingIgnoredPaths:fullPath] || ![fm fileExistsAtPath:fullPath])
return;
DLog(@"Parsing modified file: %@", fullPath);
NSArray *arguments = nil;
NSString *successTitle = nil;
NSString *successMsg = nil;
NSString *response = nil;
NSNumber *status = [NSNumber numberWithInt:0];
NSString *splitPath = [fullPath substringFromIndex:[[currentProjectURL path] length] + 1];
NSString *shadowPath = [[self shadowURLForSourceURL:[NSURL URLWithString:[fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]] path];
DLog(@"Shadow path: %@", shadowPath);
if ([self isXIBFile:fullPath] || [self isObjJFile:fullPath] || [self isXCCIgnoreFile:fullPath])
{
[[NSNotificationCenter defaultCenter] postNotificationName:XCCConversionStartNotification object:self];
if ([self isXIBFile:fullPath])
{
arguments = [NSArray arrayWithObjects: @"-c", [NSString stringWithFormat:@"(%@; nib2cib '%@';) 2>&1", profilePath, fullPath],@"",nil];
successTitle = @"XIB converted";
successMsg = splitPath;
}
else if ([self isObjJFile:fullPath])
{
arguments = [NSArray arrayWithObjects: @"-c", [NSString stringWithFormat:@"(%@; objj '%@' '%@' '%@';) 2>&1", profilePath, parserPath, fullPath, shadowPath],@"",nil];
successTitle = @"Objective-J source processed";
successMsg = splitPath;
}
else if ([self isXCCIgnoreFile:fullPath])
{
[self computeIgnoredPaths];
successTitle = @".xcodecapp-ignore processed";
successMsg = @"Ignored files list updated";
arguments = nil;
}
// Run the task and get the response if needed
if (arguments)
{
DLog(@"Running task...");
NSArray *statusInfo = [self runTask:arguments];
status = [statusInfo objectAtIndex:0];
response = [statusInfo objectAtIndex:1];
DLog(@"Task result/response: %@/%@", status, response);
}
if ([status intValue] == 0 && shouldNotify)
{
[delegate performSelector:@selector(growlWithTitle:message:) withObject:successTitle withObject:successMsg];
}
else if (![status intValue] == 0)
{
if (response)
[errorList addObject:response];
[delegate performSelector:@selector(growlWithTitle:message:) withObject:@"Error processing file" withObject:splitPath];
}
[[NSNotificationCenter defaultCenter] postNotificationName:XCCConversionStopNotification object:self];
DLog(@"Processed: %@", fullPath);
}
}
/*!
Handle a file deletion. If it's a .J, it will
remove the shadowed .h file. If it's .xcodecapp-ignore
it will reset the list of ignored files.
@param fullPath the full path of the modified file
@param shouldNotify if YES, Growl notifications will be displayed
*/
- (void)handleFileRemoval:(NSString*)fullPath
{
if ([self isPathMatchingIgnoredPaths:fullPath] || [fm fileExistsAtPath:fullPath])
return;
if ([self isObjJFile:fullPath])
{
NSString *shadowPath = [[self shadowURLForSourceURL:[NSURL URLWithString:[fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]] path];
[fm removeItemAtPath:shadowPath error:nil];
DLog(@"Removing shadow file: %@", shadowPath);
}
else if ([self isXCCIgnoreFile:fullPath])
{
[self computeIgnoredPaths];
}
}
/*!
Check if given full path is Objective-J file
@param path the path to check
@return YES or NO
*/
- (BOOL)isObjJFile:(NSString *)path
{
return [[[path pathExtension] uppercaseString] isEqual:@"J"];
}
/*!
Check if given full path is XIB or NIB file
@param path the path to check
@return YES or NO
*/
- (BOOL)isXIBFile:(NSString *)path
{
path = [[path pathExtension] uppercaseString];
return [path isEqual:@"XIB"] || [path isEqual:@"NIB"];
}
/*!
Check if given full path is the .xcodecapp-ignore file
@param path the path to check
@return YES or NO
*/
- (BOOL)isXCCIgnoreFile:(NSString *)path
{
path = [path lastPathComponent];
return [path isEqual:@".xcodecapp-ignore"];
}
/*!
Check if .xCodeSupport needs to be initialized.
If not needed, check that all J files are mirrored. If no,
then launch conversion for missing mirrored h files
@return YES or NO
*/
- (BOOL)prepareXCodeSupportProject
{
XCodeSupportProjectName = [NSString stringWithFormat:@"%@.xcodeproj/", currentProjectName];
XCodeTemplatePBXPath = [[NSBundle mainBundle] pathForResource:@"project.pbxproj" ofType:@"sample"];
XCodeSupportFolder = [NSURL URLWithString:@".xCodeSupport/" relativeToURL:currentProjectURL];
XCodeSupportProject = [NSURL URLWithString:XCodeSupportProjectName relativeToURL:XCodeSupportFolder];
XCodeSupportProjectSources = [NSURL URLWithString:@"Sources/" relativeToURL:XCodeSupportFolder];
XCodeSupportPBXPath = [NSString stringWithFormat:@"%@/project.pbxproj", [XCodeSupportProject path]];
//[fm removeItemAtURL:XCodeSupportFolder error:nil];
// create the template project if it doesn't exist
if (![fm fileExistsAtPath:[XCodeSupportFolder path]])
{
NSLog(@"Xcode support folder created at: %@", [XCodeSupportProject path]);
[fm createDirectoryAtPath:[XCodeSupportProject path] withIntermediateDirectories:YES attributes:nil error:nil];
DLog(@"Copying project.pbxproj from %@ to %@", XCodeTemplatePBXPath, [XCodeSupportProject path]);
[fm copyItemAtPath:XCodeTemplatePBXPath toPath:XCodeSupportPBXPath error:nil];
DLog(@"Reading the content of the project.pbxproj");
NSMutableString *PBXContent = [NSMutableString stringWithContentsOfFile:XCodeSupportPBXPath encoding:NSUTF8StringEncoding error:nil];
[PBXContent replaceOccurrencesOfString:@"${CappuccinoProjectName}"
withString:currentProjectName
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [PBXContent length])];
[PBXContent replaceOccurrencesOfString:@"${CappuccinoProjectRelativePath}"
withString:@".."
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [PBXContent length])];
[PBXContent writeToFile:XCodeSupportPBXPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
DLog(@"PBX file adapted to the project");
DLog(@"Creating source folder");
[fm createDirectoryAtPath:[XCodeSupportProjectSources path] withIntermediateDirectories:YES attributes:nil error:nil];
return NO;
}
return YES;
}
/*!
Initialize the creation of the .xCodeSupport project. This
Operation is threaded
@param arguments Thread arguments (not used)
@param shouldNotify is YES, XCCDidPopulateProjectNotification will be send
*/
- (void)populateXCodeProject:(NSNumber *)shouldNotify
{
if ([shouldNotify boolValue])
[delegate performSelector:@selector(growlWithTitle:message:) withObject:@"Loading project" withObject:[currentProjectURL path]];
NSArray *subdpaths = [fm subpathsAtPath:[currentProjectURL path]];
for (NSString *p in subdpaths)
{
NSString *filePath = [NSString stringWithFormat:@"%@/%@", [currentProjectURL path], p];
BOOL isDir = NO;
[fm fileExistsAtPath:filePath isDirectory:&isDir];
if (isDir
|| (![self isXIBFile:filePath] && ![self isObjJFile:filePath]))
continue;
NSURL *eventualShadow = [self shadowURLForSourceURL:[NSURL URLWithString:filePath]];
if (![fm fileExistsAtPath:[eventualShadow path]])
{
DLog(@"Computing missing shadow file for %@", filePath);
[self handleFileModification:filePath notify:NO];
}
}
if ([shouldNotify boolValue])
{
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:currentProjectURL, @"URL", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:XCCDidPopulateProjectNotification object:self userInfo:info];
}
}
/*!
Compute the mirorred (shadow) name for a given path
@param aSourceURL the origin path
@return NSURL representing the shadow path
*/
- (NSURL *)shadowURLForSourceURL:(NSURL*)aSourceURL
{
if (!aSourceURL)
[NSException raise:NSInvalidArgumentException format:@"shadowURLForSourceURL: aSource URL must not be null"];
NSMutableString *flattenedPath = [NSMutableString stringWithString:[aSourceURL path]];
// Replace "_" with a substring that is unlikely to be in a filename
[flattenedPath replaceOccurrencesOfString:@"_"
withString:@"≤‹°∞°›≥"
options:0
range:NSMakeRange(0, [flattenedPath length])];
[flattenedPath replaceOccurrencesOfString:@"/"
withString:@"_"
options:0
range:NSMakeRange(0, [flattenedPath length])];
DLog(@"Flattened path: %@", flattenedPath);
NSString *basename = [NSString stringWithFormat:@"%@.h", [[flattenedPath stringByDeletingPathExtension] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
return [NSURL URLWithString:basename relativeToURL:XCodeSupportProjectSources];
}
- (NSURL *)sourceURLForShadowName:(NSString *)aString
{
NSMutableString * unshadowedPath = [NSMutableString stringWithString:aString];
[unshadowedPath replaceOccurrencesOfString:@"_"
withString:@"/"
options:0
range:NSMakeRange(0, [unshadowedPath length])];
[unshadowedPath replaceOccurrencesOfString:@"≤‹°∞°›≥"
withString:@"_"
options:0
range:NSMakeRange(0, [unshadowedPath length])];
[unshadowedPath replaceOccurrencesOfString:@".h"
withString:@".j"
options:0
range:NSMakeRange(0, [unshadowedPath length])];
return [NSURL URLWithString:[NSString stringWithString:unshadowedPath]];
}
/*!
Compute the ignored paths according to any existing
.xcodecapp-ignore file
*/
- (void)computeIgnoredPaths
{
NSString *ignorePath = [NSString stringWithFormat:@"%@/.xcodecapp-ignore", [currentProjectURL path]];
[ignoredFilePaths removeAllObjects];
if ([fm fileExistsAtPath:ignorePath])
{
NSString *ignoreFileContent = [NSString stringWithContentsOfFile:ignorePath encoding:NSUTF8StringEncoding error:nil];
NSArray *ignoredPatterns = [ignoreFileContent componentsSeparatedByString:@"\n"];
for (NSString *pattern in ignoredPatterns)
{
if ([pattern length])
[ignoredFilePaths addObject:pattern];
}
}
[ignoredFilePaths addObject:@"*/.git/*"];
[ignoredFilePaths addObject:@"*/.svn/*"];
[ignoredFilePaths addObject:@"*/.hg/*"];
[ignoredFilePaths addObject:@"*/Frameworks/*"];
[ignoredFilePaths addObject:@"*/.xCodeSupport/*"];
[ignoredFilePaths addObject:@"*/Build/*"];
NSLog(@"Ignoring file paths: %@", ignoredFilePaths);
}
/*!
Check is given path should be ignored
@param aPath the path to check
@return YES if it should be ignored, NO otherwise
*/
- (BOOL)isPathMatchingIgnoredPaths:(NSString*)aPath
{
for (NSString *ignoredPath in ignoredFilePaths)
{
if ([ignoredPath length] == 0)
continue;
NSMutableString *regexp = [NSMutableString stringWithFormat:@"%@/%@", [currentProjectURL path], ignoredPath];
[regexp replaceOccurrencesOfString:@"/"
withString:@"\\/"
options:0
range:NSMakeRange(0, [regexp length])];
[regexp replaceOccurrencesOfString:@"."
withString:@"\\."
options:0
range:NSMakeRange(0, [regexp length])];
[regexp replaceOccurrencesOfString:@"*"
withString:@".*"
options:0
range:NSMakeRange(0, [regexp length])];
NSPredicate *regextest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regexp];
if ([regextest evaluateWithObject:aPath])
{
return YES;
}
}
return NO;
}
/*!
Start all needed processes for listening to a given path
@param path The folder path to listen to
*/
- (void)listenProjectAtPath:(NSString *)path
{
NSMutableString *tempName = [NSMutableString stringWithString:[path lastPathComponent]];
currentProjectURL = [NSURL URLWithString:path];
[tempName replaceOccurrencesOfString:@" "
withString:@"_"
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [tempName length])];
currentProjectName = [NSString stringWithString:tempName];
[self computeIgnoredPaths];
BOOL isProjectReady = [self prepareXCodeSupportProject];
[NSThread detachNewThreadSelector:@selector(populateXCodeProject:) toTarget:self withObject:[NSNumber numberWithBool:!isProjectReady]];
[self initializeEventStreamWithPath:[currentProjectURL path]];
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:path, @"path", [NSNumber numberWithInt:(isProjectReady) ? 1 : 0], @"ready", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:XCCListeningStartNotification object:self userInfo:info];
[[NSUserDefaults standardUserDefaults] setObject:[currentProjectURL path] forKey:@"LastOpenedPath"];
}
/*!
Clean the support folder according to files present in given path
*/
- (void)tidyShadowedFiles
{
NSArray *subpaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[XCodeSupportProjectSources path] error:NULL];
for (NSString *subpath in subpaths)
{
NSString *unshadowed = [[self sourceURLForShadowName:subpath] path];
NSString *shadowFullPath = [NSString stringWithFormat:@"%@/%@", [XCodeSupportProjectSources path], subpath];
if (![fm fileExistsAtPath:unshadowed])
{
DLog(@"cleaning shadow file: %@", subpath);
[fm removeItemAtPath:shadowFullPath error:nil];
if (![self supportFileLevelAPI] && [self respondsToSelector:@selector(updateLastModificationDate:forPath:)])
[self performSelector:@selector(updateLastModificationDate:forPath:) withObject:nil withObject:unshadowed];
}
}
}
@end
@implementation TNXCodeCapp (SnowLeopard)
- (void)updateLastModificationDate:(NSDate *)date forPath:(NSString *)path
{
if (!pathModificationDates)
{
pathModificationDates = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"pathModificationDates"] mutableCopy];
if (!pathModificationDates)
pathModificationDates = [NSMutableDictionary new];
}
if (date)
[pathModificationDates setObject:[date retain] forKey:path];
else
[pathModificationDates removeObjectForKey:path];
[[NSUserDefaults standardUserDefaults] setObject:pathModificationDates forKey:@"pathModificationDates"];
}
- (NSDate *)lastModificationDateForPath:(NSString *)path
{
if (!pathModificationDates)
{
pathModificationDates = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"pathModificationDates"] mutableCopy];
if (!pathModificationDates)
pathModificationDates = [NSMutableDictionary new];
}
if ([pathModificationDates valueForKey:path] != nil)
return [pathModificationDates valueForKey:path];
else
return appStartedTimestamp;
}
@end
File renamed without changes.
+7
View File
@@ -0,0 +1,7 @@
//
// Prefix header for all source files of the 'XcodeCapp' target in the 'XcodeCapp' project
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
@@ -3,22 +3,25 @@
archiveVersion = 1;
classes = {
};
objectVersion = 45;
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
024A03DD13696C1900DCBE4D /* xcodecapp-cocoa.icns in Resources */ = {isa = PBXBuildFile; fileRef = 024A03DC13696C1900DCBE4D /* xcodecapp-cocoa.icns */; };
024A03DF13696D9500DCBE4D /* xcodecapp-cocoa.png in Resources */ = {isa = PBXBuildFile; fileRef = 024A03DE13696D9500DCBE4D /* xcodecapp-cocoa.png */; };
024A040B13698E7800DCBE4D /* project.pbxproj in Resources */ = {isa = PBXBuildFile; fileRef = 024A040A13698E7700DCBE4D /* project.pbxproj */; };
022BCEA71468632000B72910 /* project.pbxproj.sample in Resources */ = {isa = PBXBuildFile; fileRef = 022BCEA61468632000B72910 /* project.pbxproj.sample */; };
024A041413699DD400DCBE4D /* parser.j in Resources */ = {isa = PBXBuildFile; fileRef = 024A041113699D6800DCBE4D /* parser.j */; };
026F3B6213866B0B00EE5B83 /* xcodecapp-cocoa-icon-inactive.png in Resources */ = {isa = PBXBuildFile; fileRef = 026F3B6113866B0B00EE5B83 /* xcodecapp-cocoa-icon-inactive.png */; };
026F3B6513866E7D00EE5B83 /* xcodecapp-cocoa-icon-active.png in Resources */ = {isa = PBXBuildFile; fileRef = 026F3B6413866E7D00EE5B83 /* xcodecapp-cocoa-icon-active.png */; };
026F3B6213866B0B00EE5B83 /* xcodecapp-icon-inactive.png in Resources */ = {isa = PBXBuildFile; fileRef = 026F3B6113866B0B00EE5B83 /* xcodecapp-icon-inactive.png */; };
026F3B6513866E7D00EE5B83 /* xcodecapp-icon-active.png in Resources */ = {isa = PBXBuildFile; fileRef = 026F3B6413866E7D00EE5B83 /* xcodecapp-icon-active.png */; };
027D999B13696A7000D3DB13 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; };
027D999C13696A7000D3DB13 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
027D999E13696A7000D3DB13 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
027D999F13696A7000D3DB13 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E01A91E0DE9EED20008BB35 /* AppController.m */; };
027D99A113696A7000D3DB13 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
027D99A213696A7000D3DB13 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E01A8DD0DE51A7C0008BB35 /* CoreServices.framework */; };
027FE49A1462C6CF00B1AB92 /* help.rtfd in Resources */ = {isa = PBXBuildFile; fileRef = 027FE4991462C6CF00B1AB92 /* help.rtfd */; };
027FE49D1462D74C00B1AB92 /* TNXCodeCapp.m in Sources */ = {isa = PBXBuildFile; fileRef = 027FE49C1462D74C00B1AB92 /* TNXCodeCapp.m */; };
027FE4BA1462F64E00B1AB92 /* xcodecapp-icon-working.png in Resources */ = {isa = PBXBuildFile; fileRef = 027FE4B91462F64E00B1AB92 /* xcodecapp-icon-working.png */; };
027FE4BD1462F7EB00B1AB92 /* FSEventCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = 027FE4BC1462F7EB00B1AB92 /* FSEventCallback.m */; };
0289AC9414668CAF003CD975 /* XcodeCapp.icns in Resources */ = {isa = PBXBuildFile; fileRef = 0289AC9314668CAF003CD975 /* XcodeCapp.icns */; };
02998CEB1369BF7D006C73DB /* Growl Registration Ticket.growlRegDict in Resources */ = {isa = PBXBuildFile; fileRef = 02998CEA1369BF7D006C73DB /* Growl Registration Ticket.growlRegDict */; };
02998CF71369C339006C73DB /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02998CF61369C339006C73DB /* Growl.framework */; };
02998CF91369C38A006C73DB /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 02998CF61369C339006C73DB /* Growl.framework */; };
@@ -39,14 +42,19 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
024A03DC13696C1900DCBE4D /* xcodecapp-cocoa.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "xcodecapp-cocoa.icns"; sourceTree = "<group>"; };
024A03DE13696D9500DCBE4D /* xcodecapp-cocoa.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "xcodecapp-cocoa.png"; sourceTree = "<group>"; };
024A040A13698E7700DCBE4D /* project.pbxproj */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.pbxproject; path = project.pbxproj; sourceTree = "<group>"; };
022BCEA61468632000B72910 /* project.pbxproj.sample */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = project.pbxproj.sample; sourceTree = "<group>"; };
024A041113699D6800DCBE4D /* parser.j */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.objj; path = parser.j; sourceTree = "<group>"; };
026F3B6113866B0B00EE5B83 /* xcodecapp-cocoa-icon-inactive.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "xcodecapp-cocoa-icon-inactive.png"; sourceTree = "<group>"; };
026F3B6413866E7D00EE5B83 /* xcodecapp-cocoa-icon-active.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "xcodecapp-cocoa-icon-active.png"; sourceTree = "<group>"; };
027D9989136969DD00D3DB13 /* xcodecapp-cocoa.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "xcodecapp-cocoa.pch"; sourceTree = "<group>"; };
027D99A613696A7000D3DB13 /* xcodecapp-cocoa.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "xcodecapp-cocoa.app"; sourceTree = BUILT_PRODUCTS_DIR; };
026F3B6113866B0B00EE5B83 /* xcodecapp-icon-inactive.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "xcodecapp-icon-inactive.png"; sourceTree = "<group>"; };
026F3B6413866E7D00EE5B83 /* xcodecapp-icon-active.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "xcodecapp-icon-active.png"; sourceTree = "<group>"; };
027D9989136969DD00D3DB13 /* XcodeCapp.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XcodeCapp.pch; sourceTree = "<group>"; };
027D99A613696A7000D3DB13 /* XcodeCapp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XcodeCapp.app; sourceTree = BUILT_PRODUCTS_DIR; };
027FE4991462C6CF00B1AB92 /* help.rtfd */ = {isa = PBXFileReference; lastKnownFileType = wrapper.rtfd; path = help.rtfd; sourceTree = "<group>"; };
027FE49B1462D74C00B1AB92 /* TNXCodeCapp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TNXCodeCapp.h; sourceTree = "<group>"; };
027FE49C1462D74C00B1AB92 /* TNXCodeCapp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TNXCodeCapp.m; sourceTree = "<group>"; };
027FE4B91462F64E00B1AB92 /* xcodecapp-icon-working.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "xcodecapp-icon-working.png"; sourceTree = "<group>"; };
027FE4BB1462F7D600B1AB92 /* FSEventCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSEventCallback.h; sourceTree = "<group>"; };
027FE4BC1462F7EB00B1AB92 /* FSEventCallback.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSEventCallback.m; sourceTree = "<group>"; };
0289AC9314668CAF003CD975 /* XcodeCapp.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = XcodeCapp.icns; sourceTree = "<group>"; };
02998CEA1369BF7D006C73DB /* Growl Registration Ticket.growlRegDict */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Growl Registration Ticket.growlRegDict"; sourceTree = "<group>"; };
02998CF61369C339006C73DB /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Growl.framework; sourceTree = "<group>"; };
089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -61,7 +69,8 @@
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8E01A8DD0DE51A7C0008BB35 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
8E01A91D0DE9EED20008BB35 /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = "<group>"; };
8E01A91E0DE9EED20008BB35 /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppController.m; sourceTree = "<group>"; };
8E01A91E0DE9EED20008BB35 /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AppController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
E12AA95F14637828006F55D6 /* macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.objj.h; path = macros.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -85,6 +94,10 @@
651DAE1D13B0CAB900ECA3F0 /* PRHEmptyGrowlDelegate.m */,
8E01A91D0DE9EED20008BB35 /* AppController.h */,
8E01A91E0DE9EED20008BB35 /* AppController.m */,
027FE49B1462D74C00B1AB92 /* TNXCodeCapp.h */,
027FE49C1462D74C00B1AB92 /* TNXCodeCapp.m */,
027FE4BB1462F7D600B1AB92 /* FSEventCallback.h */,
027FE4BC1462F7EB00B1AB92 /* FSEventCallback.m */,
);
name = Classes;
sourceTree = "<group>";
@@ -111,7 +124,7 @@
19C28FACFE9D520D11CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
027D99A613696A7000D3DB13 /* xcodecapp-cocoa.app */,
027D99A613696A7000D3DB13 /* XcodeCapp.app */,
);
name = Products;
sourceTree = "<group>";
@@ -131,8 +144,9 @@
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
isa = PBXGroup;
children = (
027D9989136969DD00D3DB13 /* xcodecapp-cocoa.pch */,
027D9989136969DD00D3DB13 /* XcodeCapp.pch */,
29B97316FDCFA39411CA2CEA /* main.m */,
E12AA95F14637828006F55D6 /* macros.h */,
);
name = "Other Sources";
sourceTree = "<group>";
@@ -140,13 +154,14 @@
29B97317FDCFA39411CA2CEA /* Resources */ = {
isa = PBXGroup;
children = (
026F3B6413866E7D00EE5B83 /* xcodecapp-cocoa-icon-active.png */,
026F3B6113866B0B00EE5B83 /* xcodecapp-cocoa-icon-inactive.png */,
022BCEA61468632000B72910 /* project.pbxproj.sample */,
027FE4B91462F64E00B1AB92 /* xcodecapp-icon-working.png */,
027FE4991462C6CF00B1AB92 /* help.rtfd */,
026F3B6413866E7D00EE5B83 /* xcodecapp-icon-active.png */,
026F3B6113866B0B00EE5B83 /* xcodecapp-icon-inactive.png */,
024A041113699D6800DCBE4D /* parser.j */,
024A03DE13696D9500DCBE4D /* xcodecapp-cocoa.png */,
024A040A13698E7700DCBE4D /* project.pbxproj */,
024A03DC13696C1900DCBE4D /* xcodecapp-cocoa.icns */,
8D1107310486CEB800E47090 /* Info.plist */,
0289AC9314668CAF003CD975 /* XcodeCapp.icns */,
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
29B97318FDCFA39411CA2CEA /* MainMenu.nib */,
02998CEA1369BF7D006C73DB /* Growl Registration Ticket.growlRegDict */,
@@ -167,9 +182,9 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
027D999913696A7000D3DB13 /* xcodecapp-cocoa */ = {
027D999913696A7000D3DB13 /* XcodeCapp */ = {
isa = PBXNativeTarget;
buildConfigurationList = 027D99A313696A7000D3DB13 /* Build configuration list for PBXNativeTarget "xcodecapp-cocoa" */;
buildConfigurationList = 027D99A313696A7000D3DB13 /* Build configuration list for PBXNativeTarget "XcodeCapp" */;
buildPhases = (
027D999A13696A7000D3DB13 /* Resources */,
027D999D13696A7000D3DB13 /* Sources */,
@@ -180,10 +195,10 @@
);
dependencies = (
);
name = "xcodecapp-cocoa";
name = XcodeCapp;
productInstallPath = "$(HOME)/Applications";
productName = "xcodecapp-cocoa";
productReference = 027D99A613696A7000D3DB13 /* xcodecapp-cocoa.app */;
productReference = 027D99A613696A7000D3DB13 /* XcodeCapp.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -191,8 +206,11 @@
/* Begin PBXProject section */
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "xcodecapp-cocoa" */;
compatibilityVersion = "Xcode 3.1";
attributes = {
LastUpgradeCheck = 0420;
};
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "XcodeCapp" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
@@ -202,7 +220,7 @@
projectDirPath = "";
projectRoot = "";
targets = (
027D999913696A7000D3DB13 /* xcodecapp-cocoa */,
027D999913696A7000D3DB13 /* XcodeCapp */,
);
};
/* End PBXProject section */
@@ -214,13 +232,14 @@
files = (
027D999B13696A7000D3DB13 /* MainMenu.nib in Resources */,
027D999C13696A7000D3DB13 /* InfoPlist.strings in Resources */,
024A03DD13696C1900DCBE4D /* xcodecapp-cocoa.icns in Resources */,
024A041413699DD400DCBE4D /* parser.j in Resources */,
024A03DF13696D9500DCBE4D /* xcodecapp-cocoa.png in Resources */,
024A040B13698E7800DCBE4D /* project.pbxproj in Resources */,
02998CEB1369BF7D006C73DB /* Growl Registration Ticket.growlRegDict in Resources */,
026F3B6213866B0B00EE5B83 /* xcodecapp-cocoa-icon-inactive.png in Resources */,
026F3B6513866E7D00EE5B83 /* xcodecapp-cocoa-icon-active.png in Resources */,
026F3B6213866B0B00EE5B83 /* xcodecapp-icon-inactive.png in Resources */,
026F3B6513866E7D00EE5B83 /* xcodecapp-icon-active.png in Resources */,
027FE49A1462C6CF00B1AB92 /* help.rtfd in Resources */,
027FE4BA1462F64E00B1AB92 /* xcodecapp-icon-working.png in Resources */,
0289AC9414668CAF003CD975 /* XcodeCapp.icns in Resources */,
022BCEA71468632000B72910 /* project.pbxproj.sample in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -234,6 +253,8 @@
027D999E13696A7000D3DB13 /* main.m in Sources */,
027D999F13696A7000D3DB13 /* AppController.m in Sources */,
651DAE1F13B0CAB900ECA3F0 /* PRHEmptyGrowlDelegate.m in Sources */,
027FE49D1462D74C00B1AB92 /* TNXCodeCapp.m in Sources */,
027FE4BD1462F7EB00B1AB92 /* FSEventCallback.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -269,15 +290,14 @@
"\"$(SRCROOT)\"",
);
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_ENABLE_OBJC_GC = required;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "xcodecapp-cocoa.pch";
GCC_PREFIX_HEADER = XcodeCapp.pch;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = /Applications;
PRODUCT_NAME = "xcodecapp-cocoa";
PRODUCT_NAME = XcodeCapp;
};
name = Debug;
};
@@ -293,10 +313,10 @@
GCC_ENABLE_OBJC_GC = required;
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "xcodecapp-cocoa.pch";
GCC_PREFIX_HEADER = XcodeCapp.pch;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = /Applications;
PRODUCT_NAME = "xcodecapp-cocoa";
PRODUCT_NAME = XcodeCapp;
};
name = Release;
};
@@ -306,12 +326,14 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
FRAMEWORK_SEARCH_PATHS = "";
GCC_ENABLE_OBJC_GC = supported;
GCC_ENABLE_OBJC_GC = required;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.5;
ONLY_ACTIVE_ARCH = YES;
PREBINDING = NO;
SDKROOT = macosx10.6;
};
name = Debug;
@@ -322,10 +344,12 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
FRAMEWORK_SEARCH_PATHS = "";
GCC_ENABLE_OBJC_GC = supported;
GCC_ENABLE_OBJC_GC = required;
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
MACOSX_DEPLOYMENT_TARGET = 10.5;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx10.6;
};
name = Release;
@@ -333,7 +357,7 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
027D99A313696A7000D3DB13 /* Build configuration list for PBXNativeTarget "xcodecapp-cocoa" */ = {
027D99A313696A7000D3DB13 /* Build configuration list for PBXNativeTarget "XcodeCapp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
027D99A413696A7000D3DB13 /* Debug */,
@@ -342,7 +366,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "xcodecapp-cocoa" */ = {
C01FCF4E08A954540054247B /* Build configuration list for PBXProject "XcodeCapp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C01FCF4F08A954540054247B /* Debug */,
@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:xcodecapp-cocoa.xcodeproj">
location = "self:XcodeCapp.xcodeproj">
</FileRef>
</Workspace>
@@ -4,16 +4,16 @@
<dict>
<key>SchemeUserState</key>
<dict>
<key>xcodecapp-cocoa RELEASE.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
<key>xcodecapp-cocoa.xcscheme</key>
<key>XcodeCapp Debug.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>XcodeCapp Release.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
+165
View File
@@ -0,0 +1,165 @@
{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230
{\fonttbl\f0\fnil\fcharset0 LucidaGrande;\f1\fswiss\fcharset0 Helvetica;\f2\fmodern\fcharset0 Courier;
}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww16380\viewh15560\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0\b\fs36 \cf0 XcodeCapp Help
\b0 \
\
\b\fs24 What is XcodeCapp?\
\b0\fs36 \
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\fs24 \cf0 One of Cappuccino\'92s greatest features is the ability to use Xcode 4 to create the user interface for your web applications. Xcode creates .xib files which then must be converted by the command line utility
\b nib2cib
\b0 to .cib files for use with Cappuccino. But beginning with Xcode 4, there is no way to directly create outlets and actions without editing Objective-C header files.\
\
XcodeCapp acts as a bridge between Xcode and Cappuccino. It performs two main functions:\
\
\'95 Reads your source files when they are modified and automatically creates outlets and actions in the .xib file.\
\'95 Automatically converts .xib files to .cib files when the .xib file is modified.\
\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\b \cf0 Using XcodeCapp
\b0 \
\
XcodeCapp is very easy to use and requires very little user interaction. When you build Cappuccino with jake, it will create a symlink to the XcodeCapp application in your Applications folder. Launch XcodeCapp from there and the XcodeCapp icon will appear in your menu bar. Clicking on the icon will display the XcodeCapp menu:\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f1 \cf0 {{\NeXTGraphic menu1.png \width4220 \height3440
}¬}\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0 \cf0 \
\
\
If this is the first time you have run XcodeCapp, or if you were not listening to a project when XcodeCapp was last quit, you need to choose a Cappuccino project. Select "Listen to Project\'85\'94, and a folder chooser will appear. Navigate to the root folder of your project \'97 the one that contains index.html and Jakefile \'97 and click Open.\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\cf0 \
Once you select a project, XcodeCapp will import your project and create a hidden folder called \'93.XcodeSupport\'94 in the root project directory. This folder contains files built by XcodeCapp that it needs to perform its magic, so you should never directly modify those files. You will probably want to ignore this folder in your IDE and source code management system as well.\
\
After XcodeCapp has imported a project, it will listen to changes in the following files anywhere in the project:\
\
\'95 *.xib \'96 Interface Builder files\
\'95 *.j - Objective-J source\
\'95 .xcodecapp-ignore - specifies files XcodeCapp should ignore\
\
Any time these files are modified, XcodeCapp will process the files and show a Growl notification when the processing is done.\
\
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\b \cf0 Declaring Outlets and Actions\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\b0 \cf0 \
The most important function XcodeCapp performs is to create outlets and actions for use with Interface Builder. You create outlets by prefixing them in your source files with
\b @outlet
\b0 or
\b IBOutlet
\b0 . For example, in the class below, there are seven outlets defined:\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f1 \cf0 {{\NeXTGraphic outlets.png \width10580 \height4580
}¬}\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0 \cf0 \
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\cf0 Similarly, you declare actions by declaring the return type of the method to be
\b @action
\b0 or
\b IBAction
\b0 . For example, the following method can serve as an action for a control:\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f1 \cf0 {{\NeXTGraphic action.png \width14180 \height2440
}¬}\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0 \cf0 \
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\cf0 \
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\b \cf0 Editing XIBs\
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\b0 \cf0 XcodeCapp creates an Xcode 4 project that allows you to edit your project\'92s xibs. To open the project, click on the XcodeCapp menu and select \'93Open Project in Xcode\'94.\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\cf0 \
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f1 \cf0 {{\NeXTGraphic menu2.png \width5220 \height3480
}¬}\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0 \cf0 \
\
Once the Xcode project is open, you can edit your xibs with the interface builder. All of the outlets and actions you declared in your source will be available in interface builder for connection to views. For example, the InfoPanelController shown above would have these outlets in interface builder:\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\cf0 \
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f1 \cf0 {{\NeXTGraphic outlets2.png \width8040 \height4160
}¬}\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0 \cf0 \
\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\b \cf0 Ignoring Files and Folders\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\b0 \cf0 To have XcodeCapp ignore files and folders, create a file in the root project directory named \'93.xcodecapp-ignore\'94, and enter one line for each pattern you would like to ignore. Patterns may use \'93*\'94 as a wildcard to match zero or more characters (it is
\b not
\b0 a shell glob) and are matched against the
\b absolute
\b0 path of the file or folder, so in most cases your patterns should begin with \'93*\'94. To safely match a folder name, the pattern should be
\f2 */<name>/*
\f0 , where
\f2 name
\f0 is the name of the folder.\
\
For example, to ignore the \'93Modules\'94 directory and the xib file \'93foo.xib\'94 in your project, enter these lines in .xcodecapp-ignore:\
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f2 \cf0 */Modules/*\
*/foo.xib
\f0 \
\
Note that in addition to whatever patterns you specify (if any), XcodeCapp
\b always
\b0 ignores the following patterns:\
\
\f2 */.git/*\
*/.svn/*\
*/.hg/*\
*/Frameworks/*\
*/.xCodeSupport/*\
*/Build/*\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0 \cf0 \
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\b \cf0 Credits
\fs28 \
\
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\b0\fs24 \cf0 XcodeCapp was originally written by Francisco Tolmasky.\
The Cocoa port was written by Antoine Mercadal with contributions from Aparajita Fishman.\
XcodeCapp (Cocoa version, formerly known as XcodeCapp-cocoa) was originally built for the Archipel Project (archipelproject.org) and is now part of Cappuccino.}
Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

+28
View File
@@ -0,0 +1,28 @@
/*
* This file is a part of program XcodeCapp
* Copyright (C) 2011 Aparajita Fishman (<aparajita@aparajitaworld.com>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef xcodecapp_cocoa_macros_h
#define xcodecapp_cocoa_macros_h
#if DEBUG
# define DLog(fmt, ...) NSLog((fmt), ##__VA_ARGS__)
#else
# define DLog(...)
#endif
#endif
@@ -1,6 +1,6 @@
/*
* This file is a part of program xcodecapp-cocoa
* Copyright (C) 2011 Antoine Mercadal (primalmotion@archipelproject.org)
* This file is a part of program XcodeCapp
* Copyright (C) 2011 Antoine Mercadal (<primalmotion@archipelproject.org>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
File renamed without changes.
@@ -351,4 +351,4 @@
/* End XCConfigurationList section */
};
rootObject = 9EEC448A135749D200615446 /* Project object */;
}
}
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

-87
View File
@@ -1,87 +0,0 @@
/*
* This file is a part of program xcodecapp-cocoa
* Copyright (C) 2011 Antoine Mercadal (primalmotion@archipelproject.org)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
#import "PRHEmptyGrowlDelegate.h"
@interface AppController : NSObject <NSMenuDelegate>
{
IBOutlet NSButton *buttonOpenXCode;
IBOutlet NSButton *buttonStart;
IBOutlet NSButton *buttonStop;
IBOutlet NSMenu *statusMenu;
IBOutlet NSMenuItem *menuItemOpenXCode;
IBOutlet NSMenuItem *menuItemStart;
IBOutlet NSMenuItem *menuItemStop;
IBOutlet NSPanel *errorsPanel;
IBOutlet NSProgressIndicator *spinner;
IBOutlet NSTableView *errorsTable;
IBOutlet NSTextField *labelCurrentPath;
IBOutlet NSTextField *labelPath;
IBOutlet NSTextField *labelStatus;
IBOutlet NSWindow *mainWindow;
FSEventStreamRef stream;
NSDate *appStartedTimestamp;
NSFileManager *fm;
NSImage *_iconActive;
NSImage *_iconInactive;
NSMutableArray *errorList;
NSMutableArray *ignoredFilePaths;
NSMutableArray *modifiedXIBs;
NSMutableDictionary *pathModificationDates;
NSNumber *lastEventId;
NSStatusItem *_statusItem;
NSString *currentProjectName;
NSString *parserPath;
NSString *XCodeSupportPBXPath;
NSString *XCodeSupportProjectName;
NSString *XCodeTemplatePBXPath;
NSString *_profilePath;
NSURL *currentProjectURL;
NSURL *XCodeSupportFolder;
NSURL *XCodeSupportProject;
NSURL *XCodeSupportProjectSources;
PRHEmptyGrowlDelegate *growlDelegateRef;
}
- (BOOL)isObjJFile:(NSString*)path;
- (BOOL)isPathMatchingIgnoredPaths:(NSString*)aPath;
- (BOOL)isXIBFile:(NSString *)path;
- (BOOL)prepareXCodeSupportProject;
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem;
- (NSURL*)shadowURLForSourceURL:(NSURL*)aSourceURL;
- (void)handleFileModification:(NSString*)path ignoreDate:(BOOL)shouldIgnoreDate;
- (void)initializeEventStreamWithPath:(NSString*)aPath;
- (void)registerDefaults;
- (void)updateErrorTable;
- (void)updateLastEventId:(uint64_t)eventId;
- (IBAction)chooseFolder:(id)aSender;
- (IBAction)clearErrors:(id)sender;
- (IBAction)openXCode:(id)aSender;
- (IBAction)stopListener:(id)aSender;
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag;
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(int)aRow;
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView;
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView;
@end
-565
View File
@@ -1,565 +0,0 @@
/*
* This file is a part of program xcodecapp-cocoa
* Copyright (C) 2011 Antoine Mercadal (primalmotion@archipelproject.org)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#import "AppController.h"
void fsevents_callback(ConstFSEventStreamRef streamRef, void *userData, size_t numEvents,
void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[])
{
AppController *ac = (AppController *)userData;
size_t i;
for(i = 0; i < numEvents; i++)
{
[ac handleFileModification:[(NSArray *)eventPaths objectAtIndex:i] ignoreDate:NO];
[ac updateLastEventId:eventIds[i]];
}
}
@implementation AppController
#pragma mark -
#pragma mark Initialization
- (id)init
{
self = [super init];
if (self)
{
errorList = [NSMutableArray arrayWithCapacity:10];
if (!growlDelegateRef)
growlDelegateRef = [[[PRHEmptyGrowlDelegate alloc] init] autorelease];
[GrowlApplicationBridge setGrowlDelegate:growlDelegateRef];
fm = [NSFileManager defaultManager];
modifiedXIBs = [NSMutableArray new];
ignoredFilePaths = [NSMutableArray new];
parserPath = [[NSBundle mainBundle] pathForResource:@"parser" ofType:@"j"];
if([fm fileExistsAtPath:[@"~/.bash_profile" stringByExpandingTildeInPath]])
_profilePath = [@"source ~/.bash_profile" stringByExpandingTildeInPath];
else if([fm fileExistsAtPath:[@"~/.profile" stringByExpandingTildeInPath]])
_profilePath = [@"source ~/.profile" stringByExpandingTildeInPath];
else if([fm fileExistsAtPath:[@"~/.bashrc" stringByExpandingTildeInPath]])
_profilePath = [@"source ~/.bashrc" stringByExpandingTildeInPath];
else if([fm fileExistsAtPath:[@"~/.zshrc" stringByExpandingTildeInPath]])
_profilePath = [@"source ~/.zshrc" stringByExpandingTildeInPath];
else
{
NSAlert *alert = [NSAlert alertWithMessageText:@"Cannot find any valid profile file"
defaultButton:@"Ok"
alternateButton:nil
otherButton:nil
informativeTextWithFormat:@"We have checked for ~/.bash_profile, ~/.profile, ~/.bashrc and ~/.zshrc without luck.\n\nYou need to have on of this file to tell XCodeCapp-cocoa where is located nib2cib. Now we gonna try to without sourcing one this file and it may fail.\n\nIf you notice any error or weird behaviour, please look at Mac OS' Console.app for log message and open a ticket."];
[alert runModal];
_profilePath = @"";
}
}
return self;
}
- (void)awakeFromNib
{
[self registerDefaults];
[labelCurrentPath setHidden:YES];
[buttonOpenXCode setEnabled:NO];
[buttonStop setEnabled:NO];
[buttonStart setEnabled:YES];
[spinner setHidden:YES];
appStartedTimestamp = [NSDate date];
pathModificationDates = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"pathModificationDates"] mutableCopy];
lastEventId = [[NSUserDefaults standardUserDefaults] objectForKey:@"lastEventId"];
NSBundle *bundle = [NSBundle mainBundle];
_iconInactive = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"xcodecapp-cocoa-icon-inactive" ofType:@"png"]];
_iconActive = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"xcodecapp-cocoa-icon-active" ofType:@"png"]];
[_iconActive setSize:NSMakeSize(14.0, 16.0)];
[_iconInactive setSize:NSMakeSize(14.0, 16.0)];
_statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
[_statusItem setMenu:statusMenu];
[_statusItem setImage:_iconInactive];
[_statusItem setHighlightMode:YES];
[statusMenu setDelegate:self];
}
- (void)initializeEventStreamWithPath:(NSString*)aPath
{
NSArray *pathsToWatch = [NSArray arrayWithObject:aPath];
void *appPointer = (void *)self;
FSEventStreamContext context = {0, appPointer, NULL, NULL, NULL};
NSTimeInterval latency = 5.0;
stream = FSEventStreamCreate(NULL, &fsevents_callback, &context, (CFArrayRef) pathsToWatch,
[lastEventId unsignedLongLongValue], (CFAbsoluteTime) latency,kFSEventStreamCreateFlagUseCFTypes);
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
FSEventStreamStart(stream);
}
- (void)stopEventStream
{
if (stream)
{
FSEventStreamStop(stream);
FSEventStreamInvalidate(stream);
stream = nil;
}
}
- (void)registerDefaults
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary
dictionaryWithObjects:[NSArray arrayWithObjects:[NSNumber numberWithUnsignedLongLong:kFSEventStreamEventIdSinceNow], [NSMutableDictionary new], nil]
forKeys:[NSArray arrayWithObjects:@"lastEventId", @"pathModificationDates", nil]];
[defaults registerDefaults:appDefaults];
}
#pragma mark -
#pragma mark Notification handlers
- (NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication *)app
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:lastEventId forKey:@"lastEventId"];
[defaults setObject:pathModificationDates forKey:@"pathModificationDates"];
[defaults synchronize];
[self stopEventStream];
return NSTerminateNow;
}
#pragma mark -
#pragma mark Utilities
- (void)updateLastModificationDateForPath: (NSString *)path
{
[pathModificationDates setObject:[NSDate date] forKey:path];
}
- (NSDate*)lastModificationDateForPath: (NSString *)path
{
if(nil != [pathModificationDates valueForKey:path])
return [pathModificationDates valueForKey:path];
else
return appStartedTimestamp;
}
- (void)updateLastEventId:(uint64_t)eventId
{
lastEventId = [NSNumber numberWithUnsignedLongLong:eventId];
}
- (void)handleFileModification:(NSString*)path ignoreDate:(BOOL)shouldIgnoreDate
{
if ([self isPathMatchingIgnoredPaths:path])
return;
NSArray *contents = [fm contentsOfDirectoryAtPath:path error:NULL];
NSDate *lastModifiedDate = [self lastModificationDateForPath:path];
[self updateLastModificationDateForPath:path];
for(NSString *node in contents)
{
NSString *fullPath = [NSString stringWithFormat:@"%@/%@", path, node];
NSString *splitedPath = [NSString stringWithFormat:@"%@/%@", [[fullPath pathComponents] objectAtIndex:[[fullPath pathComponents] count] - 2], [fullPath lastPathComponent]];
NSDictionary *fileAttributes = [fm attributesOfItemAtPath:fullPath error:NULL];
NSDate *fileModDate = [fileAttributes objectForKey:NSFileModificationDate];
if(shouldIgnoreDate || [fileModDate compare:lastModifiedDate] == NSOrderedDescending)
{
//Prepare the shell
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/bash"];
NSArray *arguments;
NSString *successMsg;
if ([self isXIBFile:fullPath] || [self isObjJFile:fullPath])
{
if ([self isXIBFile:fullPath])
{
NSLog(@"running command nib2cib %@", fullPath);
//Create the nib2cib task
arguments = [NSArray arrayWithObjects: @"-c",
[NSString stringWithFormat:@"(%@; nib2cib '%@';) 2>&1", _profilePath, fullPath],@"",nil];
successMsg = @"The XIB file has been converted";
}
else if ([self isObjJFile:fullPath])
{
NSLog(@"Full path string is: %@", [fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]);
NSString *shadowPath = [[self shadowURLForSourceURL:[NSURL URLWithString:[fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]] path];
NSLog(@"running command objj %@", shadowPath);
//Create the objj task
arguments = [NSArray arrayWithObjects: @"-c",
[NSString stringWithFormat:@"(%@; objj '%@' '%@' '%@';) 2>&1", _profilePath, parserPath, fullPath, shadowPath],@"",nil];
successMsg = @"The Objective-J file has been converted";
}
//Run the task and get the response
[task setArguments: arguments];
[task setStandardOutput:[NSPipe pipe]];
[_statusItem setTitle:@"..."];
[task launch];
[task waitUntilExit];
NSData *stdOut;
stdOut = [[[task standardOutput] fileHandleForReading] availableData];
NSString *response;
response = [[NSString alloc] initWithData:stdOut
encoding:NSUTF8StringEncoding];
NSLog(@"response was\n%@", response);
[_statusItem setTitle:@""];
if ([task terminationStatus] == 0)
{
if (!shouldIgnoreDate)
{
[GrowlApplicationBridge notifyWithTitle:splitedPath
description:successMsg
notificationName:@"DefaultNotifications"
iconData:nil
priority:0
isSticky:NO
clickContext:nil];
}
}
else
{
NSLog(@"Error in conversion: return message is %@", response);
//if (![GrowlApplicationBridge isGrowlRunning])
{
[errorList addObject:response];
[self updateErrorTable];
}
}
}
}
}
}
- (BOOL)isObjJFile:(NSString *)path
{
return [[[path pathExtension] uppercaseString] isEqual:@"J"];
}
- (BOOL)isXIBFile:(NSString *)path
{
path = [[path pathExtension] uppercaseString];
return [path isEqual:@"XIB"] || [path isEqual:@"NIB"];
}
- (BOOL)prepareXCodeSupportProject
{
XCodeSupportProjectName = [NSString stringWithFormat:@"%@.xcodeproj/", currentProjectName];
XCodeTemplatePBXPath = [[NSBundle mainBundle] pathForResource:@"project" ofType:@"pbxproj"];
XCodeSupportFolder = [NSURL URLWithString:@".xCodeSupport/" relativeToURL:currentProjectURL];
XCodeSupportProject = [NSURL URLWithString:XCodeSupportProjectName relativeToURL:XCodeSupportFolder];
XCodeSupportProjectSources = [NSURL URLWithString:@"Sources/" relativeToURL:XCodeSupportFolder];
XCodeSupportPBXPath = [NSString stringWithFormat:@"%@/project.pbxproj", [XCodeSupportProject path]];
//[fm removeItemAtURL:XCodeSupportFolder error:nil];
// create the template project if it doesn't exist
if (![fm fileExistsAtPath:[XCodeSupportFolder path]])
{
NSLog(@"Xcode support folder created at: %@", [XCodeSupportProject path]);
[fm createDirectoryAtPath:[XCodeSupportProject path] withIntermediateDirectories:YES attributes:nil error:nil];
NSLog(@"Copying project.pbxproj from %@ to %@", XCodeTemplatePBXPath, [XCodeSupportProject path]);
[fm copyItemAtPath:XCodeTemplatePBXPath toPath:XCodeSupportPBXPath error:nil];
NSLog(@"Reading the content of the project.pbxproj");
NSMutableString *PBXContent = [NSMutableString stringWithContentsOfFile:XCodeSupportPBXPath encoding:NSUTF8StringEncoding error:nil];
[PBXContent replaceOccurrencesOfString:@"${CappuccinoProjectName}"
withString:currentProjectName
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [PBXContent length])];
[PBXContent replaceOccurrencesOfString:@"${CappuccinoProjectRelativePath}"
withString:@".."
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [PBXContent length])];
[PBXContent writeToFile:XCodeSupportPBXPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSLog(@"PBX file adapted to the project");
NSLog(@"Creating source folder");
[fm createDirectoryAtPath:[XCodeSupportProjectSources path] withIntermediateDirectories:YES attributes:nil error:nil];
[NSThread detachNewThreadSelector:@selector(populateXCodeProject:)toTarget:self withObject:nil];
return NO;
}
return YES;
}
- (void)populateXCodeProject:(id)argement
{
[GrowlApplicationBridge notifyWithTitle:[[currentProjectURL path] lastPathComponent]
description:@"Loading of project..."
notificationName:@"DefaultNotifications"
iconData:nil
priority:0
isSticky:NO
clickContext:nil];
[self handleFileModification:[NSString stringWithFormat:@"%@", [currentProjectURL path]] ignoreDate:YES];
NSArray *subdirs = [fm subpathsAtPath:[currentProjectURL path]];
for (NSString *p in subdirs)
[self handleFileModification:[NSString stringWithFormat:@"%@/%@", [currentProjectURL path], p] ignoreDate:YES];
[labelStatus setStringValue:@"XCodeCapp is running"];
[buttonOpenXCode setEnabled:YES];
[buttonStop setEnabled:YES];
[buttonStart setEnabled:NO];
[spinner setHidden:YES];
[GrowlApplicationBridge notifyWithTitle:[[currentProjectURL path] lastPathComponent]
description:@"Your project has been loaded successfully!"
notificationName:@"DefaultNotifications"
iconData:nil
priority:0
isSticky:NO
clickContext:nil];
}
- (NSURL*)shadowURLForSourceURL:(NSURL*)aSourceURL
{
NSMutableString *flattenedPath = [NSMutableString stringWithString:[aSourceURL path]];
NSLog(@"Flattened path is : %@", flattenedPath);
[flattenedPath replaceOccurrencesOfString:@"/"
withString:@"_"
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [[aSourceURL path] length])];
NSString *basename = [NSString stringWithFormat:@"%@.h", [[flattenedPath stringByDeletingPathExtension] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
return [NSURL URLWithString:basename relativeToURL:XCodeSupportProjectSources];
}
- (void)computeIgnoredPaths
{
NSString *ignorePath = [NSString stringWithFormat:@"%@/.xcodecapp-ignore", [currentProjectURL path]];
if (![fm fileExistsAtPath:ignorePath])
return;
NSString *ignoreFileContent = [NSString stringWithContentsOfFile:ignorePath encoding:NSUTF8StringEncoding error:nil];
ignoredFilePaths = [NSMutableArray arrayWithArray:[ignoreFileContent componentsSeparatedByString:@"\n"]];
NSLog(@"ignored file paths are: %@", ignoredFilePaths);
}
- (BOOL)isPathMatchingIgnoredPaths:(NSString*)aPath
{
BOOL isMatching = NO;
for (NSString *ignoredPath in ignoredFilePaths)
{
if ([ignoredPath isEqual:@""])
continue;
NSMutableString *regexp = [NSMutableString stringWithFormat:@"%@/%@", [currentProjectURL path], ignoredPath];
[regexp replaceOccurrencesOfString:@"/"
withString:@"\\/"
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [regexp length])];
[regexp replaceOccurrencesOfString:@"."
withString:@"\\."
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [regexp length])];
[regexp replaceOccurrencesOfString:@"*"
withString:@".*"
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [regexp length])];
NSPredicate *regextest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regexp];
if ([regextest evaluateWithObject:aPath])
{
isMatching = YES;
break;
}
}
return isMatching;
}
#pragma mark -
#pragma mark Actions
- (IBAction)chooseFolder:(id)aSender
{
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setCanChooseDirectories:YES];
[openPanel setCanCreateDirectories:YES];
[openPanel setPrompt:@"Choose Cappuccino project"];
[openPanel setCanChooseFiles:NO];
if ([openPanel runModal] != NSFileHandlingPanelOKButton)
return;
[spinner setHidden:NO];
[spinner startAnimation:nil];
currentProjectURL = [[openPanel URLs] objectAtIndex:0];
NSMutableString *tempName = [NSMutableString stringWithString:[[[openPanel URLs] objectAtIndex:0] lastPathComponent]];
[tempName replaceOccurrencesOfString:@" "
withString:@"_"
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [tempName length])];
currentProjectName = [NSString stringWithString:tempName];
[self computeIgnoredPaths];
[self initializeEventStreamWithPath:[currentProjectURL path]];
BOOL isProjectReady = [self prepareXCodeSupportProject];
[labelPath setStringValue:[currentProjectURL path]];
[labelCurrentPath setHidden:NO];
[buttonStart setEnabled:NO];
if (isProjectReady)
{
[spinner setHidden:YES];
[buttonStop setEnabled:YES];
[buttonOpenXCode setEnabled:YES];
[labelStatus setStringValue:@"XCodeCapp is running"];
}
else
[labelStatus setStringValue:@"XCodeCapp is loading project..."];
[_statusItem setImage:_iconActive];
}
- (IBAction)stopListener:(id)aSender
{
currentProjectURL = nil;
currentProjectName = nil;
[ignoredFilePaths removeAllObjects];
[labelPath setStringValue:@""];
[labelCurrentPath setHidden:YES];
[buttonOpenXCode setEnabled:NO];
[buttonStop setEnabled:NO];
[buttonStart setEnabled:YES];
[labelStatus setStringValue:@"XCodeCapp is not running"];
[self stopEventStream];
[_statusItem setImage:_iconInactive];
}
- (IBAction)openXCode:(id)aSender
{
if (!currentProjectURL)
return;
NSLog(@"Open Xcode project at URL : '%@'", [XCodeSupportProject path]);
system([[NSString stringWithFormat:@"open \"%@\"", [XCodeSupportProject path]] UTF8String]);
}
- (void)updateErrorTable
{
[errorsTable reloadData];
[errorsPanel orderFront:self];
NSLog(@"update?");
}
- (IBAction)clearErrors:(id)sender
{
[errorList removeAllObjects];
[errorsTable reloadData];
}
#pragma mark -
#pragma mark Delegates
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
{
[mainWindow makeKeyAndOrderFront:nil];
return YES;
}
- (BOOL)validateMenuItem:(NSMenuItem *)aMenuItem
{
if (aMenuItem == menuItemStart)
return !currentProjectURL;
if ((aMenuItem == menuItemStop) || (aMenuItem == menuItemOpenXCode))
return !!currentProjectURL;
return YES;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [errorList count];
}
- (id)tableView:(NSTableView*)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
return [errorList objectAtIndex:row];
}
- (void)tableViewColumnDidResize:(NSNotification *)tableView
{
[errorsTable noteHeightOfRowsWithIndexesChanged:
[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [errorList count])]];
}
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(int)aRow
{
// Get column you want - first in this case:
NSTableColumn *tabCol = [[tableView tableColumns] objectAtIndex:0];
float width = [tabCol width];
NSRect r = NSMakeRect(0,0,width,1000.0);
NSCell *cell = [tabCol dataCellForRow:aRow];
NSString *content = [errorList objectAtIndex:aRow];
[cell setObjectValue:content];
float height = [cell cellSizeForBounds:r].height;
if (height <= 0)
height = 16.0; // Ensure miniumum height is 16.0
return height;
}
@end
File diff suppressed because it is too large. Load diff
Binary file not shown.
@@ -1,7 +0,0 @@
//
// Prefix header for all source files of the 'xcodecapp-cocoa' target in the 'xcodecapp-cocoa' project
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "027D999913696A7000D3DB13"
BuildableName = "xcodecapp-cocoa.app"
BlueprintName = "xcodecapp-cocoa"
ReferencedContainer = "container:xcodecapp-cocoa.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
displayScaleIsEnabled = "NO"
displayScale = "1.00"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "027D999913696A7000D3DB13"
BuildableName = "xcodecapp-cocoa.app"
BlueprintName = "xcodecapp-cocoa"
ReferencedContainer = "container:xcodecapp-cocoa.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
displayScaleIsEnabled = "NO"
displayScale = "1.00"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "027D999913696A7000D3DB13"
BuildableName = "xcodecapp-cocoa.app"
BlueprintName = "xcodecapp-cocoa"
ReferencedContainer = "container:xcodecapp-cocoa.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "027D999913696A7000D3DB13"
BuildableName = "xcodecapp-cocoa.app"
BlueprintName = "xcodecapp-cocoa"
ReferencedContainer = "container:xcodecapp-cocoa.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
displayScaleIsEnabled = "NO"
displayScale = "1.00"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "027D999913696A7000D3DB13"
BuildableName = "xcodecapp-cocoa.app"
BlueprintName = "xcodecapp-cocoa"
ReferencedContainer = "container:xcodecapp-cocoa.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
displayScaleIsEnabled = "NO"
displayScale = "1.00"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "027D999913696A7000D3DB13"
BuildableName = "xcodecapp-cocoa.app"
BlueprintName = "xcodecapp-cocoa"
ReferencedContainer = "container:xcodecapp-cocoa.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
-42
View File
@@ -1,42 +0,0 @@
require ("../../common.jake");
var app = require("objective-j/jake").app,
BundleTask = require("objective-j/jake").BundleTask,
FILE = require("file"),
OS = require("os"),
stream = require("narwhal/term").stream;
app ("xcodecapp", function(xcodecappTask)
{
xcodecappTask.setBuildIntermediatesPath(FILE.join($BUILD_DIR, "xcodecapp.build", $CONFIGURATION))
xcodecappTask.setBuildPath($BUILD_CJS_CAPPUCCINO_LIB);
xcodecappTask.setSummary("xCode 4 Integration for Cappuccino projects");
xcodecappTask.setIdentifier("org.cappuccino.xcodecapp");
xcodecappTask.setLicense(BundleTask.License.LGPL_v2_1);
xcodecappTask.setVersion(getCappuccinoVersion());
xcodecappTask.setSources(new FileList("*.j"));
xcodecappTask.setResources(new FileList("Resources/*"));
xcodecappTask.setIncludesNibsAndXibs(true);
xcodecappTask.setEnvironments(require("objective-j/jake/environment").CommonJS);
xcodecappTask.setFlattensSources(true);
xcodecappTask.setSpritesResources(false);
if ($CONFIGURATION === "Release")
xcodecappTask.setCompilerFlags("-O");
else
xcodecappTask.setCompilerFlags("-DDEBUG -g");
});
$BUILD_CJS_XCODECAPP = FILE.join($BUILD_CJS_CAPPUCCINO_BIN, "xcodecapp");
// executable in environment directory
filedir($BUILD_CJS_XCODECAPP, ["xcodecapp"], function()
{
make_objj_executable($BUILD_CJS_XCODECAPP);
});
task ("build", ["xcodecapp", $BUILD_CJS_XCODECAPP]);
CLOBBER.include($BUILD_CJS_CAPPUCCINO_BIN);
-464
View File
@@ -1,464 +0,0 @@
@import <Foundation/Foundation.j>
var FILE = require("file");
function main(args)
{
var fileURL = new CFURL(args[1]),
outputURL = new CFURL(args[2]),
source = FILE.read(fileURL, { charset: "UTF-8" }),
flags = ObjectiveJ.Preprocessor.Flags.IncludeDebugSymbols |
ObjectiveJ.Preprocessor.Flags.IncludeTypeSignatures,
superClasses = { };
source = ObjectiveJ.preprocess(source, fileURL, flags).code();
source = source.replace(/objj_allocateClassPair\([a-zA-Z_$](\w|$)*/g, function(aString)
{
var superClassName = aString.substr("objj_allocateClassPair(".length);
return "objj_allocateClassPair(\"" + superClassName + "\", CPObject";
});
var allocateClassPair = objj_allocateClassPair;
objj_allocateClassPair = function(superClassName)
{
superClasses[arguments[2]] = superClassName;
return allocateClassPair(arguments[1], arguments[2]);
}
var classes = [],
registerClassPair = objj_registerClassPair;
objj_registerClassPair = function(aClass)
{
aClass.actual_super_class;
registerClassPair(aClass);
classes.push(aClass);
}
objj_executeFile = function()
{
}
eval(source);
var ObjectiveCSource = "";
classes.forEach(function(aClass)
{
var outlets = [];
class_copyIvarList(aClass).forEach(function(anIvar)
{
var types = ivar_getTypeEncoding(anIvar).split(" ");
if (types.indexOf("IBOutlet") !== CPNotFound || types.indexOf("@outlet") !== CPNotFound)
{
types.forEach(function(aType, anIndex)
{
if (aType === "@outlet")
types[anIndex] = "IBOutlet";
else if (aType !== "IBOutlet")
types[anIndex] = NSCompatibleClassName(aType, YES);
});
outlets.push(" " + types.join(" ") + " " + ivar_getName(anIvar) + ";");
}
});
var actions = [];
class_copyMethodList(aClass).forEach(function(aMethod)
{
var types = aMethod.types,
type = types[0];
if (type === "IBAction" || type === "@action")
actions.push("- (IBAction)" + method_getName(aMethod) + "(" + NSCompatibleClassName(types[1] || "id", YES)+ ")aSender;");
});
var className = class_getName(aClass),
superClassName = superClasses[className];
ObjectiveCSource +=
"\n@interface " + class_getName(aClass) +
(superClassName === "Nil" ? "" : (" : " + NSCompatibleClassName(superClassName))) +
"\n{\n" +
outlets.join("\n") +
"\n}\n" +
actions.join("\n") +
"\n@end";
});
if (ObjectiveCSource.length)
FILE.write(outputURL, ObjectiveCSource, { charset:"UTF-8" });
}
function NSCompatibleClassName(aClassName, asPointer)
{
if (aClassName === "var" || aClassName === "id")
return "id";
var suffix = aClassName.substr(0, 2),
asterisk = asPointer ? "*" : "";
if (suffix !== "CP")
return aClassName + asterisk;
var NSClassName = "NS" + aClassName.substr(2);
if (NSClasses[NSClassName])
return NSClassName + asterisk;
return aClassName + asterisk;
}
var NSClasses = {
"NSAffineTransform" : YES,
"NSAppleEventDescriptor" : YES,
"NSAppleEventManager" : YES,
"NSAppleScript" : YES,
"NSArchiver" : YES,
"NSArray" : YES,
"NSAssertionHandler" : YES,
"NSAttributedString" : YES,
"NSAutoreleasePool" : YES,
"NSBlockOperation" : YES,
"NSBundle" : YES,
"NSCache" : YES,
"NSCachedURLResponse" : YES,
"NSCalendar" : YES,
"NSCharacterSet" : YES,
"NSClassDescription" : YES,
"NSCloneCommand" : YES,
"NSCloseCommand" : YES,
"NSCoder" : YES,
"NSComparisonPredicate" : YES,
"NSCompoundPredicate" : YES,
"NSCondition" : YES,
"NSConditionLock" : YES,
"NSConnection" : YES,
"NSCountCommand" : YES,
"NSCountedSet" : YES,
"NSCreateCommand" : YES,
"NSData" : YES,
"NSDate" : YES,
"NSDateComponents" : YES,
"NSDateFormatter" : YES,
"NSDecimalNumber" : YES,
"NSDecimalNumberHandler" : YES,
"NSDeleteCommand" : YES,
"NSDeserializer" : YES,
"NSDictionary" : YES,
"NSDirectoryEnumerator" : YES,
"NSDistantObject" : YES,
"NSDistantObjectRequest" : YES,
"NSDistributedLock" : YES,
"NSDistributedNotificationCenter" : YES,
"NSEnumerator" : YES,
"NSError" : YES,
"NSException" : YES,
"NSExistsCommand" : YES,
"NSExpression" : YES,
"NSFileHandle" : YES,
"NSFileManager" : YES,
"NSFileWrapper" : YES,
"NSFormatter" : YES,
"NSGarbageCollector" : YES,
"NSGetCommand" : YES,
"NSHashTable" : YES,
"NSHost" : YES,
"NSHTTPCookie" : YES,
"NSHTTPCookieStorage" : YES,
"NSHTTPURLResponse" : YES,
"NSIndexPath" : YES,
"NSIndexSet" : YES,
"NSIndexSpecifier" : YES,
"NSInputStream" : YES,
"NSInvocation" : YES,
"NSInvocationOperation" : YES,
"NSKeyedArchiver" : YES,
"NSKeyedUnarchiver" : YES,
"NSLocale" : YES,
"NSLock" : YES,
"NSLogicalTest" : YES,
"NSMachBootstrapServer" : YES,
"NSMachPort" : YES,
"NSMapTable" : YES,
"NSMessagePort" : YES,
"NSMessagePortNameServer" : YES,
"NSMetadataItem" : YES,
"NSMetadataQuery" : YES,
"NSMetadataQueryAttributeValueTuple" : YES,
"NSMetadataQueryResultGroup" : YES,
"NSMethodSignature" : YES,
"NSMiddleSpecifier" : YES,
"NSMoveCommand" : YES,
"NSMutableArray" : YES,
"NSMutableAttributedString" : YES,
"NSMutableCharacterSet" : YES,
"NSMutableData" : YES,
"NSMutableDictionary" : YES,
"NSMutableIndexSet" : YES,
"NSMutableSet" : YES,
"NSMutableString" : YES,
"NSMutableURLRequest" : YES,
"NSNameSpecifier" : YES,
"NSNetService" : YES,
"NSNetServiceBrowser" : YES,
"NSNotification" : YES,
"NSNotificationCenter" : YES,
"NSNotificationQueue" : YES,
"NSNull" : YES,
"NSNumber" : YES,
"NSNumberFormatter" : YES,
"NSObject" : YES,
"NSOperation" : YES,
"NSOperationQueue" : YES,
"NSOrthography" : YES,
"NSOutputStream" : YES,
"NSPipe" : YES,
"NSPointerArray" : YES,
"NSPointerFunctions" : YES,
"NSPort" : YES,
"NSPortCoder" : YES,
"NSPortMessage" : YES,
"NSPortNameServer" : YES,
"NSPositionalSpecifier" : YES,
"NSPredicate" : YES,
"NSProcessInfo" : YES,
"NSPropertyListSerialization" : YES,
"NSPropertySpecifier" : YES,
"NSProtocolChecker" : YES,
"NSProxy" : YES,
"NSPurgeableData" : YES,
"NSQuitCommand" : YES,
"NSRandomSpecifier" : YES,
"NSRangeSpecifier" : YES,
"NSRecursiveLock" : YES,
"NSRelativeSpecifier" : YES,
"NSRunLoop" : YES,
"NSScanner" : YES,
"NSScriptClassDescription" : YES,
"NSScriptCoercionHandler" : YES,
"NSScriptCommand" : YES,
"NSScriptCommandDescription" : YES,
"NSScriptExecutionContext" : YES,
"NSScriptObjectSpecifier" : YES,
"NSScriptSuiteRegistry" : YES,
"NSScriptWhoseTest" : YES,
"NSSerializer" : YES,
"NSSet" : YES,
"NSSetCommand" : YES,
"NSSocketPort" : YES,
"NSSocketPortNameServer" : YES,
"NSSortDescriptor" : YES,
"NSSpecifierTest" : YES,
"NSSpellServer" : YES,
"NSStream" : YES,
"NSString" : YES,
"NSTask" : YES,
"NSTextCheckingResult" : YES,
"NSThread" : YES,
"NSTimer" : YES,
"NSTimeZone" : YES,
"NSUnarchiver" : YES,
"NSUndoManager" : YES,
"NSUniqueIDSpecifier" : YES,
"NSURL" : YES,
"NSURLAuthenticationChallenge" : YES,
"NSURLCache" : YES,
"NSURLConnection" : YES,
"NSURLCredential" : YES,
"NSURLCredentialStorage" : YES,
"NSURLDownload" : YES,
"NSURLHandle" : YES,
"NSURLProtectionSpace" : YES,
"NSURLProtocol" : YES,
"NSURLRequest" : YES,
"NSURLResponse" : YES,
"NSUserDefaults" : YES,
"NSValue" : YES,
"NSValueTransformer" : YES,
"NSWhoseSpecifier" : YES,
"NSXMLDocument" : YES,
"NSXMLDTD" : YES,
"NSXMLDTDNode" : YES,
"NSXMLElement" : YES,
"NSXMLNode" : YES,
"NSXMLParser" : YES,
"NSActionCell" : YES,
"NSAffineTransform Additions" : YES,
"NSAlert" : YES,
"NSAnimation" : YES,
"NSAnimationContext" : YES,
"NSAppleScript Additions" : YES,
"NSApplication" : YES,
"NSArrayController" : YES,
"NSATSTypesetter" : YES,
"NSAttributedString Application Kit Additions" : YES,
"NSBezierPath" : YES,
"NSBitmapImageRep" : YES,
"NSBox" : YES,
"NSBrowser" : YES,
"NSBrowserCell" : YES,
"NSBundle Additions" : YES,
"NSButton" : YES,
"NSButtonCell" : YES,
"NSCachedImageRep" : YES,
"NSCell" : YES,
"NSCIImageRep" : YES,
"NSClipView" : YES,
"NSCoder Application Kit Additions" : YES,
"NSCollectionView" : YES,
"NSCollectionViewItem" : YES,
"NSColor" : YES,
"NSColorList" : YES,
"NSColorPanel" : YES,
"NSColorPicker" : YES,
"NSColorSpace" : YES,
"NSColorWell" : YES,
"NSComboBox" : YES,
"NSComboBoxCell" : YES,
"NSControl" : YES,
"NSController" : YES,
"NSCursor" : YES,
"NSCustomImageRep" : YES,
"NSDatePicker" : YES,
"NSDatePickerCell" : YES,
"NSDictionaryController" : YES,
"NSDockTile" : YES,
"NSDocument" : YES,
"NSDocumentController" : YES,
"NSDrawer" : YES,
"NSEPSImageRep" : YES,
"NSEvent" : YES,
"NSFileWrapper" : YES,
"NSFont" : YES,
"NSFontDescriptor" : YES,
"NSFontManager" : YES,
"NSFontPanel" : YES,
"NSForm" : YES,
"NSFormCell" : YES,
"NSGlyphGenerator" : YES,
"NSGlyphInfo" : YES,
"NSGradient" : YES,
"NSGraphicsContext" : YES,
"NSHelpManager" : YES,
"NSImage" : YES,
"NSImageCell" : YES,
"NSImageRep" : YES,
"NSImageView" : YES,
"NSLayoutManager" : YES,
"NSLevelIndicator" : YES,
"NSLevelIndicatorCell" : YES,
"NSMatrix" : YES,
"NSMenu" : YES,
"NSMenuItem" : YES,
"NSMenuItemCell" : YES,
"NSMenuView" : YES,
"NSMutableAttributedString Additions" : YES,
"NSMutableParagraphStyle" : YES,
"NSNib" : YES,
"NSNibConnector" : YES,
"NSNibControlConnector" : YES,
"NSNibOutletConnector" : YES,
"NSObjectController" : YES,
"NSOpenGLContext" : YES,
"NSOpenGLLayer" : YES,
"NSOpenGLPixelBuffer" : YES,
"NSOpenGLPixelFormat" : YES,
"NSOpenGLView" : YES,
"NSOpenPanel" : YES,
"NSOutlineView" : YES,
"NSPageLayout" : YES,
"NSPanel" : YES,
"NSParagraphStyle" : YES,
"NSPasteboard" : YES,
"NSPasteboardItem" : YES,
"NSPathCell" : YES,
"NSPathComponentCell" : YES,
"NSPathControl" : YES,
"NSPDFImageRep" : YES,
"NSPersistentDocument" : YES,
"NSPICTImageRep" : YES,
"NSPopUpButton" : YES,
"NSPopUpButtonCell" : YES,
"NSPredicateEditor" : YES,
"NSPredicateEditorRowTemplate" : YES,
"NSPrinter" : YES,
"NSPrintInfo" : YES,
"NSPrintOperation" : YES,
"NSPrintPanel" : YES,
"NSProgressIndicator" : YES,
"NSResponder" : YES,
"NSRuleEditor" : YES,
"NSRulerMarker" : YES,
"NSRulerView" : YES,
"NSRunningApplication" : YES,
"NSSavePanel" : YES,
"NSScreen" : YES,
"NSScroller" : YES,
"NSScrollView" : YES,
"NSSearchField" : YES,
"NSSearchFieldCell" : YES,
"NSSecureTextField" : YES,
"NSSecureTextFieldCell" : YES,
"NSSegmentedCell" : YES,
"NSSegmentedControl" : YES,
"NSShadow" : YES,
"NSSlider" : YES,
"NSSliderCell" : YES,
"NSSound" : YES,
"NSSpeechRecognizer" : YES,
"NSSpeechSynthesizer" : YES,
"NSSpellChecker" : YES,
"NSSplitView" : YES,
"NSStatusBar" : YES,
"NSStatusItem" : YES,
"NSStepper" : YES,
"NSStepperCell" : YES,
"NSString Application Kit Additions" : YES,
"NSTableColumn" : YES,
"NSTableHeaderCell" : YES,
"NSTableHeaderView" : YES,
"NSTableView" : YES,
"NSTabView" : YES,
"NSTabViewItem" : YES,
"NSText" : YES,
"NSTextAttachment" : YES,
"NSTextAttachmentCell" : YES,
"NSTextBlock" : YES,
"NSTextContainer" : YES,
"NSTextField" : YES,
"NSTextFieldCell" : YES,
"NSTextInputContext" : YES,
"NSTextList" : YES,
"NSTextStorage" : YES,
"NSTextTab" : YES,
"NSTextTable" : YES,
"NSTextTableBlock" : YES,
"NSTextView" : YES,
"NSTokenField" : YES,
"NSTokenFieldCell" : YES,
"NSToolbar" : YES,
"NSToolbarItem" : YES,
"NSToolbarItemGroup" : YES,
"NSTouch" : YES,
"NSTrackingArea" : YES,
"NSTreeController" : YES,
"NSTreeNode" : YES,
"NSTypesetter" : YES,
"NSURL Additions" : YES,
"NSUserDefaultsController" : YES,
"NSView" : YES,
"NSViewAnimation" : YES,
"NSViewController" : YES,
"NSWindow" : YES,
"NSWindowController" : YES,
"NSWorkspace" : YES
};
@@ -1,354 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
9EEC4498135749D200615446 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EEC4497135749D200615446 /* Cocoa.framework */; };
9EEC44B5135749D300615446 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EEC4497135749D200615446 /* Cocoa.framework */; };
9EEC44CC13574A0B00615446 /* ${CappuccinoProjectName} in Resources */ = {isa = PBXBuildFile; fileRef = 9EEC44CB13574A0B00615446 /* ${CappuccinoProjectName} */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
9EEC44B6135749D300615446 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 9EEC448A135749D200615446 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 9EEC4492135749D200615446;
remoteInfo = Another;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
9EEC4493135749D200615446 /* Another.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Another.app; sourceTree = BUILT_PRODUCTS_DIR; };
9EEC4497135749D200615446 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
9EEC449A135749D300615446 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
9EEC449B135749D300615446 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
9EEC449C135749D300615446 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
9EEC44B4135749D300615446 /* AnotherTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AnotherTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
9EEC44CB13574A0B00615446 /* ${CappuccinoProjectName} */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ${CappuccinoProjectName}; path = ${CappuccinoProjectRelativePath}; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9EEC4490135749D200615446 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9EEC4498135749D200615446 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9EEC44B0135749D300615446 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9EEC44B5135749D300615446 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9EEC4488135749D200615446 = {
isa = PBXGroup;
children = (
9EEC44CB13574A0B00615446 /* ${CappuccinoProjectName} */,
9EEC4496135749D200615446 /* Frameworks */,
9EEC4494135749D200615446 /* Products */,
);
sourceTree = "<group>";
};
9EEC4494135749D200615446 /* Products */ = {
isa = PBXGroup;
children = (
9EEC4493135749D200615446 /* Another.app */,
9EEC44B4135749D300615446 /* AnotherTests.octest */,
);
name = Products;
sourceTree = "<group>";
};
9EEC4496135749D200615446 /* Frameworks */ = {
isa = PBXGroup;
children = (
9EEC4497135749D200615446 /* Cocoa.framework */,
9EEC4499135749D300615446 /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
9EEC4499135749D300615446 /* Other Frameworks */ = {
isa = PBXGroup;
children = (
9EEC449A135749D300615446 /* AppKit.framework */,
9EEC449B135749D300615446 /* CoreData.framework */,
9EEC449C135749D300615446 /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
9EEC4492135749D200615446 /* Another */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9EEC44C5135749D300615446 /* Build configuration list for PBXNativeTarget "Another" */;
buildPhases = (
9EEC448F135749D200615446 /* Sources */,
9EEC4490135749D200615446 /* Frameworks */,
9EEC4491135749D200615446 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Another;
productName = Another;
productReference = 9EEC4493135749D200615446 /* Another.app */;
productType = "com.apple.product-type.application";
};
9EEC44B3135749D300615446 /* AnotherTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9EEC44C8135749D300615446 /* Build configuration list for PBXNativeTarget "AnotherTests" */;
buildPhases = (
9EEC44AF135749D300615446 /* Sources */,
9EEC44B0135749D300615446 /* Frameworks */,
9EEC44B1135749D300615446 /* Resources */,
9EEC44B2135749D300615446 /* ShellScript */,
);
buildRules = (
);
dependencies = (
9EEC44B7135749D300615446 /* PBXTargetDependency */,
);
name = AnotherTests;
productName = AnotherTests;
productReference = 9EEC44B4135749D300615446 /* AnotherTests.octest */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
9EEC448A135749D200615446 /* Project object */ = {
isa = PBXProject;
attributes = {
ORGANIZATIONNAME = "280 North, Inc.";
};
buildConfigurationList = 9EEC448D135749D200615446 /* Build configuration list for PBXProject "Another" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 9EEC4488135749D200615446;
productRefGroup = 9EEC4494135749D200615446 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
9EEC4492135749D200615446 /* Another */,
9EEC44B3135749D300615446 /* AnotherTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
9EEC4491135749D200615446 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9EEC44CC13574A0B00615446 /* ${CappuccinoProjectName} in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9EEC44B1135749D300615446 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
9EEC44B2135749D300615446 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
9EEC448F135749D200615446 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
9EEC44AF135749D300615446 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
9EEC44B7135749D300615446 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 9EEC4492135749D200615446 /* Another */;
targetProxy = 9EEC44B6135749D300615446 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
9EEC44C3135749D300615446 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
9EEC44C4135749D300615446 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
SDKROOT = macosx;
};
name = Release;
};
9EEC44C6135749D300615446 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Another/Another-Prefix.pch";
INFOPLIST_FILE = "Another/Another-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
9EEC44C7135749D300615446 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Another/Another-Prefix.pch";
INFOPLIST_FILE = "Another/Another-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Release;
};
9EEC44C9135749D300615446 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Another.app/Contents/MacOS/Another";
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AnotherTests/AnotherTests-Prefix.pch";
INFOPLIST_FILE = "AnotherTests/AnotherTests-Info.plist";
OTHER_LDFLAGS = (
"-framework",
SenTestingKit,
);
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = octest;
};
name = Debug;
};
9EEC44CA135749D300615446 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Another.app/Contents/MacOS/Another";
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AnotherTests/AnotherTests-Prefix.pch";
INFOPLIST_FILE = "AnotherTests/AnotherTests-Info.plist";
OTHER_LDFLAGS = (
"-framework",
SenTestingKit,
);
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = octest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9EEC448D135749D200615446 /* Build configuration list for PBXProject "Another" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9EEC44C3135749D300615446 /* Debug */,
9EEC44C4135749D300615446 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9EEC44C5135749D300615446 /* Build configuration list for PBXNativeTarget "Another" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9EEC44C6135749D300615446 /* Debug */,
9EEC44C7135749D300615446 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
9EEC44C8135749D300615446 /* Build configuration list for PBXNativeTarget "AnotherTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9EEC44C9135749D300615446 /* Debug */,
9EEC44CA135749D300615446 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 9EEC448A135749D200615446 /* Project object */;
}
-159
View File
@@ -1,159 +0,0 @@
@import <Foundation/CPObject.j>
@import <Foundation/CPString.j>
@import <Foundation/CPDictionary.j>
@import "XCResourceMonitor.j"
var FILE = require("file"),
OS = require("os");
@implementation XCProject : CPObject
{
CFURL m_URL;
XCResourceMonitor m_sourceResourceMonitor;
XCResourceMonitor m_nibResourceMonitor;
CFURL m_xCodeProjectURL;
CFURL m_xCodeProjectFileURL;
CFURL m_xCodeSupportSourcesURL;
}
- (id)initWithPath:(CPString)aPath
{
self = [super init];
if (self)
{
m_URL = new CFURL(aPath);
[self prepare_xCodeProject];
m_sourceResourceMonitor = [[XCResourceCollection alloc] initWithPattern:FILE.join(m_URL, "/**/*.j")];
m_nibResourceMonitor = [[XCResourceCollection alloc] initWithPattern:FILE.join(m_URL, "/**/*.[nx]ib")];
[self launch];
}
return self;
}
- (CPString)projectName
{
return m_URL.lastPathComponent();
}
- (CFURL)xCodeProjectTemplateURL
{
var CAPP_HOME = require("narwhal/packages").catalog["cappuccino"].directory;
return new CFURL(FILE.join(CAPP_HOME, "lib", "xcodecapp", "Resources", "xCodeSupport.xcodeproj"));
}
- (CFURL)xCodeProjectParserURL
{
var CAPP_HOME = require("narwhal/packages").catalog["cappuccino"].directory;
return new CFURL(FILE.join(CAPP_HOME, "lib", "xcodecapp", "Resources", "FIXME_parser.j"));
}
- (void)launch
{
OS.system("open " + m_xCodeProjectFileURL);
}
- (void)prepare_xCodeProject
{
m_xCodeProjectURL = new CFURL(".xCodeSupport", m_URL.asDirectoryPathURL());
if (FILE.exists(m_xCodeProjectURL))
FILE.rmtree(m_xCodeProjectURL);
FILE.mkdir(m_xCodeProjectURL);
var projectName = [self projectName],
xCodeProjectTemplateURL = [self xCodeProjectTemplateURL];
m_xCodeProjectFileURL = new CFURL(projectName + ".xcodeproj", m_xCodeProjectURL.asDirectoryPathURL());
FILE.copyTree(xCodeProjectTemplateURL, m_xCodeProjectFileURL.absoluteURL());
var pbxprojURL = new CFURL("project.pbxproj", m_xCodeProjectFileURL.asDirectoryPathURL()),
pbxproj = FILE.read(pbxprojURL, { charset:"UTF-8" });
pbxproj = pbxproj.replace(/\$\{CappuccinoProjectName\}/g, projectName);
pbxproj = pbxproj.replace(/\$\{CappuccinoProjectRelativePath\}/g, FILE.join("..", "..", projectName));
FILE.write(pbxprojURL, pbxproj, { charset:"UTF-8" });
m_xCodeSupportSourcesURL = new CFURL("Sources", m_xCodeProjectURL.asDirectoryPathURL());
FILE.mkdir(m_xCodeSupportSourcesURL);
}
- (void)update
{
[self updateSourceFiles];
[self updateNibFiles];
}
- (CPURL)shadowURLForSourceURL:(CPURL)aSourceURL
{
var flattenedPath = (aSourceURL + "").replace(new RegExp("\/", "g"), "_"),
extension = FILE.extension(flattenedPath),
basename = flattenedPath.substr(0, flattenedPath.length - extension.length) + ".h";
return new CFURL(basename, m_xCodeSupportSourcesURL.asDirectoryPathURL());
}
- (void)updateSourceFiles
{
// Require the new parser for this.
[m_sourceResourceMonitor update];
[m_sourceResourceMonitor addedFilePaths].forEach(function(aFilePath)
{
print("Added " + aFilePath);
OS.system("objj " + [self xCodeProjectParserURL] + " " + aFilePath + " " + [self shadowURLForSourceURL:aFilePath]);
});
[m_sourceResourceMonitor editedFilePaths].forEach(function(aFilePath)
{
print("Edited " + aFilePath);
OS.system("objj " + [self xCodeProjectParserURL] + " " + aFilePath + " " + [self shadowURLForSourceURL:aFilePath]);
});
[m_sourceResourceMonitor removedFilePaths].forEach(function(aFilePath)
{
print("Removed " + aFilePath);
FILE.remove([self shadowURLForSourceURL:aFilePath]);
});
}
- (void)updateNibFiles
{
[m_nibResourceMonitor update];
[m_nibResourceMonitor addedFilePaths].forEach(function(aFilePath)
{
print("Added " + aFilePath);
OS.system("nib2cib " + aFilePath);
});
[m_nibResourceMonitor editedFilePaths].forEach(function(aFilePath)
{
print("Edited " + aFilePath);
OS.system("nib2cib " + aFilePath);
});
[m_nibResourceMonitor removedFilePaths].forEach(function(aFilePath)
{
// delete?
print("Removed " + aFilePath);
// OS.system("nib2cib " + aFilePath);
});
}
@end
-71
View File
@@ -1,71 +0,0 @@
@import <Foundation/CPObject.j>
var FILE = require("file"),
FileList = require("jake").FileList;
@implementation XCResourceCollection : CPObject
{
CPString m_pattern;
CPDictionary m_mtimesForFilePaths;
CPMutableArray m_addedFilePaths @accessors(readonly, getter=addedFilePaths);
CPMutableArray m_removedFilePaths @accessors(readonly, getter=removedFilePaths);
CPMutableArray m_editedFilePaths @accessors(readonly, getter=editedFilePaths);
}
- (id)initWithPattern:(CPString)aPattern
{
self = [super init];
if (self)
m_pattern = aPattern;
return self;
}
- (void)update
{
m_addedFilePaths = [];
m_removedFilePaths = [];
m_editedFilePaths = [];
// FIXME: There must be a better way to do this.
var subProjects = new FileList(FILE.join(FILE.dirname(FILE.dirname(m_pattern)), "*/**/Jakefile")),
paths = new FileList(m_pattern);
subProjects.forEach(function(aPath)
{
paths.exclude(FILE.join(FILE.dirname(aPath), "**", "*"));
});
paths.exclude(FILE.join("Build", "**", "*"));
var mtimesForFilePaths = [CPMutableDictionary new];
paths.forEach(function(aPath)
{
var time = [m_mtimesForFilePaths objectForKey:aPath],
current = FILE.mtime(aPath);
if (time === nil)
[m_addedFilePaths addObject:aPath];
else if (current > time)
[m_editedFilePaths addObject:aPath];
[mtimesForFilePaths setObject:current forKey:aPath];
});
var filePath = nil,
filePaths = [m_mtimesForFilePaths keyEnumerator];
while (filePath = [filePaths nextObject])
if ([mtimesForFilePaths objectForKey:filePath] === nil)
[m_removedFilePaths addObject:filePath];
m_mtimesForFilePaths = mtimesForFilePaths;
}
@end
-15
View File
@@ -1,15 +0,0 @@
@import "XCProject.j"
var FILE = require("file"),
OS = require("os");
var project = [[XCProject alloc] initWithPath:FILE.cwd()];
while (YES)
{
[project update];
OS.sleep(1);
}