Skip to content

Commit ea4f3dc

Browse files
Add support for adding build setting info comments in generated files.
Add ability to open folder of generated files in Finder when done.
1 parent 6e9c573 commit ea4f3dc

File tree

9 files changed

+269
-17
lines changed

9 files changed

+269
-17
lines changed

BuildSettingExtractor.xcodeproj/project.pbxproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
53719EB319BF4C6D005D3DE0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53719E9219BF4C6D005D3DE0 /* Cocoa.framework */; };
1919
53719EBB19BF4C6D005D3DE0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 53719EB919BF4C6D005D3DE0 /* InfoPlist.strings */; };
2020
53719EBD19BF4C6D005D3DE0 /* BuildSettingExtractorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 53719EBC19BF4C6D005D3DE0 /* BuildSettingExtractorTests.m */; };
21+
538196C51A851BB40033CB65 /* BuildSettingInfoSubpaths.plist in Resources */ = {isa = PBXBuildFile; fileRef = 538196C41A851BB40033CB65 /* BuildSettingInfoSubpaths.plist */; };
22+
53BC11311A817447005E2FD2 /* BuildSettingInfoSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 53BC11301A817447005E2FD2 /* BuildSettingInfoSource.m */; };
2123
53F372ED1A7BC6A7006118CB /* DragFileView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F372EC1A7BC6A7006118CB /* DragFileView.m */; };
2224
53F372F01A7C042F006118CB /* BuildSettingExtractor.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F372EF1A7C042F006118CB /* BuildSettingExtractor.m */; };
2325
53F372F41A7C0CBE006118CB /* ThreeBuildConfigs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 53F372F31A7C0CBE006118CB /* ThreeBuildConfigs.plist */; };
@@ -55,7 +57,10 @@
5557
53719EB819BF4C6D005D3DE0 /* BuildSettingExtractorTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BuildSettingExtractorTests-Info.plist"; sourceTree = "<group>"; };
5658
53719EBA19BF4C6D005D3DE0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5759
53719EBC19BF4C6D005D3DE0 /* BuildSettingExtractorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BuildSettingExtractorTests.m; sourceTree = "<group>"; };
60+
538196C41A851BB40033CB65 /* BuildSettingInfoSubpaths.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = BuildSettingInfoSubpaths.plist; sourceTree = "<group>"; };
5861
5395AF4D1A7C6BB60028BE88 /* ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = ReadMe.md; sourceTree = "<group>"; };
62+
53BC112F1A817447005E2FD2 /* BuildSettingInfoSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuildSettingInfoSource.h; sourceTree = "<group>"; };
63+
53BC11301A817447005E2FD2 /* BuildSettingInfoSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BuildSettingInfoSource.m; sourceTree = "<group>"; };
5964
53F372EB1A7BC6A7006118CB /* DragFileView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragFileView.h; sourceTree = "<group>"; };
6065
53F372EC1A7BC6A7006118CB /* DragFileView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DragFileView.m; sourceTree = "<group>"; };
6166
53F372EE1A7C042F006118CB /* BuildSettingExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuildSettingExtractor.h; sourceTree = "<group>"; };
@@ -133,12 +138,15 @@
133138
53719EA519BF4C6D005D3DE0 /* AppDelegate.m */,
134139
53F372EE1A7C042F006118CB /* BuildSettingExtractor.h */,
135140
53F372EF1A7C042F006118CB /* BuildSettingExtractor.m */,
141+
53BC112F1A817447005E2FD2 /* BuildSettingInfoSource.h */,
142+
53BC11301A817447005E2FD2 /* BuildSettingInfoSource.m */,
136143
53F372EB1A7BC6A7006118CB /* DragFileView.h */,
137144
53F372EC1A7BC6A7006118CB /* DragFileView.m */,
138145
53F372F91A7C5803006118CB /* Constants+Categories.h */,
139146
53F372FA1A7C5803006118CB /* Constants+Categories.m */,
140147
53719EA719BF4C6D005D3DE0 /* MainMenu.xib */,
141148
53719EAA19BF4C6D005D3DE0 /* Images.xcassets */,
149+
538196C41A851BB40033CB65 /* BuildSettingInfoSubpaths.plist */,
142150
53719E9919BF4C6D005D3DE0 /* Supporting Files */,
143151
);
144152
path = BuildSettingExtractor;
@@ -260,6 +268,7 @@
260268
buildActionMask = 2147483647;
261269
files = (
262270
53719E9D19BF4C6D005D3DE0 /* InfoPlist.strings in Resources */,
271+
538196C51A851BB40033CB65 /* BuildSettingInfoSubpaths.plist in Resources */,
263272
53719EAB19BF4C6D005D3DE0 /* Images.xcassets in Resources */,
264273
53719EA319BF4C6D005D3DE0 /* Credits.rtf in Resources */,
265274
53719EA919BF4C6D005D3DE0 /* MainMenu.xib in Resources */,
@@ -286,6 +295,7 @@
286295
53F372F01A7C042F006118CB /* BuildSettingExtractor.m in Sources */,
287296
53719EA619BF4C6D005D3DE0 /* AppDelegate.m in Sources */,
288297
53F372ED1A7BC6A7006118CB /* DragFileView.m in Sources */,
298+
53BC11311A817447005E2FD2 /* BuildSettingInfoSource.m in Sources */,
289299
53719E9F19BF4C6D005D3DE0 /* main.m in Sources */,
290300
);
291301
runOnlyForDeploymentPostprocessing = 0;

