Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 12 additions & 18 deletions Info.plist
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,33 @@
<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>
<string>37B30044-3B14-46BA-ABAA-F01000C27B63</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/>
</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