Skip to content

Commit

Permalink
Improved Xcode4/5 support, improved loader, install routine, code cle…
Browse files Browse the repository at this point in the history
…anup.

Moved loading routies to more reliable XCFixin model. Eliminated
unneccesary and non-functional install scripts with simple compiler
directives and removed unneccesary version.plist .  Tidied codebase.
Small edit to Readme regarding  ~/.MacOSX/environment cariable used in
info.plist.  Changed schemes.. one for xcode4, one for xcode5 vs.
debug/release.
  • Loading branch information
mralexgray committed Sep 1, 2013
1 parent ad35c47 commit 7a978b7
Show file tree
Hide file tree
Showing 10 changed files with 374 additions and 404 deletions.
33 changes: 11 additions & 22 deletions Info.plist
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,32 @@
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>ru.DeepIT.${PRODUCT_NAME}</string>
<string>${DEVELOPER_DOMAIN}.${PRODUCT_NAME:rfc1034Identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.9</string>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>109</string>
<key>LoadAtLaunch</key>
<true/>
<key>NSPrincipalClass</key>
<string>XcodeColors</string>
<key>SIMBLTargetApplications</key>
<string>1</string>
<key>DVTPlugInCompatibilityUUIDs</key>
<array>
<dict>
<key>BundleIdentifier</key>
<string>com.apple.Xcode</string>
</dict>
<dict>
<key>BundleIdentifier</key>
<string>com.apple.dt.Xcode</string>
</dict>
<string>63FC1C47-140D-42B0-BB4D-A10B2D225574</string>
</array>
<key>NSPrincipalClass</key>
<string>XcodeColors</string>
<key>XC4Compatible</key>
<true/>
<key>XC5Compatible</key>
<true/>
<key>XCGCReady</key>
<true/>
<key>XCPluginHasUI</key>
<false/>
<key>XC4Compatible</key>
<true/>
<key>DVTPlugInCompatibilityUUIDs</key>
<array>
<string>63FC1C47-140D-42B0-BB4D-A10B2D225574</string>
</array>
</dict>
</plist>
8 changes: 7 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ You're not limited to a restricted color palate.
You can specify, in your source code, the exact RGB values you'd like to use.
You can specify foreground and/or background color(s).

XcodeColors is a simple plugin for Xcode 3 & 4.
XcodeColors is a simple plugin for Xcode 3 & 4 (and NOW 5!).

Before building... add your 'CFBundleIdentifier' to your "~/.MacOSX/environment" via the terminal..

`defaults write ~/.MacOSX/environment DEVELOPER_DOMAIN -string "com.yourdomain"`

You may need to logout/in for this change to reflect. This enables a unique Budle identifier via the variable `${DEVELOPER_DOMAIN}.${PRODUCT_NAME:rfc1034Identifier}`

***

Expand Down
68 changes: 68 additions & 0 deletions XCFixin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#import <Foundation/Foundation.h>

#define XCFixinPreflight() \
if (!XCFixinShouldLoad()) \
return; \
\
static NSUInteger loadAttempt = 0; \
loadAttempt++; \
NSLog(@"%@ initialization attempt %ju/%ju...", \
NSStringFromClass([self class]), \
(uintmax_t)loadAttempt, \
(uintmax_t)XCFixinMaxLoadAttempts);

#define XCFixinPostflight() \
NSLog(@"%@ initialization successful!", NSStringFromClass([self class])); \
return; \
failed: \
{ \
NSLog(@"%@ initialization failed.", NSStringFromClass([self class])); \
\
if (loadAttempt < XCFixinMaxLoadAttempts) \
{ \
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC), dispatch_get_main_queue(), \
^(void) \
{ \
[self pluginDidLoad: plugin]; \
}); \
} \
\
else NSLog(@"%@ failing permanently. :(", NSStringFromClass([self class])); \
}

#define XCFixinAssertMessageFormat @"Assertion failed (file: %s, function: %s, line: %u): %s\n"
#define XCFixinNoOp (void)0

