Skip to content

Commit

Permalink
Updated project to Xcode8 extension
Browse files Browse the repository at this point in the history
  • Loading branch information
insanoid committed Oct 28, 2016
1 parent 0837c7e commit 732e0c4
Show file tree
Hide file tree
Showing 29 changed files with 1,836 additions and 943 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
49 changes: 49 additions & 0 deletions CleanHeaders-Xcode-Extension/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Sort Headers</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>XCSourceEditorCommandDefinitions</key>
<array>
<dict>
<key>XCSourceEditorCommandClassName</key>
<string>SourceEditorCommand</string>
<key>XCSourceEditorCommandIdentifier</key>
<string>com.karthik.cleanHeader-Xcode</string>
<key>XCSourceEditorCommandName</key>
<string>Sort Headers</string>
</dict>
</array>
<key>XCSourceEditorExtensionPrincipalClass</key>
<string>SourceEditorExtension</string>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.dt.Xcode.extension.source-editor</string>
</dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Karthik. All rights reserved.</string>
</dict>
</plist>
107 changes: 107 additions & 0 deletions CleanHeaders-Xcode-Extension/SortHeader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//
// SortHeader.h
// CleanHeaders-Xcode
//
// Created by Karthik on 28/10/2016.
// Copyright © 2016 Karthik. All rights reserved.
//

#import <XcodeKit/XcodeKit.h>

static inline NSArray *formatSelectionLines(NSArray *sourceLines) {

NSMutableArray *lines = [[NSMutableArray alloc] initWithArray:sourceLines];

// Let's assume all header files start with an #import, #include, @import,
// import.
NSString *traditionalImportPrefix = @"#import";
NSString *frameworkImportPrefix = @"@import";
NSString *traditionalIncludePrefix = @"#include";
NSString *swiftPrefix = @"import";

// Position of the first and last line of header, to be used for repalcement
// of header content.
NSInteger __block initalIndex = -1;
NSInteger __block lastIndex = -1;
BOOL __block endOfFileWithNewLine = YES; // Indicates if the selection's last
// line was a new line.
NSMutableArray *headerRows = [[NSMutableArray alloc] init];

// Go through each of the line and identify any header elements.
[lines enumerateObjectsUsingBlock:^(NSString *string, NSUInteger idx,
BOOL *_Nonnull stop) {
NSString *cleansedLine =
[string stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];

BOOL isLineHeader = [cleansedLine hasPrefix:traditionalImportPrefix] ||
[cleansedLine hasPrefix:traditionalIncludePrefix] ||
[cleansedLine hasPrefix:frameworkImportPrefix] ||
[cleansedLine hasPrefix:swiftPrefix];

// If the line is a header and no header element has been detected so far,
// mark this as the start of the header segment.
if (isLineHeader && initalIndex < 0) {
initalIndex = idx;
} else if (initalIndex >= 0 && !(isLineHeader || ![cleansedLine length])) {
// If the inital index has been set AND the line is not a header or a new
// line, then this is to be marked as the end of header segment and
// enumeration has to be stopped.
lastIndex = idx;
*stop = YES;
}

if (initalIndex >= 0 && lastIndex < 0) {
// If the inital index is already set and we are in this condition it
// means we are parsing the header. Check for duplicates and ensure that
// it is not a new line and then add to the header rows array.
if (![headerRows containsObject:[cleansedLine stringByAppendingString:@"\n"]] &&
[cleansedLine length]) {
cleansedLine = [cleansedLine stringByAppendingString:@"\n"];
[headerRows addObject:cleansedLine];
}
}

// Reached the end of the selection or a file. (In case of a selection or a
// header only file)
if (idx >= lines.count - 1) {
lastIndex = idx + 1;

// If the end was a header and not a new line and also marked the end of
// selection, a new line would look odd.
if ([cleansedLine length]) {
endOfFileWithNewLine = NO;
}
}
}];

// If both the indices are set it means that we have a header section in the
// file and it needs replacing after sorting.
if (lastIndex >= 0 && initalIndex >= 0) {
[headerRows sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
// Add a new line to make it look clean (if needed, if only header is selected then don't)
// This is a flawed logic, but cannot think of a perfect way to do it right now.
if (endOfFileWithNewLine && !(headerRows.count == lines.count)) {
[headerRows addObject:@"\n"];
} else if((headerRows.count == lines.count) && headerRows.count) {
// Avoid extra line if one selects only the header and keeps sorting them.
NSString *lastHeader = [headerRows lastObject];
lastHeader = [lastHeader stringByReplacingOccurrencesOfString:@"\n" withString:@""];
[headerRows replaceObjectAtIndex:headerRows.count - 1 withObject:lastHeader];
}
// replace it in the array of all lines.
[lines replaceObjectsInRange:NSMakeRange(initalIndex,
(lastIndex - initalIndex))
withObjectsFromArray:headerRows];
}

return lines;
}

static inline NSString *formatSelection(NSString *content) {

// Convert the entire source into an array based on new lines.
// Hence the imports have to be alteast in new line to work.
return [formatSelectionLines([content componentsSeparatedByString:@"\n"])
componentsJoinedByString:@""];
}
13 changes: 13 additions & 0 deletions CleanHeaders-Xcode-Extension/SourceEditorCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SourceEditorCommand.h
// CleanHeaders-Xcode-Extension
//
// Created by Karthik on 28/10/2016.
// Copyright © 2016 Karthik. All rights reserved.
//

#import <XcodeKit/XcodeKit.h>

@interface SourceEditorCommand : NSObject <XCSourceEditorCommand>

@end
36 changes: 36 additions & 0 deletions CleanHeaders-Xcode-Extension/SourceEditorCommand.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// SourceEditorCommand.m
// CleanHeaders-Xcode-Extension
//
// Created by Karthik on 28/10/2016.
// Copyright © 2016 Karthik. All rights reserved.
//

#import "SourceEditorCommand.h"
#import "SortHeader.h"
#import "xTextModifier.h"

@implementation SourceEditorCommand

- (void)performCommandWithInvocation:(XCSourceEditorCommandInvocation *)invocation
completionHandler:(void (^)(NSError * _Nullable nilOrError))completionHandler {
[xTextModifier select:invocation
handler:self.handlers[invocation.commandIdentifier]
handlerForAllContent:self.handlers[@"all_source"]];
completionHandler(nil);
}

- (NSDictionary *)handlers {
static NSDictionary *_instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = @{
@"com.karthik.cleanHeader-Xcode":
^NSString *(NSString *text) { return formatSelection(text); },
@"all_source":
^NSArray *(NSArray *lines) { return formatSelectionLines(lines); }
};
});
return _instance;
}
@end
13 changes: 13 additions & 0 deletions CleanHeaders-Xcode-Extension/SourceEditorExtension.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SourceEditorExtension.h
// CleanHeaders-Xcode-Extension
//
// Created by Karthik on 28/10/2016.
// Copyright © 2016 Karthik. All rights reserved.
//

