From bf6ce642096e977ecfba266f56026bab4efe5908 Mon Sep 17 00:00:00 2001 From: Aparajita Fishman Date: Thu, 25 Apr 2013 13:11:22 -0400 Subject: [PATCH] New: XcodeCapp 3 tweaks... - Renamed XcodeSupport to .XcodeSupport. - Added "Reset Project" to menu, it closes the project in Xcode if necessary, removes .XcodeSupport and .xcodeproj, then reloads. - Added separate preferences for showing errors panel on warnings/errors. You may not want to see the panel if there are category warnings. - New status icons (again). - If an error occurs, the status icon turns red when all processing is done. - Reworked notifications. Objective-J parsing is notified when done. Xib conversion notifies at beginning and end, because it typically takes a few seconds. Individual file notifications are suppressed if a project is being loaded. --- .../XcodeCapp.xcodeproj/project.pbxproj | 60 ++- Tools/XcodeCapp/XcodeCapp/AppController.h | 1 - Tools/XcodeCapp/XcodeCapp/AppController.m | 41 +- .../Resources/XcodeCapp-status-icons.psd | Bin 124420 -> 136311 bytes .../XcodeCapp/Resources/icon-active.png | Bin 612 -> 635 bytes .../XcodeCapp/Resources/icon-active@2x.png | Bin 1209 -> 1311 bytes .../XcodeCapp/Resources/icon-error.png | Bin 0 -> 714 bytes .../XcodeCapp/Resources/icon-error@2x.png | Bin 0 -> 1496 bytes .../XcodeCapp/Resources/icon-inactive.png | Bin 618 -> 635 bytes .../XcodeCapp/Resources/icon-inactive@2x.png | Bin 1192 -> 1320 bytes .../XcodeCapp/Resources/icon-working.png | Bin 618 -> 759 bytes .../XcodeCapp/Resources/icon-working@2x.png | Bin 1213 -> 1516 bytes Tools/XcodeCapp/XcodeCapp/Scripts/parser.j | 14 +- .../XcodeCapp/Scripts/pbxprojModifier.py | 2 +- Tools/XcodeCapp/XcodeCapp/TNXCodeCapp.h | 4 + Tools/XcodeCapp/XcodeCapp/TNXcodeCapp.m | 170 +++++--- Tools/XcodeCapp/XcodeCapp/UserDefaults.h | 3 +- Tools/XcodeCapp/XcodeCapp/UserDefaults.m | 3 +- .../XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib | 368 +++++++++--------- 19 files changed, 388 insertions(+), 278 deletions(-) create mode 100644 Tools/XcodeCapp/XcodeCapp/Resources/icon-error.png create mode 100644 Tools/XcodeCapp/XcodeCapp/Resources/icon-error@2x.png diff --git a/Tools/XcodeCapp/XcodeCapp.xcodeproj/project.pbxproj b/Tools/XcodeCapp/XcodeCapp.xcodeproj/project.pbxproj index e3f7d7cca..420f6d056 100644 --- a/Tools/XcodeCapp/XcodeCapp.xcodeproj/project.pbxproj +++ b/Tools/XcodeCapp/XcodeCapp.xcodeproj/project.pbxproj @@ -7,9 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - E1310C96172863BE002E0A59 /* icon-active@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E1310C93172863BE002E0A59 /* icon-active@2x.png */; }; - E1310C97172863BE002E0A59 /* icon-inactive@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E1310C94172863BE002E0A59 /* icon-inactive@2x.png */; }; - E1310C98172863BE002E0A59 /* icon-working@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E1310C95172863BE002E0A59 /* icon-working@2x.png */; }; + E10E4CD717298E5F004AB09E /* project.pbxproj in Resources */ = {isa = PBXBuildFile; fileRef = E164FE2A172188F300263CE3 /* project.pbxproj */; }; E132ED951724B64C00D870AE /* FSEventCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = E132ED941724B64C00D870AE /* FSEventCallback.m */; }; E164FDD31720E77100263CE3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E164FDD21720E77100263CE3 /* Cocoa.framework */; }; E164FDDF1720E77100263CE3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E164FDDE1720E77100263CE3 /* main.m */; }; @@ -20,16 +18,21 @@ E164FE001720EC5B00263CE3 /* UserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = E164FDFD1720EC5B00263CE3 /* UserDefaults.m */; }; E164FE061720ED4500263CE3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E164FE041720ED4400263CE3 /* InfoPlist.strings */; }; E164FE0D1720F26C00263CE3 /* help.rtfd in Resources */ = {isa = PBXBuildFile; fileRef = E164FE081720F26C00263CE3 /* help.rtfd */; }; - E164FE151720F40400263CE3 /* mod_pbxproj.py in Resources */ = {isa = PBXBuildFile; fileRef = E164FE131720F40400263CE3 /* mod_pbxproj.py */; }; - E164FE161720F40400263CE3 /* pbxprojModifier.py in Resources */ = {isa = PBXBuildFile; fileRef = E164FE141720F40400263CE3 /* pbxprojModifier.py */; }; E164FE181720F44B00263CE3 /* parser.j in Resources */ = {isa = PBXBuildFile; fileRef = E164FE171720F44B00263CE3 /* parser.j */; }; E164FE1A1720F49A00263CE3 /* Growl Registration Ticket.growlRegDict in Resources */ = {isa = PBXBuildFile; fileRef = E164FE191720F49A00263CE3 /* Growl Registration Ticket.growlRegDict */; }; E164FE1F1720F51E00263CE3 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E164FE1D1720F50100263CE3 /* CoreServices.framework */; }; E164FE211720F55600263CE3 /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E164FDF61720EBD600263CE3 /* Growl.framework */; }; - E164FE2B172188F300263CE3 /* project.pbxproj in Resources */ = {isa = PBXBuildFile; fileRef = E164FE2A172188F300263CE3 /* project.pbxproj */; }; E164FE2F1721A34900263CE3 /* icon-active.png in Resources */ = {isa = PBXBuildFile; fileRef = E164FE2C1721A34900263CE3 /* icon-active.png */; }; E164FE301721A34900263CE3 /* icon-inactive.png in Resources */ = {isa = PBXBuildFile; fileRef = E164FE2D1721A34900263CE3 /* icon-inactive.png */; }; E164FE311721A34900263CE3 /* icon-working.png in Resources */ = {isa = PBXBuildFile; fileRef = E164FE2E1721A34900263CE3 /* icon-working.png */; }; + E170C3FB17296205003DC489 /* pbxprojModifier.py in CopyFiles */ = {isa = PBXBuildFile; fileRef = E164FE141720F40400263CE3 /* pbxprojModifier.py */; }; + E170C3FC1729620C003DC489 /* mod_pbxproj.py in CopyFiles */ = {isa = PBXBuildFile; fileRef = E164FE131720F40400263CE3 /* mod_pbxproj.py */; }; + E170C3FD1729620F003DC489 /* parser.j in CopyFiles */ = {isa = PBXBuildFile; fileRef = E164FE171720F44B00263CE3 /* parser.j */; }; + E170C40317298833003DC489 /* icon-active@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E170C3FE17298833003DC489 /* icon-active@2x.png */; }; + E170C40417298833003DC489 /* icon-error.png in Resources */ = {isa = PBXBuildFile; fileRef = E170C3FF17298833003DC489 /* icon-error.png */; }; + E170C40517298833003DC489 /* icon-error@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E170C40017298833003DC489 /* icon-error@2x.png */; }; + E170C40617298833003DC489 /* icon-inactive@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E170C40117298833003DC489 /* icon-inactive@2x.png */; }; + E170C40717298833003DC489 /* icon-working@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E170C40217298833003DC489 /* icon-working@2x.png */; }; E17A822D172700B90095CD83 /* XcodeCapp.iconset in Resources */ = {isa = PBXBuildFile; fileRef = E17A822C172700B90095CD83 /* XcodeCapp.iconset */; }; /* End PBXBuildFile section */ @@ -44,12 +47,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + E170C3F9172961E6003DC489 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 12; + files = ( + E170C3FB17296205003DC489 /* pbxprojModifier.py in CopyFiles */, + E170C3FC1729620C003DC489 /* mod_pbxproj.py in CopyFiles */, + E170C3FD1729620F003DC489 /* parser.j in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - E1310C93172863BE002E0A59 /* icon-active@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-active@2x.png"; path = "Resources/icon-active@2x.png"; sourceTree = ""; }; - E1310C94172863BE002E0A59 /* icon-inactive@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-inactive@2x.png"; path = "Resources/icon-inactive@2x.png"; sourceTree = ""; }; - E1310C95172863BE002E0A59 /* icon-working@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-working@2x.png"; path = "Resources/icon-working@2x.png"; sourceTree = ""; }; E132ED941724B64C00D870AE /* FSEventCallback.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FSEventCallback.m; sourceTree = ""; }; E132ED961724B6C400D870AE /* FSEventCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSEventCallback.h; sourceTree = ""; }; E132ED991724B71600D870AE /* TNXCodeCapp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TNXCodeCapp.h; sourceTree = ""; }; @@ -80,6 +92,11 @@ E164FE2C1721A34900263CE3 /* icon-active.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-active.png"; path = "Resources/icon-active.png"; sourceTree = ""; }; E164FE2D1721A34900263CE3 /* icon-inactive.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-inactive.png"; path = "Resources/icon-inactive.png"; sourceTree = ""; }; E164FE2E1721A34900263CE3 /* icon-working.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-working.png"; path = "Resources/icon-working.png"; sourceTree = ""; }; + E170C3FE17298833003DC489 /* icon-active@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-active@2x.png"; path = "Resources/icon-active@2x.png"; sourceTree = ""; }; + E170C3FF17298833003DC489 /* icon-error.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-error.png"; path = "Resources/icon-error.png"; sourceTree = ""; }; + E170C40017298833003DC489 /* icon-error@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-error@2x.png"; path = "Resources/icon-error@2x.png"; sourceTree = ""; }; + E170C40117298833003DC489 /* icon-inactive@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-inactive@2x.png"; path = "Resources/icon-inactive@2x.png"; sourceTree = ""; }; + E170C40217298833003DC489 /* icon-working@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "icon-working@2x.png"; path = "Resources/icon-working@2x.png"; sourceTree = ""; }; E17A822C172700B90095CD83 /* XcodeCapp.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = XcodeCapp.iconset; path = Resources/XcodeCapp.iconset; sourceTree = ""; }; E1DD4DF517282BFC0063C0D7 /* UserDefaults.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserDefaults.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -170,12 +187,14 @@ E164FE071720F25400263CE3 /* Resources */ = { isa = PBXGroup; children = ( - E164FE2C1721A34900263CE3 /* icon-active.png */, E164FE2D1721A34900263CE3 /* icon-inactive.png */, + E170C40117298833003DC489 /* icon-inactive@2x.png */, E164FE2E1721A34900263CE3 /* icon-working.png */, - E1310C93172863BE002E0A59 /* icon-active@2x.png */, - E1310C94172863BE002E0A59 /* icon-inactive@2x.png */, - E1310C95172863BE002E0A59 /* icon-working@2x.png */, + E170C40217298833003DC489 /* icon-working@2x.png */, + E164FE2C1721A34900263CE3 /* icon-active.png */, + E170C3FE17298833003DC489 /* icon-active@2x.png */, + E170C3FF17298833003DC489 /* icon-error.png */, + E170C40017298833003DC489 /* icon-error@2x.png */, E17A822C172700B90095CD83 /* XcodeCapp.iconset */, E164FDE71720E77100263CE3 /* MainMenu.xib */, E164FE2A172188F300263CE3 /* project.pbxproj */, @@ -188,9 +207,9 @@ E164FE121720F3E100263CE3 /* Scripts */ = { isa = PBXGroup; children = ( + E164FE171720F44B00263CE3 /* parser.j */, E164FE141720F40400263CE3 /* pbxprojModifier.py */, E164FE131720F40400263CE3 /* mod_pbxproj.py */, - E164FE171720F44B00263CE3 /* parser.j */, ); path = Scripts; sourceTree = ""; @@ -206,6 +225,7 @@ E164FDCC1720E77100263CE3 /* Frameworks */, E164FDCD1720E77100263CE3 /* Resources */, E164FE201720F54800263CE3 /* CopyFiles */, + E170C3F9172961E6003DC489 /* CopyFiles */, ); buildRules = ( ); @@ -250,18 +270,18 @@ E164FDE91720E77100263CE3 /* MainMenu.xib in Resources */, E164FE061720ED4500263CE3 /* InfoPlist.strings in Resources */, E164FE0D1720F26C00263CE3 /* help.rtfd in Resources */, - E164FE151720F40400263CE3 /* mod_pbxproj.py in Resources */, - E164FE161720F40400263CE3 /* pbxprojModifier.py in Resources */, + E10E4CD717298E5F004AB09E /* project.pbxproj in Resources */, E164FE181720F44B00263CE3 /* parser.j in Resources */, E164FE1A1720F49A00263CE3 /* Growl Registration Ticket.growlRegDict in Resources */, - E164FE2B172188F300263CE3 /* project.pbxproj in Resources */, E164FE2F1721A34900263CE3 /* icon-active.png in Resources */, E164FE301721A34900263CE3 /* icon-inactive.png in Resources */, E164FE311721A34900263CE3 /* icon-working.png in Resources */, E17A822D172700B90095CD83 /* XcodeCapp.iconset in Resources */, - E1310C96172863BE002E0A59 /* icon-active@2x.png in Resources */, - E1310C97172863BE002E0A59 /* icon-inactive@2x.png in Resources */, - E1310C98172863BE002E0A59 /* icon-working@2x.png in Resources */, + E170C40317298833003DC489 /* icon-active@2x.png in Resources */, + E170C40417298833003DC489 /* icon-error.png in Resources */, + E170C40517298833003DC489 /* icon-error@2x.png in Resources */, + E170C40617298833003DC489 /* icon-inactive@2x.png in Resources */, + E170C40717298833003DC489 /* icon-working@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tools/XcodeCapp/XcodeCapp/AppController.h b/Tools/XcodeCapp/XcodeCapp/AppController.h index 82d49e362..d994293a2 100644 --- a/Tools/XcodeCapp/XcodeCapp/AppController.h +++ b/Tools/XcodeCapp/XcodeCapp/AppController.h @@ -40,7 +40,6 @@ + (AppController *)sharedAppController; - (IBAction)listenToProject:(id)aSender; -- (IBAction)openInXcode:(id)aSender; - (IBAction)openHelp:(id)aSender; - (IBAction)openAbout:(id)aSender; diff --git a/Tools/XcodeCapp/XcodeCapp/AppController.m b/Tools/XcodeCapp/XcodeCapp/AppController.m index 044079217..f8530d750 100644 --- a/Tools/XcodeCapp/XcodeCapp/AppController.m +++ b/Tools/XcodeCapp/XcodeCapp/AppController.m @@ -37,6 +37,7 @@ AppController *SharedAppControllerInstance = nil; @property (nonatomic) NSImage *iconActive; @property (nonatomic) NSImage *iconInactive; @property (nonatomic) NSImage *iconWorking; +@property (nonatomic) NSImage *iconError; @property (nonatomic) NSMenu *menuHistory; @property NSStatusItem *statusItem; @@ -104,15 +105,16 @@ AppController *SharedAppControllerInstance = nil; - (void)registerDefaults { NSDictionary *appDefaults = @{ - kDefaultLastEventId: [NSNumber numberWithUnsignedLongLong:kFSEventStreamEventIdSinceNow], - kDefaultFirstLaunch: @YES, - kDefaultFirstLaunchVersion: @2.0, - kDefaultXCCAPIMode: [NSNumber numberWithInt:kXCCAPIModeAuto], - kDefaultXCCReactMode: @YES, - kDefaultXCCReopenLastProject: @YES, - kDefaultXCCAutoOpenErrorsPanel: @YES, - kDefaultXCCProjectHistory: [NSArray new], - kDefaultMaxRecentProjects: @20 + kDefaultLastEventId: [NSNumber numberWithUnsignedLongLong:kFSEventStreamEventIdSinceNow], + kDefaultFirstLaunch: @YES, + kDefaultFirstLaunchVersion: @2.0, + kDefaultXCCAPIMode: [NSNumber numberWithInt:kXCCAPIModeAuto], + kDefaultXCCReactMode: @YES, + kDefaultXCCReopenLastProject: @YES, + kDefaultXCCAutoOpenErrorsPanelOnWarnings: @YES, + kDefaultXCCAutoOpenErrorsPanelOnErrors: @YES, + kDefaultXCCProjectHistory: [NSArray new], + kDefaultMaxRecentProjects: @20 }; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; @@ -171,6 +173,14 @@ AppController *SharedAppControllerInstance = nil; return _iconWorking; } +- (NSImage *)iconError +{ + if (!_iconError) + _iconError = [NSImage imageNamed:@"icon-error"]; + + return _iconError; +} + - (NSMenu *)menuHistory { if (!_menuHistory) @@ -205,7 +215,7 @@ AppController *SharedAppControllerInstance = nil; - (void)XcodeCappConversionDidStop:(NSNotification *)aNotification { if (!self.xcc.isLoadingProject) - self.statusItem.image = self.iconActive; + self.statusItem.image = self.xcc.hasErrors ? self.iconError : self.iconActive; } - (void)XcodeCappDidPopulateProject:(NSNotification *)aNotification @@ -214,7 +224,7 @@ AppController *SharedAppControllerInstance = nil; - (void)XcodeCappListeningDidStart:(NSNotification *)aNotification { - self.statusItem.image = self.iconActive; + self.statusItem.image = self.xcc.hasErrors ? self.iconError : self.iconActive; self.menuItemListen.title = [NSString stringWithFormat:@"Close “%@”", self.xcc.currentProjectPath.lastPathComponent]; self.menuItemListen.action = @selector(stopListening:); } @@ -308,15 +318,6 @@ AppController *SharedAppControllerInstance = nil; [self updateHistoryMenu]; } -- (IBAction)openInXcode:(id)aSender -{ - if (!self.xcc.currentProjectPath) - return; - - DLog(@"Opening Xcode project at: %@", self.xcc.XcodeSupportProjectURL.path); - system([[NSString stringWithFormat:@"open \"%@\"", self.xcc.XcodeSupportProjectURL.path] UTF8String]); -} - - (IBAction)openHelp:(id)aSender { [self.helpTextView readRTFDFromFile:[[NSBundle mainBundle] pathForResource:@"help" ofType:@"rtfd"]]; diff --git a/Tools/XcodeCapp/XcodeCapp/Resources/XcodeCapp-status-icons.psd b/Tools/XcodeCapp/XcodeCapp/Resources/XcodeCapp-status-icons.psd index 4233fb174f9756420a0e54531ff239a1245a0e86..cfac2801323878e171cb93915c49d19aafdb8179 100644 GIT binary patch literal 136311 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 O2g^b+rstUm^Zx;T037T9 literal 124420 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 XYsWO|REwr_00000NkvXXu0mjfC5!!~ diff --git a/Tools/XcodeCapp/XcodeCapp/Resources/icon-active@2x.png b/Tools/XcodeCapp/XcodeCapp/Resources/icon-active@2x.png index d3e535249ca607c636f1e2a4dc2f009f40d1c862..dd2bf9b4987c7629d38b5efe5c70ebc50c8e469e 100644 GIT binary patch delta 1289 zcmV+k1@`*637-lfiBL{Q4GJ0x0000DNk~Le0000W0000Y2nGNE06wzY|B)dmf5Aya zK~#9!#8_KMV^uh@QnwwF6$jQkGfBK?Mr(^dv`T~HxS@r!sJoz`U1FYlkzqESR=ttmB zny%OD?*NSkgTaRWO+XNQU;c(8;6Zi>u225ej6>wp)(%jr!Wefx#7>&kW z;6p$k5fLHK3pKecTD?-W2;%JQOq`#edw}nNN0@sNP(WT@9*y4u(Kk_1e^J)R$Vd^0 zI8?h%$jQlxI6Xam2_e0h`$guJ1mx%E>p;{O9Uc7zpeMOZ9EdbKJ6n{NmP*fSYinYA zdpoEY5L19SK0fvUefaw;%w0$^0K&(yv9b37Y1P4qIo{dXDeCL%FU7$0^t2cp92EY+ z$9HHCF(larmjR1=czAf2e+JJyFpQ0jeQYwBzK)BF<77xzH#9VemX;Q2RcbJX+-|qn z+}sQ(Toyv_qSat~?1tjv;_spC4K+DYS63&Ro0}z34u?Y-@9OFj^pw8@ZPLmyOS$B80 z(=a?dyt}`@e~-bVc2giYolb$HD$>)_mA&U#pP!$X_FoRTU|{1Z!fAS-^PSU2BO@c9 zj*gB>2DP-bv@|7qe{OAUN$%I$T3cI1TU*<=$RnS~nUJzRx7+Ps4h#$!Ha0diXFaWr zJOu>>qNk_FYq41R%F4$^_rdim(=%-=0tyQYm29=Vy!<|fdJhf`numsl470Pde_?xsc5ODBXm4-#B0o%V zVZaZ_I~RWs}$!b4WYR;$&M zn3#B~CBv!X2<|_}C3GC>7+(oOf6zdDeEdJ*3V;U=wFIxGvxS1?PZ&!HCl2t9rqbN# zSFvOPckvvfynyqMdM{GFIxTHyX9u4eKVz+-3hE=Ae~PDo<4RSGG-->8iJ8I&CPuy7 zm>n@LLF<*xGmpYk3S1^2b#g*pabx@r#(yNYQFXgLfnpO%a-kL=S1{omMOid$skgzG zoJ=5pvb($cE`=%ra0gge>xG+g0~Mfh-FIcrVILK-#aEL3cMAB!gp=W>+;Bk-U8O$#7LM@NU9+aZmq_UJvA%k^w&X~~2V?M8lzBcX|^sw%hHY`%?tfdQ%r zK+YG7i;G!!ybHW_L;nu=19%E92g%9(uK)u88^@&bDUt#-00000NkvXXu0mjfok?CP delta 1186 zcmV;T1YP@|3b_d(iBL{Q4GJ0x0000DNk~Le0000e0000e2nGNE0F3^)ZIK};e_KgJ zK~#9!>{wq&TUQuANpGUYXcyzOrOG-wvUOTbG41wXJB2-zjm;P9pL8g$U>`R6;uz>2 zR)iugSR7mFNGXC8Q5W_QUq)eO?qL~B9ky$sf0#C{OLe9un))X>y3)sh7T`S~PhyIZM+tBUXyC`gz!-29 zZ~_}rzBN*5rm3mv12pG={b}C4zksuVV`yk7qL^S~W1|_(H+9vv`@#VPOcp+ z$m>{`Q<8a*VVF~Rmd3~%1_#;~>K1k_60$@RVqy29Y&#V2ZIR4_TW=#2uh&a*bDzf3>gsB|{xP86 zCa}V>xM!2vk(;Pt;9)Qr+$S6x9UUcBtCf4p>FMb>!-Y4@^tnU3{+9u?(jZl1OHU_dO;VgZQj{tJmuv z%RPODWdnKp+F??Br-(3qh6C->F{+bmhx(+x`0don@J zXf)2XwY7Z>g0#AsOQo7I`ThQPdV711PfkvL7>PuTX(>V(CR9~bwqlT9OJeq>+a= zw^Av$UIkv`VN&J3xWd!`@WrTcIM-IOB~06{|RyL;o9l`UYXL%jM5AhgcFpI zn2U4A+2FSQ#o&CV#`)CP$N7a_4sj>A-apW*GWIAU%R^CFhLFS{Ac`Ogf>&hOHf&oK zY?%gBYBl&>tG&|@`@Pn1J<9 zp8+R;s%gT;b`{pPwv3XdT@pK^v8TyMSWW~Lk0=o0kveiY;4*7GYhS+su7}e}5UEee zm?({jM-p+R6-Rc-WRD)Yt^=j@6?j!|;O+<9^;#7LEGC77o^1975d@1gsau|&hRsq5 zHj70lznu1|FHmZETom#6>TG^=WpeVO^=m!3yTUULkTV+ z`7R!xxnysZrn;ZHt!sS&LjV8(07*qoM6N<$f>|O)NB{r; literal 0 HcmV?d00001 diff --git a/Tools/XcodeCapp/XcodeCapp/Resources/icon-error@2x.png b/Tools/XcodeCapp/XcodeCapp/Resources/icon-error@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..abdd05568fc5b14894d46fca0bb156496a01ba72 GIT binary patch literal 1496 zcmV;}1t;~ybuUcc@dMU4)0mk!wp5uJk?~%pZx?#jL!x+(Y{XB9SosZcgg9Fw8yc%q*urbyqG4_Qn;=YhjNa-$nMXu1I@O@pMCp=TKFOj6U1+qpEr?o=WY(E`2!+;M{T;?Yq7b`#Tj5JMWPdz;~pYnUT&_l&VT_1_I{q ziQ!>TN3PA;k0Pe2LC5g7s=|%QcxG&J>OExTgG2p&hRJ|OmiJdVUAu9PF=}~U$H+TW zwQm9MhV|xeDi!D?^79!O>G+CPWbQV@KC&Q~V^UD1k|dPa#P>%gVhgc(FPr%Ow%9T90IdkC>7&}fY&gI%;2M%0d z&n#Vbw8rgO=vHK4-2Z7Iy|NyX=nU`!cH`!M_2paJ0g$Dc0LTQ78^(Li%{vA$A_@#d zp3#m8@C)qrWiCm|ac*{8wGt$|9r*ecxpRtjDV)!_jM}V>LB5>m6MZk|OWmF^#?Pi) zyf6$3QYBst<UG2}`Q0 z`|Z&;-{_z`umWvs|Nc*!V}1QCnCmSaQ2YWfFkJcOfZ;Icw<6Y@<34o-gFiOzeZ3oB zzs{!OHng=@&-PUQdF;zJEgJP(VWXHr35j_;;hOE+j{DcG9mT3%v~RNj$Xhd73k7$% zv$Oj8>F%afcw`v|a92olOif}%MX3Do=3i>tp1g$lfE;$AbQa#mKx#U-^NI%110 zw90L@i$myq9AAggj-nlY@sWm6D}vb@=tRmQo29VJ8LHxPzrG{WEpB^Z* z;wPCb^<{9I6ZstBTi()g3B^v)2xza@G_AR)7ZAM#0XWLaqMRbf zi_y+zUz<2p83>HsH2~TSysV6q?z0R4o$`u8D}Vf60MJ2^Bf4%BK|cYIqi;R7zToz; zmUdZ9|md51|a-f=Nfo);Uo|)z<}l5)^lXnuHS`F3b!n z=SL7111yFCXf01`MeMGmn*qBN=N^|KbC$Lk%X%g4Pvgl8yYN)PCx z41LW4uwwhRQyRyo?&oFQyfvYZRWIy3G1uL2S0r?4X}GIvc_tQf-j}Pm%QfL|Z5{G1 ysr>_A56%Rz2yF)~{QLYbfz+MjeuQ5B5nuq)`Gquy&n}?=0000Pp?l={DBCw9kh*ti?@of5M5Y{U`WCL!1WMBn|4LJAZVGJXc;_d zF`HZ%NsP9fjjl#YgBk`E5q~{@^_^Qc9*-%44t(G}_kQ2~&OPU;?e}~7pAhy%u~;AFr3A&AIB zAQOmWSr#pqOIoc~AAn=iG|#khxqK%W489En0$#u0PeKSuj>qFvC={eXyoqMF3!2Sl)^s{O5|K!x3P>^&VOx^2*{ocv--E$`JRT3hC9z9D$NHs+f5l>cPVmk4 zn9t{=9++*bayVF+0Zzb`&*$G@vEc)DwA*bOjYc#a4yn~@k#nCp%;iVC*6DPPo6Y83 z)O4sy_*1Yeyjee!$(*Fq>F3%nn+L${Znt~A(P)%l`M@c}=TPcpE|)V?snjQ=-T~iK zVHd#bWHR{#k95unr)3sIe|yhCevIu`OqS;y4!@)4U#=2h2iO}Z;+2yq6GHU)Hq}BE zo6UyzzW#NTIZ(o9<-i#zq3_JeN32vTPqFy`gQ17RVTwkha#-wv(UmQoOeQ>ym}=`; zwOV~79blLqhC(61lg8k0!Py1Qu`pW50ytD6#>MqKx_cSLO{$2#BYK4G7#?p;+4ymEqj8l zml4^^5fKsWK&lal^MII>fMb3E@k}7DSg~ToHw**A!oqlf)Gi>lB*lx2jEon6W;m=` zwdx~^mw|#^|Ni~MFicNRk0B{3e+kTZ>fhZ7zCBl)5NC$oe;$uMk d1||RyU;r?Z9zT@=%3%Ni002ovPDHLkV1hwn{CWTY diff --git a/Tools/XcodeCapp/XcodeCapp/Resources/icon-inactive@2x.png b/Tools/XcodeCapp/XcodeCapp/Resources/icon-inactive@2x.png index c58a2be73842da00f035a3315fca87d4edb979b1..dc626fa20793343e765f53f59893b7ce259e1081 100644 GIT binary patch delta 1298 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 z j<{#+kTl)$4jQ|4xrX$E2G8hIq00000NkvXXu0mjf8MtedCAHKi74vGXK zph+>Jceoipu9|UBj0i9_Bnbm@1SCDjO1jy#Q%+{(s-0PR>t^ zX_dxH%7O7PP*sP+`ziFaIsw7GcPfm}_~1J^@azq+e=b2TJ#A;xbDc`Kf2``Uk!aMk zT}cEQK`C-wYF+_@`oHZwe4dYERz{GW8Y-1{u5$iJi6tsSBC;2lqDvtP;#igis_zAM zHqY=HFKETM2^wN_Vwv=OTjDt-;BE!WH8dWB#dIF#Q#L&P6f07nQsPQ1!8X>6PHyx* z8DnP_Gg{@J68^TN`sJbAf9%B;|JBJu;XxGfHhg{2m%y{rqu;Ve?vB8@Ra;AJCz8Mj zx0id`#Bh6q@ey5ba4%3dw+?k@Z!I-;KYVtg-nbE==_%p6#cxJmgr=qt+>fzCb)5qX zK`D|MhXd^OC1~t^ut=S?8R6Q+1Rl23UYo<11sUtv)}|I)Ql#x P00000NkvXXu0mjfG>A~c delta 591 zcmV-V0tD6#>MqKx_cSLO{$2#BYK4G7#?p;+4ymEqj8l zml4^^5fKsWK&lal^MII>fMb3E@k}7DSg~ToHw**A!oqlf)Gi>lB*lx2jEon6W;m=` zwdx~^mw|#^|Ni~MFw97khaoFce-g}|w){E6x$9rhl^8HFG4%uKB$P<``}c1Q5Hq0T z7*8e!roXSj7{tb=28ctjMaqAWBszHg@;<}Q&yZmG{EZQ)nHMvuFfskdNH*f);-|6M zzHrMQhI{uOFx0S}5W9cW)YSIY*49p!kdW906#9*k4uOCf6l-VCo;7Q0 zYb*Zn;e#?X1;7jeV}5@AdsS6cJ;uhyr+~s2KyivIr+_5R0u^4Dl9ICe{Q0voFu*~9 z4mJp6FfeH`NJ>hc1gcpGe^mR8sH_K7cnf3z%n+D?P}knYW*9yL88|pN9wHltlmQsn z*w`N73|r(d1QrTbKx!Ef%M%&N4?#r$u#h-`)rG%){aOlikvs{hMjjZxAO|SnGLYlP zj~^tJf54#Oz*)fh`T0!%ru;WwzkX#P1_OQbCNMCtA7>Z>fhZ7zCBl)5NC$oe;$uMk d1||RyU;xGtIVax%+o}Kn002ovPDHLkV1g^y|HS|R diff --git a/Tools/XcodeCapp/XcodeCapp/Resources/icon-working@2x.png b/Tools/XcodeCapp/XcodeCapp/Resources/icon-working@2x.png index a225eeb40e9316b82c31bfae379e7e5c4e241974..9741e09640d9fc95def5de8e5b265bcb9b967b20 100644 GIT binary patch delta 1497 zcmV;~1t$8v3G53YiBL{Q4GJ0x0000DNk~Le0000W0000Y2nGNE06wzY|B)dle+7<7 zL_t(|+Qe9EY*S?ze$TzJ2_am!-Jpff8^Ybt=H!a!{8U!$Z~v?VfjX2*g9OZ?BbJpS zmT?*7G!QF6J=@>2wK@PSCp56U)WHh!Do&8w@wc86Wn7mKi-4e5Aou~x1j{nO(#KI$ zFpcp+oF9v=d%xS%$9vB2+Y+y&gSj~e=5@Zsu!3tjFL^ifvVXOp1Xw|-e+6Fl0fIoq zA{x)xg11xqsSBtV&~OA{Xb2()#&`X;J|5*S_~4D*RCN zh8IgUGeC5QfOC0m#pnsNn4__n+@}Rpwb$}tT<6AanD948C8y`r3!W$(3sDu;)4h*;_-Gh3BdYBrD6%%D${zyzzf)& zBozVBb58cS)?-8n_)zyJJ(s`yx;O9)Ej1^jy=fHIMTg6t`?jwEj$8^l+J`o+HL8QC+whQaj-WR*>Q~N zh^ta#r9N=0gSP5AIY0RPQquiMi!y{uzoP7$06+`B9c3BKkG&_d%{{&B;tL5ehRvU; zO0#8>CcoCdf3n5;W&I-e0L$3D>LAMDau1^jN+(JqJ^1@yUFrH!Ti!e3y1!COt{i6* zqILPxFFnTZkIoQNh2=qNHOf#WLUIM=Gn6k-&fFCeGOcx)e)@==w&B?STY~9+RG!4c zK9pT3J8o1y86UV%5I19FH<pz;xI%UMq2CuBAB; zuL?k+Leh$8CJBO>PR+Xoi@H8pH7##__EXEv8>2KF&H@M%4glEM?yO$LX`; zTIB3|f8tKAEh@w4>bIMaD6Ge(V>fnzGGS4Hp@dck(sbUS2*gu*ux-Q6*9$o>d^4g{qf$vMIV9k=y@o1x(>^_xQFqUJz0ROiq2>2B%-FYv6 zFD5p#_H4O#!&xXBP{iB(mw;Ay++U^#{|PVvtfiH6A^-1c00000NkvXXu0mjf&63R? delta 1191 zcmV;Y1X%m*3%v;;iBL{Q4GJ0x0000DNk~Le0000e0000e2nGNE0F3^)ZIK}-e*|Ai zL_t(|+U!_uXj@enK1puUuOyn*r3_oQG0Ai*ZAOFssapg77{jdywI5Mh>YxLa{iz78 ze?~=$LZwAzBSQ*h^vkdx>3-~kEvrAQu(r|;gw<)cxEjmWwQ26sd^SGknv9!E%)K{F zvLU|kaLzp+@B7^Myyx8aTtzGve|F8#C=`lo z=riSGBf!>Qu=U2o#Kav@f{l%hj8dtb-rCx-NHwr?hlafO)(%o_D&d|N79W%I7atJM zgOD7Ox535ia5w^D$IScDXw*W9OTo?;81mT%MsjeUil`I;4zy0&XrEL)aL7J5=A`I3 z$S}-F3?_V3RaKFJfdLM*f6niF+p5Mg_{gT;n*`cM`=sij0KpTY=U^xlIv`y3hK2?b z3l*SnYBHaR&-%w{v^4f@u6#S4pmvi~K2e@f-QxQj7XD@hL( zoldtbO0crB(zUj>mPF9w@o-2bmv3rGxz0lh)zPH(Kv;!7V-ksUdg8XPi*6Ep+Rkb; znnzN1-@}apGIVt>x%Hcxc)ctKTBmKaPpTejliHSYP^*WBhd;qb{WSWRJRQ^#kUQPp z-u@*X!(!P?xUH@2e;muQ&pVyYQ&=KRPV+sbGK3vH2y*9yXUGC`U_!iIV9?cGp^p#({rM}zWxVP?*fsmr2Gk^P)rrx85|sZ z2%~mDl^`M{#3#&qfvCY?xDdYzWbaNgH8qv=TvJoyEi5ct4Fm$lbT1?nI)~29`K=Bf ziWL_ZdxWHff5e1s@j0=a6Qoj5P~c7#fBzPj6qxfzPOhD)q^PLqo^VO|v6sq=m~%I8 z1hHJdrz0jLPfHM7${RtwUVl5?hDb#)F-LaHr!!)++1^F*Az-Gfl;tnoBj6VBEfSOO zWfR2JvnPJB&WCj2%K4S7CC1I}V<{eYv@5$m36}QrVjX-ebezur?p; z)N1vHY=S0}$vHPSXUhk{>gsA|CcF4RZ*T8M)6>&$uCK4}f=AU^j=OMaY3Wj3UEP)L z?(Q@65|~N4wFh`P9wXWQ8yk%uHNOJ)wv(_vRry(.*)\s*$", re.MULTILINE) FRAMEWORKS_RE = re.compile(ur"^(.+/Frameworks/(?:Debug|Source)/([^/]+))/.+$") diff --git a/Tools/XcodeCapp/XcodeCapp/TNXCodeCapp.h b/Tools/XcodeCapp/XcodeCapp/TNXCodeCapp.h index 8b8814561..f111270fe 100644 --- a/Tools/XcodeCapp/XcodeCapp/TNXCodeCapp.h +++ b/Tools/XcodeCapp/XcodeCapp/TNXCodeCapp.h @@ -51,6 +51,9 @@ extern NSString * const XCCListeningDidStartNotification; - (IBAction)openErrorsPanel:(id)sender; - (IBAction)clearErrors:(id)sender; - (IBAction)openErrorInEditor:(id)sender; +- (IBAction)openInXcode:(id)aSender; +- (IBAction)resetProject:(id)aSender; + - (void)start; - (void)stop; - (void)listenToProjectAtPath:(NSString *)path; @@ -63,6 +66,7 @@ extern NSString * const XCCListeningDidStartNotification; - (void)handleFileModificationAtPath:(NSString*)path notify:(BOOL)shouldNotify; - (void)handleFileRemovalAtPath:(NSString*)path; - (void)updateUserDefaultsWithLastEventId; +- (BOOL)hasErrors; @end diff --git a/Tools/XcodeCapp/XcodeCapp/TNXcodeCapp.m b/Tools/XcodeCapp/XcodeCapp/TNXcodeCapp.m index f7a99d5e4..6646b0641 100644 --- a/Tools/XcodeCapp/XcodeCapp/TNXcodeCapp.m +++ b/Tools/XcodeCapp/XcodeCapp/TNXcodeCapp.m @@ -39,6 +39,27 @@ enum XCCLineSpecifier { }; typedef enum XCCLineSpecifier XCCLineSpecifier; +enum { + XCCStatusCodeError = 1, + XCCStatusCodeWarning = 2 +}; + +const char *XCCCloseProjectScript = + "tell application \"Xcode\"\n" + "set docs to (document of every window)\n" + "repeat with doc in docs\n" + "if class of doc is workspace document then\n" + "set docURL to file of doc\n" + "set docPath to docURL as text\n" + "set docPath to POSIX path of docPath\n" + "if docPath begins with \"%@\" then\n" + "close doc\n" + "return\n" + "end if\n" + "end if\n" + "end repeat\n" + "end tell"; + NSString * const XCCDidPopulateProjectNotification = @"XCCDidPopulateProjectNotification"; NSString * const XCCConversionDidStartNotification = @"XCCConversionDidStartNotification"; NSString * const XCCConversionDidStopNotification = @"XCCConversionDidStopNotification"; @@ -67,6 +88,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; @property NSString *profilePath; @property NSString *shellPath; @property NSString *PBXModifierScriptPath; +@property NSString *closeProjectScriptSource; @property NSString *supportPath; @property NSDate *appStartedTimestamp; @property NSMutableDictionary *pathModificationDates; @@ -115,7 +137,8 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; self.errorList = [NSMutableArray arrayWithCapacity:10]; self.fm = [NSFileManager defaultManager]; self.ignoredPathRegexes = [NSMutableArray new]; - self.parserPath = [[NSBundle mainBundle] pathForResource:@"parser" ofType:@"j"]; + self.parserPath = [[[NSBundle mainBundle] sharedSupportPath] stringByAppendingPathComponent:@"parser.j"]; + self.closeProjectScriptSource = [NSString stringWithUTF8String:XCCCloseProjectScript]; self.lastEventId = [[NSUserDefaults standardUserDefaults] objectForKey:kDefaultLastEventId]; self.appStartedTimestamp = [NSDate date]; self.projectPathsForSourcePaths = [NSMutableDictionary new]; @@ -192,24 +215,24 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; NSURL *projectURL = [NSURL fileURLWithPath:self.currentProjectPath]; self.XcodeSupportProjectURL = [NSURL URLWithString:self.XcodeSupportProjectName relativeToURL:projectURL]; - self.supportPath = [[NSURL URLWithString:@"XcodeSupport" relativeToURL:projectURL] path]; + self.supportPath = [[NSURL URLWithString:@".XcodeSupport" relativeToURL:projectURL] path]; self.XcodeSupportPBXPath = [self.XcodeSupportProjectURL.path stringByAppendingPathComponent:@"project.pbxproj"]; - self.PBXModifierScriptPath = [[NSBundle mainBundle] pathForResource:@"pbxprojModifier" ofType:@"py"]; + self.PBXModifierScriptPath = [[[NSBundle mainBundle] sharedSupportPath] stringByAppendingPathComponent:@"pbxprojModifier.py"]; // Create the template project if it doesn't exist if (![self.fm fileExistsAtPath:self.supportPath]) { - NSLog(@"%@ Xcode support folder created at: %@", NSStringFromSelector(_cmd), self.XcodeSupportProjectURL.path); + NSLog(@"Xcode support folder created at: %@", self.XcodeSupportProjectURL.path); [self.fm createDirectoryAtPath:self.XcodeSupportProjectURL.path withIntermediateDirectories:YES attributes:nil error:nil]; - DLog(@"%@ Copying project.pbxproj from %@ to %@", NSStringFromSelector(_cmd), self.XcodeTemplatePBXPath, self.XcodeSupportProjectURL.path); + DLog(@"Copying project.pbxproj from %@ to %@", self.XcodeTemplatePBXPath, self.XcodeSupportProjectURL.path); [self.fm copyItemAtPath:self.XcodeTemplatePBXPath toPath:self.XcodeSupportPBXPath error:nil]; - DLog(@"%@ Reading the content of the project.pbxproj", NSStringFromSelector(_cmd)); + DLog(@"Reading the content of the project.pbxproj"); NSMutableString *PBXContent = [NSMutableString stringWithContentsOfFile:self.XcodeSupportPBXPath encoding:NSUTF8StringEncoding error:nil]; [PBXContent writeToFile:self.XcodeSupportPBXPath atomically:YES encoding:NSUTF8StringEncoding error:nil]; - DLog(@"%@ PBX file adapted to the project", NSStringFromSelector(_cmd)); + DLog(@"PBX file adapted to the project"); [self.fm createDirectoryAtPath:self.supportPath withIntermediateDirectories:YES attributes:nil error:nil]; @@ -226,9 +249,6 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; */ - (void)populateXcodeProject:(BOOL)shouldNotify { - if (shouldNotify) - [self notifyUserWithTitle:@"Loading project" message:self.currentProjectPath.lastPathComponent]; - // First populate with all non-framework code [self populateXcodeProjectWithProjectRelativePath:@""]; @@ -242,10 +262,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; [self populateXcodeProjectWithProjectRelativePath:@"Resources"]; if (shouldNotify) - { [[NSNotificationCenter defaultCenter] postNotificationName:XCCDidPopulateProjectNotification object:self userInfo:nil]; - [self notifyUserWithTitle:@"Project loaded" message:self.currentProjectPath.lastPathComponent]; - } } - (void)populateXcodeProjectWithProjectRelativePath:(NSString *)aProjectPath @@ -329,6 +346,8 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; - (void)listenToProjectAtPath:(NSString *)path { self.isLoadingProject = YES; + + [self notifyUserWithTitle:@"Loading project…" message:path.lastPathComponent]; [self clearErrors:self]; self.currentProjectPath = path; @@ -348,9 +367,36 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; [[NSUserDefaults standardUserDefaults] setObject:self.currentProjectPath forKey:kDefaultLastOpenedPath]; - [self notifyUserWithTitle:@"Listening to project" message:self.currentProjectPath.lastPathComponent]; + [self notifyUserWithTitle:@"Project loaded" message:self.currentProjectPath.lastPathComponent]; } +- (IBAction)openInXcode:(id)aSender +{ + if (!self.currentProjectPath) + return; + + DLog(@"Opening Xcode project at: %@", self.XcodeSupportProjectURL.path); + system([[NSString stringWithFormat:@"open \"%@\"", self.XcodeSupportProjectURL.path] UTF8String]); +} + +- (IBAction)resetProject:(id)aSender +{ + NSString *projectPath = self.currentProjectPath; + + [self stop]; + + // Close the project in Xcode if it's open + NSString *source = [NSString stringWithFormat:self.closeProjectScriptSource, projectPath]; + NSAppleScript *script = [[NSAppleScript alloc] initWithSource:source]; + + NSAppleEventDescriptor *descriptor; + descriptor = [script executeAndReturnError:nil]; + + [self.fm removeItemAtURL:self.XcodeSupportProjectURL error:nil]; + [self.fm removeItemAtPath:self.supportPath error:nil]; + + [self listenToProjectAtPath:projectPath]; +} #pragma mark - Event Stream @@ -371,7 +417,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; if (self.supportsFileBasedListening) { - DLog(@"%@ Initializing the FSEventStream at file level (clean)", NSStringFromSelector(_cmd)); + DLog(@"Initializing the FSEventStream at file level (clean)"); flags = kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents; } else @@ -464,7 +510,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; if (!self.supportsFileLevelAPI) { - DLog(@"%@ System doesn't support file level API", NSStringFromSelector(_cmd)); + DLog(@"System doesn't support file level API"); [defaults setObject:[NSNumber numberWithInt:kXCCAPIModeFolder] forKey:kDefaultXCCAPIMode]; } @@ -485,7 +531,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; if (self.supportsFileBasedListening) { - DLog(@"%@ using 10.7+ mode listening (clean)", NSStringFromSelector(_cmd)); + DLog(@"using 10.7+ mode listening (clean)"); self.currentAPIMode = @"File level (Lion)"; self.isUsingFileLevelAPI = YES; @@ -493,7 +539,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; } else { - DLog(@"%@ using 10.6 mode listening (dirty)", NSStringFromSelector(_cmd)); + DLog(@"using 10.6 mode listening (dirty)"); self.reactToInodeModification = NO; self.currentAPIMode = @"Folder level (Snow Leopard)"; self.isUsingFileLevelAPI = NO; @@ -615,10 +661,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; return; NSString *projectPath = [self projectPathForSourcePath:path]; - BOOL success = [self processModifiedFileAtPath:path projectSourcePath:projectPath notify:shouldNotify]; - - if (success) - [self notifyUserWithTitle:@"File successfully processed" message:path.lastPathComponent]; + [self processModifiedFileAtPath:path projectSourcePath:projectPath notify:shouldNotify]; } - (BOOL)processModifiedFileAtPath:(NSString *)realSourcePath projectSourcePath:(NSString *)projectSourcePath notify:(BOOL)shouldNotify @@ -629,35 +672,33 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; NSArray *arguments = nil; NSArray *pbxArguments = nil; - NSString *growlTitle = nil; - NSString *growlMessage = nil; NSString *response = nil; - NSString *projectRelativePath = [projectSourcePath substringFromIndex:self.currentProjectPath.length + 1]; + NSString *notificationTitle = nil; + NSString *notificationMessage = projectRelativePath.lastPathComponent; [[NSNotificationCenter defaultCenter] postNotificationName:XCCConversionDidStartNotification object:self]; // Remove all errors for the path being processed - BOOL (^pathMatcher)(id obj, NSUInteger idx, BOOL *stop); - - pathMatcher = ^(id obj, NSUInteger idx, BOOL *stop) - { - return [[obj valueForKey:@"path"] isEqualToString:realSourcePath]; - }; - - NSIndexSet *matchingErrors = [self.errorList indexesOfObjectsPassingTest:pathMatcher]; + NSIndexSet *matchingErrors = [self.errorList indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) + { + return [[obj valueForKey:@"path"] isEqualToString:realSourcePath]; + }]; + [self.errorListController removeObjectsAtArrangedObjectIndexes:matchingErrors]; if ([self isXibFile:realSourcePath]) { + // nib2cib can take a while to run, show a message while the conversion is happening + [self notifyUserWithTitle:@"Converting xib…" message:projectRelativePath.lastPathComponent]; + arguments = @[ @"-c", [NSString stringWithFormat:@"source '%@'; nib2cib --no-colors '%@'", self.profilePath, realSourcePath], @"" ]; - growlTitle = @"Converting xib..."; - growlMessage = projectRelativePath.lastPathComponent; + notificationTitle = @"Xib converted"; } else if ([self isObjjFile:realSourcePath]) { @@ -679,23 +720,20 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; projectSourcePath] ]; - growlTitle = @"Processing Objective-J source..."; - growlMessage = projectRelativePath.lastPathComponent; + notificationTitle = @"Objective-J source processed"; } else if ([self isXCCIgnoreFile:realSourcePath]) { [self computeIgnoredPaths]; - growlTitle = @"Parsing .xcodecapp-ignore..."; - growlMessage = @"Updating ignored paths"; + notificationTitle = @"Parsed .xcodecapp-ignore"; + notificationMessage = @"Ignored paths updated"; arguments = nil; } // Run the task and get the response if needed if (arguments) { - DLog(@"%@ Running conversion task...", NSStringFromSelector(_cmd)); - - [self notifyUserWithTitle:growlTitle message:growlMessage]; + DLog(@"Running conversion task..."); NSDictionary *taskResult = [self runTaskWithLaunchPath:self.shellPath arguments:arguments @@ -704,7 +742,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; NSInteger status = [taskResult[@"status"] intValue]; response = taskResult[@"response"]; - DLog(@"%@ Conversion task result/response: %ld/%@", NSStringFromSelector(_cmd), status, response); + DLog(@"Conversion task result/response: %ld/%@", status, response); if (status != 0) { @@ -715,40 +753,54 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; if ([self isXibFile:realSourcePath]) { + notificationTitle = @"Error converting xib"; + NSString *message = [NSString stringWithFormat:@"%@\n%@", realSourcePath.lastPathComponent, response]; - [self.errorListController addObject:@{ @"message":message, @"path":realSourcePath }]; + [self.errorListController addObject:@{ @"message":message, @"path":realSourcePath, @"status":taskResult[@"status"] }]; } else { + notificationTitle = [(XCCStatusCodeError ? @"Error" : @"Warning") stringByAppendingString:@" parsing Objective-J source"]; + NSArray *errors = [response propertyList]; for (NSDictionary *error in errors) { NSMutableDictionary *newError = [error mutableCopy]; newError[@"message"] = [NSString stringWithFormat:@"%@, line %d\n%@", [error[@"path"] lastPathComponent], [error[@"line"] intValue], error[@"message"]]; + newError[@"status"] = taskResult[@"status"]; [self.errorListController addObject:newError]; } } - if ([[NSUserDefaults standardUserDefaults] boolForKey:kDefaultXCCAutoOpenErrorsPanel]) + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + if ((status == XCCStatusCodeError && [defaults boolForKey:kDefaultXCCAutoOpenErrorsPanelOnErrors]) || + (status == XCCStatusCodeWarning && [defaults boolForKey:kDefaultXCCAutoOpenErrorsPanelOnWarnings])) + { [self openErrorsPanel:self]; + } - [self notifyUserWithTitle:@"Error processing file" message:projectRelativePath.lastPathComponent]; + [self notifyUserWithTitle:notificationTitle message:notificationMessage]; + } + else if (!self.isLoadingProject) + { + [self notifyUserWithTitle:notificationTitle message:notificationMessage]; } } if (pbxArguments) { - DLog(@"%@ Running update PBX task...", NSStringFromSelector(_cmd)); + DLog(@"Running update PBX task..."); NSDictionary *taskResult; taskResult = [self runTaskWithLaunchPath:self.shellPath arguments:pbxArguments returnType:kTaskReturnTypeStdOut]; - DLog(@"%@ Update PBX Task result/response: %@/%@", NSStringFromSelector(_cmd), taskResult[@"status"], taskResult[@"response"]); + DLog(@"Update PBX Task result/response: %@/%@", taskResult[@"status"], taskResult[@"response"]); } [[NSNotificationCenter defaultCenter] postNotificationName:XCCConversionDidStopNotification object:self]; - DLog(@"%@ Processed: %@", NSStringFromSelector(_cmd), realSourcePath); + DLog(@"Processed: %@", realSourcePath); return success; } @@ -823,13 +875,13 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; NSString *shadowHeaderPath = [shadowBasePath stringByAppendingPathExtension:@"h"]; NSString *shadowImplementationPath = [shadowBasePath stringByAppendingPathExtension:@"m"]; - DLog(@"%@ Removing shadow header file: %@", NSStringFromSelector(_cmd), shadowHeaderPath); + DLog(@"Removing shadow header file: %@", shadowHeaderPath); [self.fm removeItemAtPath:shadowHeaderPath error:nil]; - DLog(@"%@ Removing shadow implementation file: %@", NSStringFromSelector(_cmd), shadowImplementationPath); + DLog(@"Removing shadow implementation file: %@", shadowImplementationPath); [self.fm removeItemAtPath:shadowImplementationPath error:nil]; - DLog(@"%@ Removing PBX reference", NSStringFromSelector(_cmd)); + DLog(@"Removing PBX reference"); NSString *projectSourcePath = [self projectPathForSourcePath:sourcePath]; NSArray *pbxArguments = @[ @@ -845,7 +897,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; taskResult = [self runTaskWithLaunchPath:self.shellPath arguments:pbxArguments returnType:kTaskReturnTypeStdOut]; - DLog(@"%@ PBX Reference removal status/response: %@/%@", NSStringFromSelector(_cmd), taskResult[@"status"], taskResult[@"response"]); + DLog(@"PBX Reference removal status/response: %@/%@", taskResult[@"status"], taskResult[@"response"]); } /*! @@ -951,7 +1003,7 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; return ignore; } -#pragma mark - Errors panel +#pragma mark - Errors - (IBAction)openErrorsPanel:(id)aSender { @@ -1082,6 +1134,16 @@ NSArray *XCCDefaultIgnoredPathRegexes = nil; self.errorListController.content = self.errorList; } +- (BOOL)hasErrors +{ + NSInteger index = [self.errorList indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) + { + return [[obj valueForKey:@"status"] intValue] == XCCStatusCodeError; + }]; + + return index != NSNotFound; +} + #pragma mark - User notifications - (NSString *)applicationNameForGrowl diff --git a/Tools/XcodeCapp/XcodeCapp/UserDefaults.h b/Tools/XcodeCapp/XcodeCapp/UserDefaults.h index 3e25d9797..8cbfc8098 100644 --- a/Tools/XcodeCapp/XcodeCapp/UserDefaults.h +++ b/Tools/XcodeCapp/XcodeCapp/UserDefaults.h @@ -17,7 +17,8 @@ extern NSString * const kDefaultFirstLaunchVersion; extern NSString * const kDefaultXCCAPIMode; extern NSString * const kDefaultXCCReactMode; extern NSString * const kDefaultXCCReopenLastProject; -extern NSString * const kDefaultXCCAutoOpenErrorsPanel; +extern NSString * const kDefaultXCCAutoOpenErrorsPanelOnWarnings; +extern NSString * const kDefaultXCCAutoOpenErrorsPanelOnErrors; extern NSString * const kDefaultXCCProjectHistory; extern NSString * const kDefaultLastOpenedPath; extern NSString * const kDefaultPathModificationDates; diff --git a/Tools/XcodeCapp/XcodeCapp/UserDefaults.m b/Tools/XcodeCapp/XcodeCapp/UserDefaults.m index 3a3bc34ff..6aa6cf68a 100644 --- a/Tools/XcodeCapp/XcodeCapp/UserDefaults.m +++ b/Tools/XcodeCapp/XcodeCapp/UserDefaults.m @@ -15,7 +15,8 @@ NSString * const kDefaultFirstLaunchVersion = @"firstLaunchVersion"; NSString * const kDefaultXCCAPIMode = @"XCCAPIMode"; NSString * const kDefaultXCCReactMode = @"XCCReactMode"; NSString * const kDefaultXCCReopenLastProject = @"XCCReopenLastProject"; -NSString * const kDefaultXCCAutoOpenErrorsPanel = @"XCCAutoOpenErrorsPanel"; +NSString * const kDefaultXCCAutoOpenErrorsPanelOnWarnings = @"XCCAutoOpenErrorsPanelOnWarnings"; +NSString * const kDefaultXCCAutoOpenErrorsPanelOnErrors = @"XCCAutoOpenErrorsPanelOnErrors"; NSString * const kDefaultXCCProjectHistory = @"XCCProjectHistory"; NSString * const kDefaultLastOpenedPath = @"LastOpenedPath"; NSString * const kDefaultPathModificationDates = @"pathModificationDates"; diff --git a/Tools/XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib b/Tools/XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib index 738ad0313..448a6bc06 100644 --- a/Tools/XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib +++ b/Tools/XcodeCapp/XcodeCapp/en.lproj/MainMenu.xib @@ -12,7 +12,6 @@ NSArrayController - NSBox NSButton NSButtonCell NSCustomObject @@ -86,6 +85,14 @@ + + + Reset Project + + 2147483647 + + + YES @@ -181,7 +188,7 @@ 268 {{164, 23}, {172, 98}} - + YES 68157504 @@ -195,7 +202,7 @@ Y29tA 3100 - + 6 System textBackgroundColor @@ -221,7 +228,6 @@ Y29tA 266 {{164, 140}, {160, 14}} - YES @@ -260,7 +266,6 @@ Y29tA {{17, 46}, {128, 128}} - _NS:9 YES @@ -283,7 +288,6 @@ Y29tA {358, 185} - {{0, 0}, {2560, 1418}} @@ -518,36 +522,37 @@ Y29tA 3 2 - {{529, 541}, {336, 198}} + {{529, 541}, {341, 155}} 1685586944 Preferences NSWindow - + 256 - + 268 - {{18, 43}, {282, 18}} + {{18, 119}, {295, 18}} - + + YES - + -2080374784 0 - React to inode meta information changes + Listen to the most recent project on launch LucidaGrande 13 1044 - + 1211912448 2 - + NSImage NSSwitch @@ -561,70 +566,23 @@ Y29tA NO - - - 268 - {{18, 20}, {284, 17}} - - YES - - 68157504 - 272630784 - In "File level" API mode, react to touch, chown, etc. - - LucidaGrande - 11 - 16 - - - - - 1 - MC4zNDU1Mjg0ODM0IDAuMzQ1NTI4NDgzNCAwLjM0NTUyODQ4MzQAA - - - NO - - - - 268 - {{18, 162}, {295, 18}} - - - YES - - -2080374784 - 0 - Listen to the most recent project on launch - - - 1211912448 - 2 - - - - - 200 - 25 - - NO - 268 - {{18, 132}, {300, 18}} + {{37, 58}, {81, 18}} - + + YES -2080374784 0 - Automatically open Errors & Warnings panel + Warnings 1211912448 2 - + @@ -633,35 +591,37 @@ Y29tA NO - + - 10 - {{18, 76}, {300, 5}} + 268 + {{139, 58}, {60, 18}} - - _NS:9 - {0, 0} - - 67108864 + + + YES + + -2080374784 0 - Box + Errors - - - 3 - MCAwLjgwMDAwMDAxMTkAA - + + 1211912448 + 2 + + + + + 200 + 25 - 3 - 2 - 0 - NO + NO 268 - {{17, 101}, {106, 17}} + {{17, 21}, {106, 17}} + _NS:1535 YES @@ -680,9 +640,10 @@ Y29tA 268 - {{126, 95}, {56, 26}} + {{126, 15}, {56, 26}} - + + _NS:9 YES @@ -747,8 +708,31 @@ Y29tA NO + + + 268 + {{18, 84}, {306, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Automatically open Errors & Warnings panel on: + + _NS:1535 + + + + + NO + - {336, 198} + {341, 155} + + {{0, 0}, {2560, 1418}} @@ -1024,14 +1008,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 619 - - - openInXcode: - - - - 620 - menuItemHistory @@ -1096,6 +1072,14 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 792 + + + save: + + + + 821 + errorTable @@ -1153,40 +1137,20 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 786 - - value: values.XCCReactMode - - - - - - value: values.XCCReactMode - value - values.XCCReactMode - - NSValidatesImmediately - - - 2 - + + openInXcode: + + - 629 + 815 - - enabled: isUsingFileLevelAPI - - - - - - enabled: isUsingFileLevelAPI - enabled - isUsingFileLevelAPI - 2 - + + resetProject: + + - 630 + 816 @@ -1351,15 +1315,15 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA - value: values.XCCAutoOpenErrorsPanel + value: values.XCCAutoOpenErrorsPanelOnWarnings - value: values.XCCAutoOpenErrorsPanel + value: values.XCCAutoOpenErrorsPanelOnWarnings value - values.XCCAutoOpenErrorsPanel + values.XCCAutoOpenErrorsPanelOnWarnings NSValidatesImmediately @@ -1367,7 +1331,7 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 2 - 793 + 823 @@ -1385,6 +1349,42 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA 810 + + + enabled: currentProjectPath.length + + + + + + enabled: currentProjectPath.length + enabled + currentProjectPath.length + 2 + + + 812 + + + + value: values.XCCAutoOpenErrorsPanelOnErrors + + + + + + value: values.XCCAutoOpenErrorsPanelOnErrors + value + values.XCCAutoOpenErrorsPanelOnErrors + + NSValidatesImmediately + + + 2 + + + 824 + @@ -1432,6 +1432,7 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA + @@ -1521,31 +1522,14 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA - - - - + + + - - 559 - - - - - - - - 561 - - - - - - 563 @@ -1559,16 +1543,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA - - 578 - - - - - 580 - - - 581 @@ -1770,11 +1744,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA - - 794 - - - 797 @@ -1842,6 +1811,37 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA + + 811 + + + + + 817 + + + + + + + + 818 + + + + + 819 + + + + + + + + 820 + + + @@ -1873,12 +1873,8 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1918,7 +1914,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1929,12 +1924,25 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + When an error or warning occurs, automatically open the Errors & Warnings panel + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin - 810 + 824 @@ -1945,7 +1953,7 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA id id id - id + id @@ -1960,8 +1968,8 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA openHelp: id - - openInXcode: + + openPreferences: id @@ -2052,6 +2060,8 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA id id id + id + id @@ -2066,6 +2076,14 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA openErrorsPanel: id + + openInXcode: + id + + + resetProject: + id + NSArrayController