BuildSettingExtractor/AppDelegate.m

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,12 @@ @interface AppDelegate () <NSOpenSavePanelDelegate>
1919
@property (assign) IBOutlet NSWindow *window;
2020
@property (weak) IBOutlet DragFileView *dragFileView;
2121

22-
@property BuildSettingExtractor *buildSettingExtractor;
2322
@property BOOL shouldOverwriteFiles;
2423

25-
26-
@property (strong, nonatomic) NSDictionary *buildSettingHelpStringsFile;
27-
2824
@end
2925

3026
@implementation AppDelegate
3127

32-
- (instancetype)init {
33-
self = [super init];
34-
if (self) {
35-
_buildSettingExtractor = [[BuildSettingExtractor alloc] init];
36-
37-
}
38-
return self;
39-
}
40-
4128
- (void)awakeFromNib {
4229
self.dragFileView.target = self;
4330
self.dragFileView.action = @selector(handleDroppedFile:);
@@ -68,7 +55,16 @@ - (IBAction)handleDroppedFile:(DragFileView *)sender {
6855
[openPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
6956
if (result == NSModalResponseOK) {
7057
NSURL *destinationURL = openPanel.URL;
71-
[self.buildSettingExtractor extractBuildSettingsFromProject:fileURL toDestinationFolder:destinationURL];
58+
59+
BuildSettingExtractor *buildSettingExtractor = [[BuildSettingExtractor alloc] init];
60+
buildSettingExtractor.includeBuildSettingInfoComments = [[NSUserDefaults standardUserDefaults] boolForKey:TPSIncludeBuildSettingInfoComments];
61+
62+
[buildSettingExtractor extractBuildSettingsFromProject:fileURL toDestinationFolder:destinationURL];
63+
64+
BOOL openInFinder = [[NSUserDefaults standardUserDefaults] boolForKey:TPSOpenDirectoryInFinder];
65+
if (openInFinder) {
66+
[[NSWorkspace sharedWorkspace] openURL:destinationURL];
67+
}
7268
}
7369

7470
}];
@@ -134,5 +130,10 @@ - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
134130
return YES;
135131
}
136132

133+
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
134+
NSDictionary *defaults = @{TPSOpenDirectoryInFinder:@(YES), TPSIncludeBuildSettingInfoComments:@(YES)};
135+
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
136+
}
137+
137138

138139
@end

BuildSettingExtractor/BuildSettingExtractor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
// The name that will be used to name the project configuration. Default is "Project".
1818
@property (copy) NSString *projectConfigName;
1919

20+
// Should each build setting be commented with title and description, if available.
21+
@property (assign) BOOL includeBuildSettingInfoComments;
22+
2023
- (void)extractBuildSettingsFromProject:(NSURL *)projectWrapperURL toDestinationFolder:(NSURL *)folderURL;
2124

2225
@end

BuildSettingExtractor/BuildSettingExtractor.m

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
//
88

99
#import "BuildSettingExtractor.h"
10+
#import "BuildSettingInfoSource.h"
1011
#import "Constants+Categories.h"
1112

1213
static NSString * const XcodeCompatibilityVersionString = @"Xcode 3.2";
1314

1415
@interface BuildSettingExtractor ()
1516
@property (strong) NSMutableDictionary *buildSettingsByTarget;
1617
@property (strong) NSDictionary *objects;
18+
19+
@property (strong) BuildSettingInfoSource *buildSettingInfoSource;
1720
@end
1821