#import <XcodeKit/XcodeKit.h>

@interface SourceEditorExtension : NSObject <XCSourceEditorExtension>

@end
13 changes: 13 additions & 0 deletions CleanHeaders-Xcode-Extension/SourceEditorExtension.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SourceEditorExtension.m
// CleanHeaders-Xcode-Extension
//
// Created by Karthik on 28/10/2016.
// Copyright © 2016 Karthik. All rights reserved.
//

#import "SourceEditorExtension.h"

@implementation SourceEditorExtension

@end
55 changes: 55 additions & 0 deletions CleanHeaders-Xcode-Extension/xTextMatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// xTextMatcher.h
// xTextHandler
//
// Created by cyan on 16/6/18.
// Copyright © 2016年 cyan. All rights reserved.
//

#import <XcodeKit/XcodeKit.h>

static NSString *const xTextHandlerStringPattern = @"\"(.+)\""; // match "abc"
static NSString *const xTextHandlerHexPattern = @"([0-9a-fA-F]+)"; // match 00FFFF
static NSString *const xTextHandlerRGBPattern = @"([0-9]+.+[0-9]+.+[0-9]+)"; // match 20, 20, 20 | 20 20 20 ...
static NSString *const xTextHandlerRadixPattern = @"([0-9]+)"; // match numbers

@interface xTextMatchResult : NSObject

@property (nonatomic, copy) NSString *text; // text for each lines
@property (nonatomic, assign) NSRange range; // clipped text range
@property (nonatomic, assign) BOOL clipboard; // is clipboard text


/**
Result from clipboard text
@return xTextMatchResult
*/
+ (instancetype)clipboardResult;

/**
Result with text & clipped text
@param text text
@param clipped clipped text
@return xTextMatchResult
*/
+ (instancetype)resultWithText:(NSString *)text clipped:(NSString *)clipped;

@end

@interface xTextMatcher : NSObject


/**
Match texts in XCSourceEditorCommandInvocation
@param selection XCSourceTextRange
@param invocation XCSourceEditorCommandInvocation
@return match result
*/
+ (xTextMatchResult *)match:(XCSourceTextRange *)selection invocation:(XCSourceEditorCommandInvocation *)invocation;

@end
Loading

0 comments on commit 732e0c4

Please sign in to comment.