#define XCFixinAssertOrPerform(condition, action) \
({ \
bool __evaluated_condition = false; \
\
__evaluated_condition = (condition); \
\
if (!__evaluated_condition) \
{ \
NSLog(XCFixinAssertMessageFormat, __FILE__, __PRETTY_FUNCTION__, __LINE__, (#condition)); \
action; \
} \
})

#define XCFixinAssertOrRaise(condition) XCFixinAssertOrPerform((condition), [NSException raise: NSGenericException format: @"An XCFixin exception occurred"])

#define XCFixinConfirmOrPerform(condition, action) \
({ \
if (!(condition)) \
{ \
action; \
} \
})

BOOL XCFixinShouldLoad(void);
extern const NSUInteger XCFixinMaxLoadAttempts;

/* This function overrides a method at the given class level, and returns the old implementation. If no method existed at
the given class' level, a new method is created at that level, and the superclass' (or super-superclass', and so on)
implementation is returned.
This function returns nil on failure. */
IMP XCFixinOverrideMethod(Class class, SEL selector, IMP newImplementation);
#define XCFixinOverrideMethodString(className, selector, newImplementation) XCFixinOverrideMethod(NSClassFromString(className), selector, newImplementation)
88 changes: 88 additions & 0 deletions XCFixin.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#import "XCFixin.h"
#import <objc/runtime.h>

BOOL XCFixinShouldLoad(void)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
BOOL result = NO;

/* Prevent our plugins from loading in non-IDE processes, like xcodebuild. */
NSString *processName = [[NSProcessInfo processInfo] processName];
XCFixinConfirmOrPerform([processName caseInsensitiveCompare: @"xcode"] == NSOrderedSame, goto cleanup);

/* Prevent our plugins from loading in Xcode versions < 4. */
NSArray *versionComponents = [[[NSBundle mainBundle] objectForInfoDictionaryKey: @"CFBundleShortVersionString"] componentsSeparatedByString: @"."];
XCFixinConfirmOrPerform(versionComponents && [versionComponents count], goto cleanup);
NSInteger xcodeMajorVersion = [[versionComponents objectAtIndex: 0] integerValue];
XCFixinConfirmOrPerform(xcodeMajorVersion >= 4, goto cleanup);

result = YES;

cleanup:
{
[pool release],
pool = nil;
}

return result;
}

const NSUInteger XCFixinMaxLoadAttempts = 3;
IMP XCFixinOverrideMethod(Class class, SEL selector, IMP newImplementation)
{
Method *classMethods = nil;
IMP result = nil;

XCFixinAssertOrPerform(class, goto cleanup);
XCFixinAssertOrPerform(selector, goto cleanup);
XCFixinAssertOrPerform(newImplementation, goto cleanup);

Method originalMethod = class_getInstanceMethod(class, selector);
XCFixinAssertOrPerform(originalMethod, goto cleanup);

IMP originalImplementation = method_getImplementation(originalMethod);
unsigned int classMethodsCount = 0;
classMethods = class_copyMethodList(class, &classMethodsCount);
XCFixinAssertOrPerform(classMethods, goto cleanup);

/* Check to see if the method is defined at the level of 'class', rather than at a super class' level. */
BOOL methodDefined = NO;
for (unsigned int i = 0; i < classMethodsCount; i++)
{
if (classMethods[i] == originalMethod)
{
methodDefined = YES;
break;
}
}

/* If the method's defined at the level of 'class', then we'll just set its implementation. */
if (methodDefined)
{
IMP setImplementationResult = method_setImplementation(originalMethod, newImplementation);
XCFixinAssertOrPerform(setImplementationResult, goto cleanup);
}

/* If the method isn't defined at the level of 'class' (and therefore it's defined at a superclass' level), then
we need to add a method to the level of 'class'. */
else
{
/* Use the return/argument types for the existing method. */
const char *types = method_getTypeEncoding(originalMethod);
XCFixinAssertOrPerform(types, goto cleanup);

BOOL addMethodResult = class_addMethod(class, selector, newImplementation, types);
XCFixinAssertOrPerform(addMethodResult, goto cleanup);
}

result = originalImplementation;

cleanup:
{
if (classMethods)
free(classMethods),
classMethods = nil;
}

return result;
}
6 changes: 0 additions & 6 deletions XcodeColors.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,8 @@
#import <Cocoa/Cocoa.h>

@interface XcodeColors_NSTextStorage : NSTextStorage

- (void)fixAttributesInRange:(NSRange)aRange;

@end

@interface XcodeColors : NSObject

+ (void)pluginDidLoad:(id)xcodeDirectCompatibility;
- (void)registerLaunchSystemDescriptions;

@end
Loading

0 comments on commit 7a978b7

Please sign in to comment.