1922
@implementation BuildSettingExtractor
@@ -24,6 +27,7 @@ - (instancetype)init {
2427
_sharedConfigName = @"Shared";
2528
_projectConfigName = @"Project";
2629
_buildSettingsByTarget = [[NSMutableDictionary alloc] init];
30+
_buildSettingInfoSource = [[BuildSettingInfoSource alloc] init];
2731
}
2832
return self;
2933
}
@@ -116,12 +120,13 @@ - (void)writeConfigFilesToDestinationFolder:(NSURL *)destinationURL {
116120
// If the config name is not the shared config, we need to import the shared config
117121
if (![configName isEqualToString:self.sharedConfigName]) {
118122
NSString *configFilename = [self configFilenameWithTargetName:targetName configName:self.sharedConfigName];
119-
NSString *includeDirective = [NSString stringWithFormat:@"#include \"%@\"\n\n", configFilename];
123+
NSString *includeDirective = [NSString stringWithFormat:@"\n\n#include \"%@\"", configFilename];
120124
configFileString = [configFileString stringByAppendingString:includeDirective];
121125
}
122126

123127
// If there are no settings at all, add a comment that the lack of settings is on purpose
124128
if ([settings isEqualToString:@""]) {
129+
settings = [settings stringByAppendingString:@"\n\n"];
125130
settings = [settings stringByAppendingString:@"//********************************************//\n"];
126131
settings = [settings stringByAppendingString:@"//* Currently no build settings in this file *//\n"];
127132
settings = [settings stringByAppendingString:@"//********************************************//"];
@@ -159,8 +164,7 @@ - (NSString *)headerCommentForFilename:(NSString *)filename {
159164
headerComment = [headerComment stringByAppendingString:@"//\n"];
160165
headerComment = [headerComment stringByAppendingFormat:@"// Generated by BuildSettingExtractor on %@\n", dateString];
161166
headerComment = [headerComment stringByAppendingString:@"// https://github.com/dempseyatgithub/BuildSettingExtractor\n"];
162-
headerComment = [headerComment stringByAppendingString:@"//\n"];
163-
headerComment = [headerComment stringByAppendingString:@"\n"];
167+
headerComment = [headerComment stringByAppendingString:@"//"];
164168

165169
return headerComment;
166170
}
@@ -176,6 +180,11 @@ - (NSString *)stringRepresentationOfBuildSettings:(NSDictionary *)buildSettings
176180
for (NSString *key in sortedKeys) {
177181
id value = buildSettings[key];
178182

183+
if (self.includeBuildSettingInfoComments) {
184+
NSString *comment = [self.buildSettingInfoSource commentForBuildSettingWithName:key];
185+
[string appendString:comment];
186+
}
187+
179188
if ([value isKindOfClass:[NSString class]]) {
180189
[string appendFormat:@"%@ = %@\r", key, value];
181190

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// BuildSettingInfoSource.h
3+
// BuildSettingExtractor
4+
//
5+
// Created by James Dempsey on 2/3/15.
6+
// Copyright (c) 2015 Tapas Software. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
@interface BuildSettingInfoSource : NSObject
12+
13+
- (NSString *)commentForBuildSettingWithName:(NSString *)buildSettingName;
14+
15+
@end
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
//
2+
// BuildSettingInfoSource.m
3+
// BuildSettingExtractor
4+
//
5+
// Created by James Dempsey on 2/3/15.
6+
// Copyright (c) 2015 Tapas Software. All rights reserved.
7+
//
8+
9+
#define MAX_LINE_LENGTH 87 // For 90 columns, minus three (comment slashes and a space)
10+
11+
#import "BuildSettingInfoSource.h"
12+
#import "Constants+Categories.h"
13+
14+
@interface BuildSettingInfoSource ()
15+
16+
@property (strong, nonatomic) NSDictionary *buildSettingInfoDictionary;
17+
18+
@end
19+
20+
21+
@implementation BuildSettingInfoSource
22+
23+
24+
- (NSString *)commentForBuildSettingWithName:(NSString *)buildSettingName {
25+
NSMutableString *comment = [[NSMutableString alloc] init];
26+
27+
NSString *presentationName = [self presentationNameForKey:buildSettingName];
28+
NSString *settingDescription = [self descriptionForKey:buildSettingName];
29+
30+
if (presentationName || settingDescription) {
31+
32+
if (settingDescription) {
33+
settingDescription = [self processedDescriptionString:settingDescription forKey:buildSettingName];
34+
}
35+
36+
[comment appendString:@"\n\n\n"];
37+
if (presentationName) {
38+
[comment appendFormat:@"// %@\n", presentationName];
39+
}
40+
if (settingDescription) {
41+
[comment appendFormat:@"// %@\n", settingDescription];
42+
}
43+
[comment appendString:@"\n"];
44+
} else {
45+
// For now, leave some space above an entry without a name or description
46+
[comment appendString:@"\n\n\n"];
47+
}
48+
49+
return comment;
50+
}
51+
52+
- (NSString *)presentationNameForKey:(NSString *)key {
53+
if (!self.buildSettingInfoDictionary) {
54+
[self loadBuildSettingInfo];
55+
}
56+
57+
NSString *processedKey = [key tps_baseBuildSettingName]; // strip any conditional part of build setting
58+
59+
processedKey = [NSString stringWithFormat:@"[%@]-name", processedKey];
60+
return self.buildSettingInfoDictionary[processedKey];
61+
}
62+
63+
- (NSString *)descriptionForKey:(NSString *)key {
64+
if (!self.buildSettingInfoDictionary) {
65+
[self loadBuildSettingInfo];
66+
}
67+
68+
NSString *processedKey = [key tps_baseBuildSettingName]; // strip any conditional part of build setting
69+
70+
processedKey = [NSString stringWithFormat:@"[%@]-description", processedKey];
71+
return self.buildSettingInfoDictionary[processedKey];
72+
}
73+
74+
- (NSString *)processedDescriptionString:(NSString *)string forKey:(NSString *)key {
75+
76+
NSString *processedString = @"";
77+
78+
// Take the repetition of the build setting name out of the description.
79+
NSString *baseBuildSettingName = [key tps_baseBuildSettingName];
80+
NSString *buildNameString = [NSString stringWithFormat:@"[%@]", baseBuildSettingName];
81+
string = [string stringByReplacingOccurrencesOfString:buildNameString withString:@""];
82+
83+
buildNameString = [NSString stringWithFormat:@"[%@, ", baseBuildSettingName];
84+
string = [string stringByReplacingOccurrencesOfString:buildNameString withString:@"["];
85+
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
86+
87+
for (NSString *paragraphString in [string componentsSeparatedByString:@"\n"]) {
88+
89+
90+
// Yes, this is not using grapheme clusters and assumes one char is one character.
91+
// It also assumes spaces separate words, which is not true in some languages.
92+
NSInteger characterCount = 0;
93+
NSString *currentLine = @"";
94+
95+
for (NSString *wordish in [paragraphString componentsSeparatedByString:@" "]) {
96+
characterCount += wordish.length;
97+
if (characterCount < MAX_LINE_LENGTH) {
98+
currentLine = [currentLine stringByAppendingFormat:@"%@ ", wordish];
99+
characterCount++; // Account for the space
100+
} else {
101+
// Trim whitespace
102+
currentLine = [currentLine stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
103+
// Add newline and comment prefix
104+
currentLine = [NSString stringWithFormat:@"\n// %@", currentLine];
105+
// Add to processed string
106+
processedString = [processedString stringByAppendingString:currentLine];
107+
// reset line count and set current line to token that didn't fit.
108+
characterCount = wordish.length + 1;
109+
currentLine = [NSString stringWithFormat:@"%@ ", wordish];
110+
}
111+
112+
113+
}
114+
115+
// Append the last line if there is any
116+
if (![currentLine isEqualToString:@""]) {
117+
// Trim whitespace
118+
currentLine = [currentLine stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
119+
// Add newline and comment prefix
120+
currentLine = [NSString stringWithFormat:@"\n// %@", currentLine];
121+
// Add to processed string
122+
processedString = [processedString stringByAppendingString:currentLine];
123+
}
124+
125+
}
126+
127+
return processedString;
128+
}
129+
130+
131+
- (void)loadBuildSettingInfo {
132+
NSString *defaultXcodePath = @"/Applications/Xcode.app";
133+
NSURL *buildSettingInfoPlistURL = [[NSBundle mainBundle] URLForResource:@"BuildSettingInfoSubpaths" withExtension:@"plist"];
134+
NSDictionary *buildSettingInfoDict = [NSDictionary dictionaryWithContentsOfURL:buildSettingInfoPlistURL];
135+
NSArray *buildSettingInfoSubpaths = buildSettingInfoDict[@"subpaths"];
136+
137+
NSMutableDictionary *infoStringFile = [NSMutableDictionary new];
138+
139+
// A spot to put additional setting info. If a more official version is read in, it replaces the backstop info.
140+
NSDictionary *backstopSettingsInfo = buildSettingInfoDict[@"backstopSettingInfo"];
141+
[infoStringFile addEntriesFromDictionary:backstopSettingsInfo];
142+
143+
for (NSString *subpath in buildSettingInfoSubpaths) {
144+
NSString *fullpath = [defaultXcodePath stringByAppendingPathComponent:subpath];
145+
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:fullpath];
146+
if (!dictionary) NSLog(@"Could not read dictionary at path: %@", fullpath);
147+
[infoStringFile addEntriesFromDictionary:dictionary];
148+
}
149+
150+
_buildSettingInfoDictionary = infoStringFile;
151+
}
152+
153+
154+
@end

0 commit comments

Comments
 (0)