├── .gitignore ├── .travis.yml ├── ACCodeSnippetRepository Tests ├── ACCodeSnippetGitDataStoreTests.m ├── ACCodeSnippetRepository Tests-Info.plist ├── ACCodeSnippetRepository Tests-Prefix.pch ├── ACCodeSnippetSerializationTests.m ├── ACGitRepositoryTests.m ├── NSDictionary+MergeTests.m └── en.lproj │ └── InfoPlist.strings ├── ACCodeSnippetRepository.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── ACCodeSnippetRepository ├── ACCodeSnippetRepository-Info.plist ├── ACCodeSnippetRepository-Prefix.pch ├── ACCodeSnippetRepositoryPlugin.h ├── ACCodeSnippetRepositoryPlugin.m ├── Categories │ ├── NSDictionary+Merge.h │ ├── NSDictionary+Merge.m │ ├── NSString+Path.h │ ├── NSString+Path.m │ ├── NSTask+Extras.h │ └── NSTask+Extras.m ├── Classes │ ├── ACGitRepository.h │ ├── ACGitRepository.m │ ├── DataStores │ │ ├── ACCodeSnippetDataStoreProtocol.h │ │ ├── ACCodeSnippetGitDataStore.h │ │ └── ACCodeSnippetGitDataStore.m │ └── Serialization │ │ ├── ACCodeSnippetSerialization.h │ │ └── ACCodeSnippetSerialization.m ├── Controllers │ ├── ACCodeSnippetRepositoryConfigurationWindowController.h │ ├── ACCodeSnippetRepositoryConfigurationWindowController.m │ └── ACCodeSnippetRepositoryConfigurationWindowController.xib ├── IDE │ ├── Headers │ │ ├── IDE.h │ │ ├── IDECodeSnippet.h │ │ ├── IDECodeSnippetLibrary.h │ │ └── IDECodeSnippetRepository.h │ ├── Swizzle │ │ ├── IDECodeSnippetRepositorySwizzler.h │ │ ├── IDECodeSnippetRepositorySwizzler.m │ │ ├── Swizzler.h │ │ └── Swizzler.m │ └── classdump.txt ├── Resources │ └── Images │ │ ├── GitHub-Mark-120px-plus.png │ │ ├── GitHub-Mark-32px.png │ │ └── GitHub-Mark-64px.png └── en.lproj │ └── InfoPlist.strings ├── Documentation ├── architecture.jpg └── architecture.key │ ├── Data │ ├── 110809_FamilyChineseOahu_EN_00317_2040x1360-small-12.jpg │ ├── 110809_FamilyChineseOahu_EN_02016_981x654-small-14.jpg │ ├── 110809_FamilyChineseOahu_EN_02390_2880x1921-small-10.jpg │ ├── mt10@2x-92.jpg │ ├── mt1@2x-83.jpg │ ├── mt2@2x-84.jpg │ ├── mt3@2x-85.jpg │ ├── mt4@2x-86.jpg │ ├── mt5@2x-87.jpg │ ├── mt6@2x-88.jpg │ ├── mt7@2x-89.jpg │ ├── mt8@2x-90.jpg │ ├── mt9@2x-91.jpg │ └── st0-332.jpg │ ├── Index.zip │ ├── Metadata │ ├── BuildVersionHistory.plist │ ├── DocumentIdentifier │ └── Properties.plist │ ├── preview-micro.jpg │ ├── preview-web.jpg │ └── preview.jpg ├── LICENSE ├── README.md └── Screenshots ├── screenshot01.png ├── screenshot02.png ├── screenshot03.png └── screenshot04.png /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # .gitignore file for Xcode4 / OS X Source projects 3 | # 4 | # Version 2.0 5 | # For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects 6 | # 7 | # 2013 updates: 8 | # - fixed the broken "save personal Schemes" 9 | # 10 | # NB: if you are storing "built" products, this WILL NOT WORK, 11 | # and you should use a different .gitignore (or none at all) 12 | # This file is for SOURCE projects, where there are many extra 13 | # files that we want to exclude 14 | # 15 | ######################### 16 | 17 | ##### 18 | # OS X temporary files that should never be committed 19 | 20 | .DS_Store 21 | *.swp 22 | *.lock 23 | profile 24 | 25 | 26 | #### 27 | # Xcode temporary files that should never be committed 28 | # 29 | # NB: NIB/XIB files still exist even on Storyboard projects, so we want this... 30 | 31 | *~.nib 32 | 33 | 34 | #### 35 | # Xcode build files - 36 | # 37 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData" 38 | 39 | DerivedData/ 40 | 41 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build" 42 | 43 | build/ 44 | 45 | 46 | ##### 47 | # Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups) 48 | # 49 | # This is complicated: 50 | # 51 | # SOMETIMES you need to put this file in version control. 52 | # Apple designed it poorly - if you use "custom executables", they are 53 | # saved in this file. 54 | # 99% of projects do NOT use those, so they do NOT want to version control this file. 55 | # ..but if you're in the 1%, comment out the line "*.pbxuser" 56 | 57 | *.pbxuser 58 | *.mode1v3 59 | *.mode2v3 60 | *.perspectivev3 61 | # NB: also, whitelist the default ones, some projects need to use these 62 | !default.pbxuser 63 | !default.mode1v3 64 | !default.mode2v3 65 | !default.perspectivev3 66 | 67 | 68 | #### 69 | # Xcode 4 - semi-personal settings 70 | # 71 | # 72 | # OPTION 1: --------------------------------- 73 | # throw away ALL personal settings (including custom schemes! 74 | # - unless they are "shared") 75 | # 76 | # NB: this is exclusive with OPTION 2 below 77 | xcuserdata 78 | 79 | # OPTION 2: --------------------------------- 80 | # get rid of ALL personal settings, but KEEP SOME OF THEM 81 | # - NB: you must manually uncomment the bits you want to keep 82 | # 83 | # NB: this is exclusive with OPTION 1 above 84 | # 85 | #xcuserdata/**/* 86 | 87 | # (requires option 2 above): Personal Schemes 88 | # 89 | #!xcuserdata/**/xcschemes/* 90 | 91 | #### 92 | # XCode 4 workspaces - more detailed 93 | # 94 | # Workspaces are important! They are a core feature of Xcode - don't exclude them :) 95 | # 96 | # Workspace layout is quite spammy. For reference: 97 | # 98 | # /(root)/ 99 | # /(project-name).xcodeproj/ 100 | # project.pbxproj 101 | # /project.xcworkspace/ 102 | # contents.xcworkspacedata 103 | # /xcuserdata/ 104 | # /(your name)/xcuserdatad/ 105 | # UserInterfaceState.xcuserstate 106 | # /xcsshareddata/ 107 | # /xcschemes/ 108 | # (shared scheme name).xcscheme 109 | # /xcuserdata/ 110 | # /(your name)/xcuserdatad/ 111 | # (private scheme).xcscheme 112 | # xcschememanagement.plist 113 | # 114 | # 115 | 116 | #### 117 | # Xcode 4 - Deprecated classes 118 | # 119 | # Allegedly, if you manually "deprecate" your classes, they get moved here. 120 | # 121 | # We're using source-control, so this is a "feature" that we do not want! 122 | 123 | *.moved-aside 124 | 125 | 126 | #### 127 | # UNKNOWN: recommended by others, but I can't discover what these files are 128 | # 129 | # ...none. Everything is now explained. -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository Tests/ACCodeSnippetGitDataStoreTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetGitDataStoreTests.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 13/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ACCodeSnippetGitDataStore.h" 11 | 12 | 13 | @interface ACCodeSnippetGitDataStoreTests : SenTestCase 14 | @end 15 | 16 | @implementation ACCodeSnippetGitDataStoreTests 17 | 18 | 19 | - (void)testExample { 20 | 21 | ACGitRepository *gitRepository = [[ACGitRepository alloc] init]; 22 | ACCodeSnippetGitDataStore *gitDataStore = [[ACCodeSnippetGitDataStore alloc] initWithGitRepository:gitRepository]; 23 | 24 | [gitDataStore syncCodeSnippets]; 25 | 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository Tests/ACCodeSnippetRepository Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.acoomans.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository Tests/ACCodeSnippetRepository Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository Tests/ACCodeSnippetSerializationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetSerializationTests.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ACCodeSnippetSerialization.h" 11 | 12 | @interface ACCodeSnippetSerializationTests : SenTestCase 13 | @end 14 | 15 | @implementation ACCodeSnippetSerializationTests 16 | 17 | - (void)testSerialize { 18 | 19 | NSDictionary *dict = @{ 20 | ACCodeSnippetTitleKey: @"title", 21 | ACCodeSnippetSummaryKey: @"summary", 22 | ACCodeSnippetContentsKey: @"line1\nline2\nline3", 23 | @"WhateverKey": @"WhateverValue", 24 | @"Array": @[@"one", @"two"], 25 | }; 26 | 27 | NSData *data = [ACCodeSnippetSerialization dataWithDictionary:dict 28 | format:ACCodeSnippetSerializationFormatC 29 | options:0 30 | error:nil]; 31 | NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 32 | NSLog(@"\n%@", string); 33 | 34 | STAssertTrue([string rangeOfString:@"title"].location != NSNotFound, nil); 35 | STAssertTrue([string rangeOfString:@"summary"].location != NSNotFound, nil); 36 | STAssertTrue([string rangeOfString:@"line1\nline2\nline3"].location != NSNotFound, nil); 37 | STAssertTrue([string rangeOfString:@"WhateverKey"].location != NSNotFound, nil); 38 | STAssertTrue([string rangeOfString:@"WhateverValue"].location != NSNotFound, nil); 39 | 40 | STAssertTrue([string rangeOfString:@"one"].location != NSNotFound, nil); 41 | STAssertTrue([string rangeOfString:@"two"].location != NSNotFound, nil); 42 | } 43 | 44 | - (void)testDeserialize { 45 | NSString *string = @"// title\n// summary\n//\n// WhateverKey: WhateverValue\n// Array: [one,two]\nline1\nline2\nline3\n"; 46 | 47 | NSDictionary *dict = [ACCodeSnippetSerialization dictionaryWithData:[string dataUsingEncoding:NSUTF8StringEncoding] 48 | options:0 49 | format:ACCodeSnippetSerializationFormatC 50 | error:nil]; 51 | NSLog(@"\n%@", dict); 52 | 53 | STAssertTrue([dict[ACCodeSnippetTitleKey] isEqualToString:@"title"], nil); 54 | STAssertTrue([dict[ACCodeSnippetSummaryKey] isEqualToString:@"summary"], nil); 55 | STAssertTrue([dict[ACCodeSnippetContentsKey] isEqualToString:@"line1\nline2\nline3\n"], nil); 56 | STAssertTrue([dict[@"WhateverKey"] isEqualToString:@"WhateverValue"], nil); 57 | 58 | NSArray *a = @[@"one", @"two"]; 59 | STAssertTrue([dict[@"Array"] isEqualToArray:a], nil); 60 | } 61 | 62 | - (void)testDeserialize2 { 63 | NSString *string = @"// Title: title\n// Summary: summary\n//\n// WhateverKey: WhateverValue\n// Array: [one,two]\nline1\nline2\nline3\n"; 64 | 65 | NSDictionary *dict = [ACCodeSnippetSerialization dictionaryWithData:[string dataUsingEncoding:NSUTF8StringEncoding] 66 | options:0 67 | format:ACCodeSnippetSerializationFormatC 68 | error:nil]; 69 | NSLog(@"\n%@", dict); 70 | 71 | STAssertTrue([dict[ACCodeSnippetTitleKey] isEqualToString:@"title"], nil); 72 | STAssertTrue([dict[ACCodeSnippetSummaryKey] isEqualToString:@"summary"], nil); 73 | STAssertTrue([dict[ACCodeSnippetContentsKey] isEqualToString:@"line1\nline2\nline3\n"], nil); 74 | STAssertTrue([dict[@"WhateverKey"] isEqualToString:@"WhateverValue"], nil); 75 | 76 | NSArray *a = @[@"one", @"two"]; 77 | STAssertTrue([dict[@"Array"] isEqualToArray:a], nil); 78 | } 79 | 80 | - (void)testSerializeDeserialize { 81 | 82 | NSDictionary *dict1 = @{ 83 | ACCodeSnippetTitleKey: @"title", 84 | ACCodeSnippetSummaryKey: @"summary", 85 | ACCodeSnippetContentsKey: @"line1\nline2\nline3\n", 86 | @"WhateverKey": @"WhateverValue", 87 | @"Array": @[@"one", @"two"], 88 | }; 89 | 90 | NSData *data = [ACCodeSnippetSerialization dataWithDictionary:dict1 91 | format:ACCodeSnippetSerializationFormatC 92 | options:0 93 | error:nil]; 94 | 95 | NSDictionary *dict2 = [ACCodeSnippetSerialization dictionaryWithData:data 96 | options:0 97 | format:ACCodeSnippetSerializationFormatC 98 | error:nil]; 99 | STAssertTrue([dict1 isEqualToDictionary:dict2], nil); 100 | 101 | } 102 | 103 | 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository Tests/ACGitRepositoryTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACGitRepositoryTests.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ACGitRepository.h" 11 | 12 | @interface ACGitRepositoryTests : SenTestCase 13 | @end 14 | 15 | @implementation ACGitRepositoryTests 16 | 17 | - (void)testExample { 18 | 19 | NSURL *gitURL = [NSURL URLWithString:@"git@github.com:acoomans/test.git"]; 20 | 21 | NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject]; 22 | NSString *gitPath = [NSString pathWithComponents:@[libraryPath, @"Developer", @"Xcode", @"UserData", @"CodeSnippets", @"git"]]; 23 | 24 | ACGitRepository *git = [[ACGitRepository alloc] initWithLocalRepositoryDirectory:gitPath]; 25 | 26 | //[git forkRemoteRepositoryWithURL:gitURL inDirectory:gitPath]; 27 | //[git removeLocalRepository]; 28 | //NSLog(@"%@", [git identifierForCurrentCommit]); 29 | //NSLog(@"%@", [git changedFilesSinceCommitWithIdentifier:@"HEAD~6"]); 30 | 31 | git.remoteRepositoryURL = gitURL; 32 | NSLog(@"%@", [git remoteRepositoryURL]); 33 | 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository Tests/NSDictionary+MergeTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+MergeTests.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 17/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSDictionary+Merge.h" 11 | 12 | @interface NSDictionary_MergeTests : SenTestCase 13 | @end 14 | 15 | @implementation NSDictionary_MergeTests 16 | 17 | - (void)testExample { 18 | NSDictionary *d = @{ 19 | @"a": @"a", 20 | @"b": @"b", 21 | }; 22 | 23 | NSDictionary *r = [d dictionaryByMergingDictionary:@{ 24 | @"b": @"B", 25 | @"c": @"c" 26 | }]; 27 | 28 | STAssertTrue([r[@"a"] isEqualToString:@"a"], nil); 29 | STAssertTrue([r[@"b"] isEqualToString:@"b"], nil); 30 | STAssertTrue([r[@"c"] isEqualToString:@"c"], nil); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 51010E0218AC5CB1000AA1F1 /* ACGitRepository.m in Sources */ = {isa = PBXBuildFile; fileRef = 51010E0118AC5CB1000AA1F1 /* ACGitRepository.m */; }; 11 | 51010E0318AC5CB1000AA1F1 /* ACGitRepository.m in Sources */ = {isa = PBXBuildFile; fileRef = 51010E0118AC5CB1000AA1F1 /* ACGitRepository.m */; }; 12 | 5105B22718AC59520066728E /* NSTask+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = 5105B22618AC59520066728E /* NSTask+Extras.m */; }; 13 | 5105B22818AC59520066728E /* NSTask+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = 5105B22618AC59520066728E /* NSTask+Extras.m */; }; 14 | 5132BF3618AD5EE500C0DE83 /* ACCodeSnippetGitDataStoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5132BF3518AD5EE500C0DE83 /* ACCodeSnippetGitDataStoreTests.m */; }; 15 | 5133D0D018AC5CF900998BE2 /* ACGitRepositoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5133D0CF18AC5CF900998BE2 /* ACGitRepositoryTests.m */; }; 16 | 5153BAA918B3406D00C1E75B /* NSDictionary+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = 5153BAA818B3406D00C1E75B /* NSDictionary+Merge.m */; }; 17 | 5153BAAA18B3406D00C1E75B /* NSDictionary+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = 5153BAA818B3406D00C1E75B /* NSDictionary+Merge.m */; }; 18 | 5153BAAC18B3410C00C1E75B /* NSDictionary+MergeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5153BAAB18B3410C00C1E75B /* NSDictionary+MergeTests.m */; }; 19 | 5154068518AC4B500065CA33 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5154068418AC4B500065CA33 /* SenTestingKit.framework */; }; 20 | 5154068B18AC4B500065CA33 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5154068918AC4B500065CA33 /* InfoPlist.strings */; }; 21 | 515CE9DA18B1DCAA000962EA /* GitHub-Mark-120px-plus.png in Resources */ = {isa = PBXBuildFile; fileRef = 515CE9D718B1DCAA000962EA /* GitHub-Mark-120px-plus.png */; }; 22 | 515CE9DB18B1DCAA000962EA /* GitHub-Mark-32px.png in Resources */ = {isa = PBXBuildFile; fileRef = 515CE9D818B1DCAA000962EA /* GitHub-Mark-32px.png */; }; 23 | 515CE9DC18B1DCAA000962EA /* GitHub-Mark-64px.png in Resources */ = {isa = PBXBuildFile; fileRef = 515CE9D918B1DCAA000962EA /* GitHub-Mark-64px.png */; }; 24 | 5162AC2A18AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5162AC2818AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.m */; }; 25 | 5162AC2B18AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5162AC2918AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.xib */; }; 26 | 517DF2A618AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 517DF2A318AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.m */; }; 27 | 517DF2A718AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 517DF2A318AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.m */; }; 28 | 517DF2A818AC4BF1008980B3 /* Swizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 517DF2A518AC4BF1008980B3 /* Swizzler.m */; }; 29 | 517DF2A918AC4BF1008980B3 /* Swizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 517DF2A518AC4BF1008980B3 /* Swizzler.m */; }; 30 | 517E12C018AC5F8A0072B743 /* ACCodeSnippetGitDataStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 517E12BF18AC5F8A0072B743 /* ACCodeSnippetGitDataStore.m */; }; 31 | 517E12C118AC5F8A0072B743 /* ACCodeSnippetGitDataStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 517E12BF18AC5F8A0072B743 /* ACCodeSnippetGitDataStore.m */; }; 32 | 517FD2CE18AC4C70003E1813 /* ACCodeSnippetSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 517FD2CD18AC4C70003E1813 /* ACCodeSnippetSerialization.m */; }; 33 | 517FD2CF18AC4C70003E1813 /* ACCodeSnippetSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 517FD2CD18AC4C70003E1813 /* ACCodeSnippetSerialization.m */; }; 34 | 517FD2D118AC4C89003E1813 /* ACCodeSnippetSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 517FD2D018AC4C89003E1813 /* ACCodeSnippetSerializationTests.m */; }; 35 | 518E69A318AC4A8900C57456 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 518E69A218AC4A8900C57456 /* AppKit.framework */; }; 36 | 518E69A518AC4A8900C57456 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 518E69A418AC4A8900C57456 /* Foundation.framework */; }; 37 | 518E69AB18AC4A8900C57456 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 518E69A918AC4A8900C57456 /* InfoPlist.strings */; }; 38 | 518E69AE18AC4A8900C57456 /* ACCodeSnippetRepositoryPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 518E69AD18AC4A8900C57456 /* ACCodeSnippetRepositoryPlugin.m */; }; 39 | 51D2D55418AC58FD00493579 /* NSString+Path.m in Sources */ = {isa = PBXBuildFile; fileRef = 51D2D55318AC58FD00493579 /* NSString+Path.m */; }; 40 | 51D2D55518AC590000493579 /* NSString+Path.m in Sources */ = {isa = PBXBuildFile; fileRef = 51D2D55318AC58FD00493579 /* NSString+Path.m */; }; 41 | /* End PBXBuildFile section */ 42 | 43 | /* Begin PBXContainerItemProxy section */ 44 | 5154068F18AC4B500065CA33 /* PBXContainerItemProxy */ = { 45 | isa = PBXContainerItemProxy; 46 | containerPortal = 518E699718AC4A8900C57456 /* Project object */; 47 | proxyType = 1; 48 | remoteGlobalIDString = 518E699E18AC4A8900C57456; 49 | remoteInfo = ACCodeSnippetRepository; 50 | }; 51 | /* End PBXContainerItemProxy section */ 52 | 53 | /* Begin PBXFileReference section */ 54 | 51010E0018AC5CB1000AA1F1 /* ACGitRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ACGitRepository.h; sourceTree = ""; }; 55 | 51010E0118AC5CB1000AA1F1 /* ACGitRepository.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACGitRepository.m; sourceTree = ""; }; 56 | 5105B22518AC59520066728E /* NSTask+Extras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTask+Extras.h"; sourceTree = ""; }; 57 | 5105B22618AC59520066728E /* NSTask+Extras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTask+Extras.m"; sourceTree = ""; }; 58 | 5132BF3518AD5EE500C0DE83 /* ACCodeSnippetGitDataStoreTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACCodeSnippetGitDataStoreTests.m; sourceTree = ""; }; 59 | 5133D0CF18AC5CF900998BE2 /* ACGitRepositoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACGitRepositoryTests.m; sourceTree = ""; }; 60 | 5153BAA718B3406D00C1E75B /* NSDictionary+Merge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Merge.h"; sourceTree = ""; }; 61 | 5153BAA818B3406D00C1E75B /* NSDictionary+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Merge.m"; sourceTree = ""; }; 62 | 5153BAAB18B3410C00C1E75B /* NSDictionary+MergeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+MergeTests.m"; sourceTree = ""; }; 63 | 5154068318AC4B500065CA33 /* ACCodeSnippetRepository Tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ACCodeSnippetRepository Tests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | 5154068418AC4B500065CA33 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 65 | 5154068818AC4B500065CA33 /* ACCodeSnippetRepository Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ACCodeSnippetRepository Tests-Info.plist"; sourceTree = ""; }; 66 | 5154068A18AC4B500065CA33 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 67 | 5154068E18AC4B500065CA33 /* ACCodeSnippetRepository Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ACCodeSnippetRepository Tests-Prefix.pch"; sourceTree = ""; }; 68 | 515CE9D718B1DCAA000962EA /* GitHub-Mark-120px-plus.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "GitHub-Mark-120px-plus.png"; sourceTree = ""; }; 69 | 515CE9D818B1DCAA000962EA /* GitHub-Mark-32px.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "GitHub-Mark-32px.png"; sourceTree = ""; }; 70 | 515CE9D918B1DCAA000962EA /* GitHub-Mark-64px.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "GitHub-Mark-64px.png"; sourceTree = ""; }; 71 | 5162AC2718AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ACCodeSnippetRepositoryConfigurationWindowController.h; sourceTree = ""; }; 72 | 5162AC2818AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACCodeSnippetRepositoryConfigurationWindowController.m; sourceTree = ""; }; 73 | 5162AC2918AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ACCodeSnippetRepositoryConfigurationWindowController.xib; sourceTree = ""; }; 74 | 517D918E18AC4BA700A564B9 /* classdump.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = classdump.txt; sourceTree = ""; }; 75 | 517D919018AC4BA700A564B9 /* IDE.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IDE.h; sourceTree = ""; }; 76 | 517D919118AC4BA700A564B9 /* IDECodeSnippet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IDECodeSnippet.h; sourceTree = ""; }; 77 | 517D919218AC4BA700A564B9 /* IDECodeSnippetLibrary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IDECodeSnippetLibrary.h; sourceTree = ""; }; 78 | 517D919318AC4BA700A564B9 /* IDECodeSnippetRepository.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IDECodeSnippetRepository.h; sourceTree = ""; }; 79 | 517DF2A218AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDECodeSnippetRepositorySwizzler.h; sourceTree = ""; }; 80 | 517DF2A318AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IDECodeSnippetRepositorySwizzler.m; sourceTree = ""; }; 81 | 517DF2A418AC4BF1008980B3 /* Swizzler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Swizzler.h; sourceTree = ""; }; 82 | 517DF2A518AC4BF1008980B3 /* Swizzler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Swizzler.m; sourceTree = ""; }; 83 | 517DF2AE18AC4C1A008980B3 /* ACCodeSnippetDataStoreProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ACCodeSnippetDataStoreProtocol.h; sourceTree = ""; }; 84 | 517E12BE18AC5F8A0072B743 /* ACCodeSnippetGitDataStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ACCodeSnippetGitDataStore.h; sourceTree = ""; }; 85 | 517E12BF18AC5F8A0072B743 /* ACCodeSnippetGitDataStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACCodeSnippetGitDataStore.m; sourceTree = ""; }; 86 | 517FD2CC18AC4C70003E1813 /* ACCodeSnippetSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ACCodeSnippetSerialization.h; sourceTree = ""; }; 87 | 517FD2CD18AC4C70003E1813 /* ACCodeSnippetSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACCodeSnippetSerialization.m; sourceTree = ""; }; 88 | 517FD2D018AC4C89003E1813 /* ACCodeSnippetSerializationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACCodeSnippetSerializationTests.m; sourceTree = ""; }; 89 | 518E699F18AC4A8900C57456 /* ACCodeSnippetRepository.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ACCodeSnippetRepository.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 90 | 518E69A218AC4A8900C57456 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 91 | 518E69A418AC4A8900C57456 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 92 | 518E69A818AC4A8900C57456 /* ACCodeSnippetRepository-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ACCodeSnippetRepository-Info.plist"; sourceTree = ""; }; 93 | 518E69AA18AC4A8900C57456 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 94 | 518E69AC18AC4A8900C57456 /* ACCodeSnippetRepositoryPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ACCodeSnippetRepositoryPlugin.h; sourceTree = ""; }; 95 | 518E69AD18AC4A8900C57456 /* ACCodeSnippetRepositoryPlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ACCodeSnippetRepositoryPlugin.m; sourceTree = ""; }; 96 | 518E69AF18AC4A8900C57456 /* ACCodeSnippetRepository-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ACCodeSnippetRepository-Prefix.pch"; sourceTree = ""; }; 97 | 519AC2B318B4257600F3B4EA /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = ""; }; 98 | 51D2D55218AC58FD00493579 /* NSString+Path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Path.h"; sourceTree = ""; }; 99 | 51D2D55318AC58FD00493579 /* NSString+Path.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Path.m"; sourceTree = ""; }; 100 | /* End PBXFileReference section */ 101 | 102 | /* Begin PBXFrameworksBuildPhase section */ 103 | 5154068018AC4B500065CA33 /* Frameworks */ = { 104 | isa = PBXFrameworksBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | 5154068518AC4B500065CA33 /* SenTestingKit.framework in Frameworks */, 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | 518E699C18AC4A8900C57456 /* Frameworks */ = { 112 | isa = PBXFrameworksBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | 518E69A318AC4A8900C57456 /* AppKit.framework in Frameworks */, 116 | 518E69A518AC4A8900C57456 /* Foundation.framework in Frameworks */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXFrameworksBuildPhase section */ 121 | 122 | /* Begin PBXGroup section */ 123 | 5154068618AC4B500065CA33 /* ACCodeSnippetRepository Tests */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 517FD2D018AC4C89003E1813 /* ACCodeSnippetSerializationTests.m */, 127 | 5133D0CF18AC5CF900998BE2 /* ACGitRepositoryTests.m */, 128 | 5132BF3518AD5EE500C0DE83 /* ACCodeSnippetGitDataStoreTests.m */, 129 | 5153BAAB18B3410C00C1E75B /* NSDictionary+MergeTests.m */, 130 | 5154068718AC4B500065CA33 /* Supporting Files */, 131 | ); 132 | path = "ACCodeSnippetRepository Tests"; 133 | sourceTree = ""; 134 | }; 135 | 5154068718AC4B500065CA33 /* Supporting Files */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 5154068818AC4B500065CA33 /* ACCodeSnippetRepository Tests-Info.plist */, 139 | 5154068918AC4B500065CA33 /* InfoPlist.strings */, 140 | 5154068E18AC4B500065CA33 /* ACCodeSnippetRepository Tests-Prefix.pch */, 141 | ); 142 | name = "Supporting Files"; 143 | sourceTree = ""; 144 | }; 145 | 515CE9D518B1DCAA000962EA /* Resources */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 515CE9D618B1DCAA000962EA /* Images */, 149 | ); 150 | path = Resources; 151 | sourceTree = ""; 152 | }; 153 | 515CE9D618B1DCAA000962EA /* Images */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 515CE9D718B1DCAA000962EA /* GitHub-Mark-120px-plus.png */, 157 | 515CE9D818B1DCAA000962EA /* GitHub-Mark-32px.png */, 158 | 515CE9D918B1DCAA000962EA /* GitHub-Mark-64px.png */, 159 | ); 160 | path = Images; 161 | sourceTree = ""; 162 | }; 163 | 5162AC2618AD9FB4000109C9 /* Controllers */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 5162AC2718AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.h */, 167 | 5162AC2818AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.m */, 168 | 5162AC2918AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.xib */, 169 | ); 170 | path = Controllers; 171 | sourceTree = ""; 172 | }; 173 | 517D918D18AC4BA700A564B9 /* IDE */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 517D918E18AC4BA700A564B9 /* classdump.txt */, 177 | 517D918F18AC4BA700A564B9 /* Headers */, 178 | 517DF2A118AC4BF1008980B3 /* Swizzle */, 179 | ); 180 | path = IDE; 181 | sourceTree = ""; 182 | }; 183 | 517D918F18AC4BA700A564B9 /* Headers */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 517D919018AC4BA700A564B9 /* IDE.h */, 187 | 517D919118AC4BA700A564B9 /* IDECodeSnippet.h */, 188 | 517D919218AC4BA700A564B9 /* IDECodeSnippetLibrary.h */, 189 | 517D919318AC4BA700A564B9 /* IDECodeSnippetRepository.h */, 190 | ); 191 | path = Headers; 192 | sourceTree = ""; 193 | }; 194 | 517DF2A118AC4BF1008980B3 /* Swizzle */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 517DF2A418AC4BF1008980B3 /* Swizzler.h */, 198 | 517DF2A518AC4BF1008980B3 /* Swizzler.m */, 199 | 517DF2A218AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.h */, 200 | 517DF2A318AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.m */, 201 | ); 202 | path = Swizzle; 203 | sourceTree = ""; 204 | }; 205 | 517DF2AA18AC4C1A008980B3 /* Classes */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | 517DF2AD18AC4C1A008980B3 /* DataStores */, 209 | 517FD2CB18AC4C70003E1813 /* Serialization */, 210 | 51010E0018AC5CB1000AA1F1 /* ACGitRepository.h */, 211 | 51010E0118AC5CB1000AA1F1 /* ACGitRepository.m */, 212 | ); 213 | path = Classes; 214 | sourceTree = ""; 215 | }; 216 | 517DF2AD18AC4C1A008980B3 /* DataStores */ = { 217 | isa = PBXGroup; 218 | children = ( 219 | 517DF2AE18AC4C1A008980B3 /* ACCodeSnippetDataStoreProtocol.h */, 220 | 517E12BE18AC5F8A0072B743 /* ACCodeSnippetGitDataStore.h */, 221 | 517E12BF18AC5F8A0072B743 /* ACCodeSnippetGitDataStore.m */, 222 | ); 223 | path = DataStores; 224 | sourceTree = ""; 225 | }; 226 | 517FD2CB18AC4C70003E1813 /* Serialization */ = { 227 | isa = PBXGroup; 228 | children = ( 229 | 517FD2CC18AC4C70003E1813 /* ACCodeSnippetSerialization.h */, 230 | 517FD2CD18AC4C70003E1813 /* ACCodeSnippetSerialization.m */, 231 | ); 232 | path = Serialization; 233 | sourceTree = ""; 234 | }; 235 | 518E699618AC4A8900C57456 = { 236 | isa = PBXGroup; 237 | children = ( 238 | 519AC2B318B4257600F3B4EA /* README.md */, 239 | 518E69A618AC4A8900C57456 /* ACCodeSnippetRepository */, 240 | 5154068618AC4B500065CA33 /* ACCodeSnippetRepository Tests */, 241 | 518E69A118AC4A8900C57456 /* Frameworks */, 242 | 518E69A018AC4A8900C57456 /* Products */, 243 | ); 244 | sourceTree = ""; 245 | }; 246 | 518E69A018AC4A8900C57456 /* Products */ = { 247 | isa = PBXGroup; 248 | children = ( 249 | 518E699F18AC4A8900C57456 /* ACCodeSnippetRepository.xcplugin */, 250 | 5154068318AC4B500065CA33 /* ACCodeSnippetRepository Tests.octest */, 251 | ); 252 | name = Products; 253 | sourceTree = ""; 254 | }; 255 | 518E69A118AC4A8900C57456 /* Frameworks */ = { 256 | isa = PBXGroup; 257 | children = ( 258 | 518E69A218AC4A8900C57456 /* AppKit.framework */, 259 | 518E69A418AC4A8900C57456 /* Foundation.framework */, 260 | 5154068418AC4B500065CA33 /* SenTestingKit.framework */, 261 | ); 262 | name = Frameworks; 263 | sourceTree = ""; 264 | }; 265 | 518E69A618AC4A8900C57456 /* ACCodeSnippetRepository */ = { 266 | isa = PBXGroup; 267 | children = ( 268 | 517D918D18AC4BA700A564B9 /* IDE */, 269 | 51D2D55118AC58FD00493579 /* Categories */, 270 | 517DF2AA18AC4C1A008980B3 /* Classes */, 271 | 5162AC2618AD9FB4000109C9 /* Controllers */, 272 | 515CE9D518B1DCAA000962EA /* Resources */, 273 | 518E69AC18AC4A8900C57456 /* ACCodeSnippetRepositoryPlugin.h */, 274 | 518E69AD18AC4A8900C57456 /* ACCodeSnippetRepositoryPlugin.m */, 275 | 518E69A718AC4A8900C57456 /* Supporting Files */, 276 | ); 277 | path = ACCodeSnippetRepository; 278 | sourceTree = ""; 279 | }; 280 | 518E69A718AC4A8900C57456 /* Supporting Files */ = { 281 | isa = PBXGroup; 282 | children = ( 283 | 518E69A818AC4A8900C57456 /* ACCodeSnippetRepository-Info.plist */, 284 | 518E69A918AC4A8900C57456 /* InfoPlist.strings */, 285 | 518E69AF18AC4A8900C57456 /* ACCodeSnippetRepository-Prefix.pch */, 286 | ); 287 | name = "Supporting Files"; 288 | sourceTree = ""; 289 | }; 290 | 51D2D55118AC58FD00493579 /* Categories */ = { 291 | isa = PBXGroup; 292 | children = ( 293 | 51D2D55218AC58FD00493579 /* NSString+Path.h */, 294 | 51D2D55318AC58FD00493579 /* NSString+Path.m */, 295 | 5105B22518AC59520066728E /* NSTask+Extras.h */, 296 | 5105B22618AC59520066728E /* NSTask+Extras.m */, 297 | 5153BAA718B3406D00C1E75B /* NSDictionary+Merge.h */, 298 | 5153BAA818B3406D00C1E75B /* NSDictionary+Merge.m */, 299 | ); 300 | path = Categories; 301 | sourceTree = ""; 302 | }; 303 | /* End PBXGroup section */ 304 | 305 | /* Begin PBXNativeTarget section */ 306 | 5154068218AC4B500065CA33 /* ACCodeSnippetRepository Tests */ = { 307 | isa = PBXNativeTarget; 308 | buildConfigurationList = 5154069318AC4B500065CA33 /* Build configuration list for PBXNativeTarget "ACCodeSnippetRepository Tests" */; 309 | buildPhases = ( 310 | 5154067F18AC4B500065CA33 /* Sources */, 311 | 5154068018AC4B500065CA33 /* Frameworks */, 312 | 5154068118AC4B500065CA33 /* Resources */, 313 | ); 314 | buildRules = ( 315 | ); 316 | dependencies = ( 317 | 5154069018AC4B500065CA33 /* PBXTargetDependency */, 318 | ); 319 | name = "ACCodeSnippetRepository Tests"; 320 | productName = "ACCodeSnippetRepository Tests"; 321 | productReference = 5154068318AC4B500065CA33 /* ACCodeSnippetRepository Tests.octest */; 322 | productType = "com.apple.product-type.bundle"; 323 | }; 324 | 518E699E18AC4A8900C57456 /* ACCodeSnippetRepository */ = { 325 | isa = PBXNativeTarget; 326 | buildConfigurationList = 518E69B218AC4A8900C57456 /* Build configuration list for PBXNativeTarget "ACCodeSnippetRepository" */; 327 | buildPhases = ( 328 | 518E699B18AC4A8900C57456 /* Sources */, 329 | 518E699C18AC4A8900C57456 /* Frameworks */, 330 | 518E699D18AC4A8900C57456 /* Resources */, 331 | ); 332 | buildRules = ( 333 | ); 334 | dependencies = ( 335 | ); 336 | name = ACCodeSnippetRepository; 337 | productName = ACCodeSnippetRepository; 338 | productReference = 518E699F18AC4A8900C57456 /* ACCodeSnippetRepository.xcplugin */; 339 | productType = "com.apple.product-type.bundle"; 340 | }; 341 | /* End PBXNativeTarget section */ 342 | 343 | /* Begin PBXProject section */ 344 | 518E699718AC4A8900C57456 /* Project object */ = { 345 | isa = PBXProject; 346 | attributes = { 347 | LastUpgradeCheck = 0500; 348 | ORGANIZATIONNAME = "Arnaud Coomans"; 349 | TargetAttributes = { 350 | 5154068218AC4B500065CA33 = { 351 | TestTargetID = 518E699E18AC4A8900C57456; 352 | }; 353 | }; 354 | }; 355 | buildConfigurationList = 518E699A18AC4A8900C57456 /* Build configuration list for PBXProject "ACCodeSnippetRepository" */; 356 | compatibilityVersion = "Xcode 3.2"; 357 | developmentRegion = English; 358 | hasScannedForEncodings = 0; 359 | knownRegions = ( 360 | en, 361 | ); 362 | mainGroup = 518E699618AC4A8900C57456; 363 | productRefGroup = 518E69A018AC4A8900C57456 /* Products */; 364 | projectDirPath = ""; 365 | projectRoot = ""; 366 | targets = ( 367 | 518E699E18AC4A8900C57456 /* ACCodeSnippetRepository */, 368 | 5154068218AC4B500065CA33 /* ACCodeSnippetRepository Tests */, 369 | ); 370 | }; 371 | /* End PBXProject section */ 372 | 373 | /* Begin PBXResourcesBuildPhase section */ 374 | 5154068118AC4B500065CA33 /* Resources */ = { 375 | isa = PBXResourcesBuildPhase; 376 | buildActionMask = 2147483647; 377 | files = ( 378 | 5154068B18AC4B500065CA33 /* InfoPlist.strings in Resources */, 379 | ); 380 | runOnlyForDeploymentPostprocessing = 0; 381 | }; 382 | 518E699D18AC4A8900C57456 /* Resources */ = { 383 | isa = PBXResourcesBuildPhase; 384 | buildActionMask = 2147483647; 385 | files = ( 386 | 515CE9DC18B1DCAA000962EA /* GitHub-Mark-64px.png in Resources */, 387 | 515CE9DB18B1DCAA000962EA /* GitHub-Mark-32px.png in Resources */, 388 | 5162AC2B18AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.xib in Resources */, 389 | 518E69AB18AC4A8900C57456 /* InfoPlist.strings in Resources */, 390 | 515CE9DA18B1DCAA000962EA /* GitHub-Mark-120px-plus.png in Resources */, 391 | ); 392 | runOnlyForDeploymentPostprocessing = 0; 393 | }; 394 | /* End PBXResourcesBuildPhase section */ 395 | 396 | /* Begin PBXSourcesBuildPhase section */ 397 | 5154067F18AC4B500065CA33 /* Sources */ = { 398 | isa = PBXSourcesBuildPhase; 399 | buildActionMask = 2147483647; 400 | files = ( 401 | 51010E0318AC5CB1000AA1F1 /* ACGitRepository.m in Sources */, 402 | 5153BAAC18B3410C00C1E75B /* NSDictionary+MergeTests.m in Sources */, 403 | 517DF2A718AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.m in Sources */, 404 | 517FD2D118AC4C89003E1813 /* ACCodeSnippetSerializationTests.m in Sources */, 405 | 517E12C118AC5F8A0072B743 /* ACCodeSnippetGitDataStore.m in Sources */, 406 | 517FD2CF18AC4C70003E1813 /* ACCodeSnippetSerialization.m in Sources */, 407 | 5105B22818AC59520066728E /* NSTask+Extras.m in Sources */, 408 | 5153BAAA18B3406D00C1E75B /* NSDictionary+Merge.m in Sources */, 409 | 51D2D55518AC590000493579 /* NSString+Path.m in Sources */, 410 | 517DF2A918AC4BF1008980B3 /* Swizzler.m in Sources */, 411 | 5132BF3618AD5EE500C0DE83 /* ACCodeSnippetGitDataStoreTests.m in Sources */, 412 | 5133D0D018AC5CF900998BE2 /* ACGitRepositoryTests.m in Sources */, 413 | ); 414 | runOnlyForDeploymentPostprocessing = 0; 415 | }; 416 | 518E699B18AC4A8900C57456 /* Sources */ = { 417 | isa = PBXSourcesBuildPhase; 418 | buildActionMask = 2147483647; 419 | files = ( 420 | 51010E0218AC5CB1000AA1F1 /* ACGitRepository.m in Sources */, 421 | 518E69AE18AC4A8900C57456 /* ACCodeSnippetRepositoryPlugin.m in Sources */, 422 | 517DF2A618AC4BF1008980B3 /* IDECodeSnippetRepositorySwizzler.m in Sources */, 423 | 5162AC2A18AD9FD0000109C9 /* ACCodeSnippetRepositoryConfigurationWindowController.m in Sources */, 424 | 517E12C018AC5F8A0072B743 /* ACCodeSnippetGitDataStore.m in Sources */, 425 | 5153BAA918B3406D00C1E75B /* NSDictionary+Merge.m in Sources */, 426 | 517DF2A818AC4BF1008980B3 /* Swizzler.m in Sources */, 427 | 517FD2CE18AC4C70003E1813 /* ACCodeSnippetSerialization.m in Sources */, 428 | 5105B22718AC59520066728E /* NSTask+Extras.m in Sources */, 429 | 51D2D55418AC58FD00493579 /* NSString+Path.m in Sources */, 430 | ); 431 | runOnlyForDeploymentPostprocessing = 0; 432 | }; 433 | /* End PBXSourcesBuildPhase section */ 434 | 435 | /* Begin PBXTargetDependency section */ 436 | 5154069018AC4B500065CA33 /* PBXTargetDependency */ = { 437 | isa = PBXTargetDependency; 438 | target = 518E699E18AC4A8900C57456 /* ACCodeSnippetRepository */; 439 | targetProxy = 5154068F18AC4B500065CA33 /* PBXContainerItemProxy */; 440 | }; 441 | /* End PBXTargetDependency section */ 442 | 443 | /* Begin PBXVariantGroup section */ 444 | 5154068918AC4B500065CA33 /* InfoPlist.strings */ = { 445 | isa = PBXVariantGroup; 446 | children = ( 447 | 5154068A18AC4B500065CA33 /* en */, 448 | ); 449 | name = InfoPlist.strings; 450 | sourceTree = ""; 451 | }; 452 | 518E69A918AC4A8900C57456 /* InfoPlist.strings */ = { 453 | isa = PBXVariantGroup; 454 | children = ( 455 | 518E69AA18AC4A8900C57456 /* en */, 456 | ); 457 | name = InfoPlist.strings; 458 | sourceTree = ""; 459 | }; 460 | /* End PBXVariantGroup section */ 461 | 462 | /* Begin XCBuildConfiguration section */ 463 | 5154069118AC4B500065CA33 /* Debug */ = { 464 | isa = XCBuildConfiguration; 465 | buildSettings = { 466 | FRAMEWORK_SEARCH_PATHS = ( 467 | "$(DEVELOPER_FRAMEWORKS_DIR)", 468 | "$(inherited)", 469 | ); 470 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 471 | GCC_PREFIX_HEADER = "ACCodeSnippetRepository Tests/ACCodeSnippetRepository Tests-Prefix.pch"; 472 | GCC_PREPROCESSOR_DEFINITIONS = ( 473 | "DEBUG=1", 474 | "$(inherited)", 475 | ); 476 | INFOPLIST_FILE = "ACCodeSnippetRepository Tests/ACCodeSnippetRepository Tests-Info.plist"; 477 | PRODUCT_NAME = "$(TARGET_NAME)"; 478 | WRAPPER_EXTENSION = octest; 479 | }; 480 | name = Debug; 481 | }; 482 | 5154069218AC4B500065CA33 /* Release */ = { 483 | isa = XCBuildConfiguration; 484 | buildSettings = { 485 | FRAMEWORK_SEARCH_PATHS = ( 486 | "$(DEVELOPER_FRAMEWORKS_DIR)", 487 | "$(inherited)", 488 | ); 489 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 490 | GCC_PREFIX_HEADER = "ACCodeSnippetRepository Tests/ACCodeSnippetRepository Tests-Prefix.pch"; 491 | INFOPLIST_FILE = "ACCodeSnippetRepository Tests/ACCodeSnippetRepository Tests-Info.plist"; 492 | PRODUCT_NAME = "$(TARGET_NAME)"; 493 | WRAPPER_EXTENSION = octest; 494 | }; 495 | name = Release; 496 | }; 497 | 518E69B018AC4A8900C57456 /* Debug */ = { 498 | isa = XCBuildConfiguration; 499 | buildSettings = { 500 | ALWAYS_SEARCH_USER_PATHS = NO; 501 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 502 | CLANG_CXX_LIBRARY = "libc++"; 503 | CLANG_ENABLE_OBJC_ARC = YES; 504 | CLANG_WARN_BOOL_CONVERSION = YES; 505 | CLANG_WARN_CONSTANT_CONVERSION = YES; 506 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 507 | CLANG_WARN_EMPTY_BODY = YES; 508 | CLANG_WARN_ENUM_CONVERSION = YES; 509 | CLANG_WARN_INT_CONVERSION = YES; 510 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 511 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 512 | COPY_PHASE_STRIP = NO; 513 | GCC_C_LANGUAGE_STANDARD = gnu99; 514 | GCC_DYNAMIC_NO_PIC = NO; 515 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 516 | GCC_OPTIMIZATION_LEVEL = 0; 517 | GCC_PREPROCESSOR_DEFINITIONS = ( 518 | "DEBUG=1", 519 | "$(inherited)", 520 | ); 521 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 522 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 523 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 524 | GCC_WARN_UNDECLARED_SELECTOR = YES; 525 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 526 | GCC_WARN_UNUSED_FUNCTION = YES; 527 | GCC_WARN_UNUSED_VARIABLE = YES; 528 | MACOSX_DEPLOYMENT_TARGET = 10.9; 529 | ONLY_ACTIVE_ARCH = YES; 530 | SDKROOT = macosx; 531 | }; 532 | name = Debug; 533 | }; 534 | 518E69B118AC4A8900C57456 /* Release */ = { 535 | isa = XCBuildConfiguration; 536 | buildSettings = { 537 | ALWAYS_SEARCH_USER_PATHS = NO; 538 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 539 | CLANG_CXX_LIBRARY = "libc++"; 540 | CLANG_ENABLE_OBJC_ARC = YES; 541 | CLANG_WARN_BOOL_CONVERSION = YES; 542 | CLANG_WARN_CONSTANT_CONVERSION = YES; 543 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 544 | CLANG_WARN_EMPTY_BODY = YES; 545 | CLANG_WARN_ENUM_CONVERSION = YES; 546 | CLANG_WARN_INT_CONVERSION = YES; 547 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 548 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 549 | COPY_PHASE_STRIP = YES; 550 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 551 | ENABLE_NS_ASSERTIONS = NO; 552 | GCC_C_LANGUAGE_STANDARD = gnu99; 553 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 554 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 555 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 556 | GCC_WARN_UNDECLARED_SELECTOR = YES; 557 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 558 | GCC_WARN_UNUSED_FUNCTION = YES; 559 | GCC_WARN_UNUSED_VARIABLE = YES; 560 | MACOSX_DEPLOYMENT_TARGET = 10.9; 561 | SDKROOT = macosx; 562 | }; 563 | name = Release; 564 | }; 565 | 518E69B318AC4A8900C57456 /* Debug */ = { 566 | isa = XCBuildConfiguration; 567 | buildSettings = { 568 | COMBINE_HIDPI_IMAGES = YES; 569 | DEPLOYMENT_LOCATION = YES; 570 | DSTROOT = "$(HOME)"; 571 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 572 | GCC_PREFIX_HEADER = "ACCodeSnippetRepository/ACCodeSnippetRepository-Prefix.pch"; 573 | INFOPLIST_FILE = "ACCodeSnippetRepository/ACCodeSnippetRepository-Info.plist"; 574 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 575 | OTHER_LDFLAGS = ""; 576 | PRODUCT_NAME = "$(TARGET_NAME)"; 577 | WRAPPER_EXTENSION = xcplugin; 578 | }; 579 | name = Debug; 580 | }; 581 | 518E69B418AC4A8900C57456 /* Release */ = { 582 | isa = XCBuildConfiguration; 583 | buildSettings = { 584 | COMBINE_HIDPI_IMAGES = YES; 585 | DEPLOYMENT_LOCATION = YES; 586 | DSTROOT = "$(HOME)"; 587 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 588 | GCC_PREFIX_HEADER = "ACCodeSnippetRepository/ACCodeSnippetRepository-Prefix.pch"; 589 | INFOPLIST_FILE = "ACCodeSnippetRepository/ACCodeSnippetRepository-Info.plist"; 590 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 591 | OTHER_LDFLAGS = ""; 592 | PRODUCT_NAME = "$(TARGET_NAME)"; 593 | WRAPPER_EXTENSION = xcplugin; 594 | }; 595 | name = Release; 596 | }; 597 | /* End XCBuildConfiguration section */ 598 | 599 | /* Begin XCConfigurationList section */ 600 | 5154069318AC4B500065CA33 /* Build configuration list for PBXNativeTarget "ACCodeSnippetRepository Tests" */ = { 601 | isa = XCConfigurationList; 602 | buildConfigurations = ( 603 | 5154069118AC4B500065CA33 /* Debug */, 604 | 5154069218AC4B500065CA33 /* Release */, 605 | ); 606 | defaultConfigurationIsVisible = 0; 607 | defaultConfigurationName = Release; 608 | }; 609 | 518E699A18AC4A8900C57456 /* Build configuration list for PBXProject "ACCodeSnippetRepository" */ = { 610 | isa = XCConfigurationList; 611 | buildConfigurations = ( 612 | 518E69B018AC4A8900C57456 /* Debug */, 613 | 518E69B118AC4A8900C57456 /* Release */, 614 | ); 615 | defaultConfigurationIsVisible = 0; 616 | defaultConfigurationName = Release; 617 | }; 618 | 518E69B218AC4A8900C57456 /* Build configuration list for PBXNativeTarget "ACCodeSnippetRepository" */ = { 619 | isa = XCConfigurationList; 620 | buildConfigurations = ( 621 | 518E69B318AC4A8900C57456 /* Debug */, 622 | 518E69B418AC4A8900C57456 /* Release */, 623 | ); 624 | defaultConfigurationIsVisible = 0; 625 | defaultConfigurationName = Release; 626 | }; 627 | /* End XCConfigurationList section */ 628 | }; 629 | rootObject = 518E699718AC4A8900C57456 /* Project object */; 630 | } 631 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/ACCodeSnippetRepository-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.acoomans.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DVTPlugInCompatibilityUUIDs 26 | 27 | 640F884E-CE55-4B40-87C0-8869546CAB7A 28 | C4A681B0-4A26-480E-93EC-1218098B9AA0 29 | 37B30044-3B14-46BA-ABAA-F01000C27B63 30 | A2E4D43F-41F4-4FB9-BB94-7177011C9AED 31 | FEC992CC-CA4A-4CFD-8881-77300FCB848A 32 | A16FF353-8441-459E-A50C-B071F53F51B7 33 | 9F75337B-21B4-4ADC-B558-F9CADF7073A7 34 | 35 | NSPrincipalClass 36 | ACCodeSnippetRepositoryPlugin 37 | XC4Compatible 38 | 39 | XCGCReady 40 | 41 | XCPluginHasUI 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/ACCodeSnippetRepository-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/ACCodeSnippetRepositoryPlugin.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetRepositoryPlugin.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 12/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ACCodeSnippetRepositoryConfigurationWindowController.h" 11 | 12 | @interface ACCodeSnippetRepositoryPlugin : NSObject 13 | 14 | @property (nonatomic, strong) NSTimer *updatesTimer; 15 | 16 | @end -------------------------------------------------------------------------------- /ACCodeSnippetRepository/ACCodeSnippetRepositoryPlugin.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetRepositoryPlugin.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 12/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "ACCodeSnippetRepositoryPlugin.h" 10 | 11 | #import "IDE.h" 12 | #import "IDECodeSnippetRepositorySwizzler.h" 13 | #import "ACCodeSnippetGitDataStore.h" 14 | 15 | 16 | static ACCodeSnippetRepositoryPlugin *sharedPlugin; 17 | static NSString * const pluginMenuTitle = @"Plug-ins"; 18 | 19 | @interface ACCodeSnippetRepositoryPlugin() 20 | @property (nonatomic, strong) NSBundle *bundle; 21 | @property (nonatomic, weak) NSMenuItem *updateMenuItem; 22 | @property (nonatomic, strong) ACCodeSnippetRepositoryConfigurationWindowController *configurationWindowController; 23 | @end 24 | 25 | @implementation ACCodeSnippetRepositoryPlugin 26 | 27 | + (void)pluginDidLoad:(NSBundle *)plugin { 28 | static dispatch_once_t onceToken; 29 | NSString *currentApplicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"]; 30 | if ([currentApplicationName isEqual:@"Xcode"]) { 31 | dispatch_once(&onceToken, ^{ 32 | sharedPlugin = [[self alloc] initWithBundle:plugin]; 33 | }); 34 | } 35 | } 36 | 37 | - (id)initWithBundle:(NSBundle *)plugin { 38 | if (self = [super init]) { 39 | 40 | // reference to plugin's bundle, for resource acccess 41 | self.bundle = plugin; 42 | 43 | // add data stores to Xcode's snippet repository 44 | ACCodeSnippetGitDataStore *gitDataStore = [[ACCodeSnippetGitDataStore alloc] init]; 45 | [gitDataStore addObserver:self forKeyPath:@"mainQueue.operationCount" options:0 context:NULL]; 46 | 47 | //TODO: add multiple datastores 48 | IDECodeSnippetRepository *codeSnippetRepository = [NSClassFromString(@"IDECodeSnippetRepository") sharedRepository]; 49 | [codeSnippetRepository addDataStore:gitDataStore]; 50 | [codeSnippetRepository addObserver:self forKeyPath:@"dataStores" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL]; 51 | 52 | // timer for updates 53 | [[NSUserDefaults standardUserDefaults] addObserver:self 54 | forKeyPath:ACCodeSnippetRepositoryUpdateRegularlyKey 55 | options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld 56 | context:NULL]; 57 | if ([[[NSUserDefaults standardUserDefaults] objectForKey:ACCodeSnippetRepositoryUpdateRegularlyKey] integerValue]) { 58 | [self startTimer]; 59 | } 60 | 61 | // Create menu items, initialize UI, etc. 62 | NSMenu *pluginMenu = [self pluginMenu]; 63 | pluginMenu.autoenablesItems = NO; 64 | 65 | if (pluginMenu) { 66 | 67 | NSMenuItem *actionMenuItem = nil; 68 | 69 | self.updateMenuItem = actionMenuItem = [[NSMenuItem alloc] initWithTitle:@"Update snippets" action:@selector(updateAction:) keyEquivalent:@""]; 70 | actionMenuItem.target = self; 71 | [pluginMenu addItem:actionMenuItem]; 72 | 73 | actionMenuItem = [[NSMenuItem alloc] initWithTitle:@"Configure snippets repository" action:@selector(configureAction:) keyEquivalent:@""]; 74 | actionMenuItem.target = self; 75 | [pluginMenu addItem:actionMenuItem]; 76 | 77 | //[pluginMenu addItem:[NSMenuItem separatorItem]]; 78 | } 79 | 80 | } 81 | return self; 82 | } 83 | 84 | - (id)init { 85 | return [self initWithBundle:nil]; 86 | } 87 | 88 | - (void)dealloc { 89 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 90 | } 91 | 92 | 93 | #pragma mark - Menu and actions 94 | 95 | - (NSMenu*)pluginMenu { 96 | NSMenu *pluginMenu = [[[NSApp mainMenu] itemWithTitle:pluginMenuTitle] submenu]; 97 | if (!pluginMenu) { 98 | pluginMenu = [[NSMenu alloc] initWithTitle:pluginMenuTitle]; 99 | 100 | NSMenuItem *pluginMenuItem = [[NSMenuItem alloc] initWithTitle:pluginMenuTitle action:nil keyEquivalent:@""]; 101 | pluginMenuItem.submenu = pluginMenu; 102 | 103 | [[NSApp mainMenu] addItem:pluginMenuItem]; 104 | } 105 | return pluginMenu; 106 | } 107 | 108 | - (void)updateAction:(id)sender { 109 | [self stopTimer]; 110 | [self updateSnippets]; 111 | [self startTimer]; 112 | } 113 | 114 | - (void)updateSnippets { 115 | for (id dataStore in [[NSClassFromString(@"IDECodeSnippetRepository") sharedRepository] dataStores]) { 116 | [dataStore syncCodeSnippets]; 117 | } 118 | } 119 | 120 | - (void)configureAction:(id)sender { 121 | self.configurationWindowController = [[ACCodeSnippetRepositoryConfigurationWindowController alloc] initWithWindowNibName:NSStringFromClass(ACCodeSnippetRepositoryConfigurationWindowController.class)]; 122 | self.configurationWindowController.delegate = self; 123 | self.configurationWindowController.window.delegate = self; 124 | [self.configurationWindowController.window makeKeyWindow]; 125 | } 126 | 127 | 128 | #pragma mark - NSWindowDelegate 129 | 130 | - (void)windowWillClose:(NSNotification *)notification { 131 | 132 | if (notification.object == self.configurationWindowController.window) { 133 | self.configurationWindowController = nil; 134 | } 135 | } 136 | 137 | #pragma mark - NSKeyValueObserving 138 | 139 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 140 | 141 | if ([keyPath isEqualToString:@"mainQueue.operationCount"]) { 142 | 143 | IDECodeSnippetRepository *codeSnippetRepository = [NSClassFromString(@"IDECodeSnippetRepository") sharedRepository]; 144 | 145 | if ([[object valueForKeyPath:keyPath] integerValue] > 0) { 146 | self.updateMenuItem.title = @"Updating snippets..."; 147 | self.updateMenuItem.enabled = NO; 148 | 149 | } else if ([[codeSnippetRepository.dataStores valueForKeyPath:@"@sum.mainQueue.operationCount"] integerValue] == 0) { 150 | self.updateMenuItem.title = @"Update snippets"; 151 | self.updateMenuItem.enabled = YES; 152 | } 153 | 154 | } else if ([keyPath isEqualToString:@"dataStores"]) { 155 | 156 | for (id dataStore in change[NSKeyValueChangeOldKey]) { 157 | [dataStore removeObserver:self forKeyPath:@"mainQueue.operationCount"]; 158 | } 159 | 160 | for (id dataStore in change[NSKeyValueChangeNewKey]) { 161 | [dataStore addObserver:self forKeyPath:@"mainQueue.operationCount" options:0 context:NULL]; 162 | } 163 | 164 | } else if ([keyPath isEqualToString:ACCodeSnippetRepositoryUpdateRegularlyKey]) { 165 | if ( 166 | ([[[NSUserDefaults standardUserDefaults] objectForKey:ACCodeSnippetRepositoryUpdateRegularlyKey] integerValue] == NSOnState) && 167 | ![self.updatesTimer isValid] 168 | ) { 169 | [self startTimer]; 170 | } else { 171 | [self stopTimer]; 172 | } 173 | } 174 | } 175 | 176 | #pragma mark - ACCodeSnippetRepositoryConfigurationWindowControllerDelegate 177 | 178 | - (NSArray*)dataStoresForCodeSnippetConfigurationWindowController:(ACCodeSnippetRepositoryConfigurationWindowController*)configurationWindowController { 179 | return [[NSClassFromString(@"IDECodeSnippetRepository") sharedRepository] dataStores]; 180 | } 181 | 182 | #pragma mark - timer 183 | 184 | - (void)startTimer { 185 | [self.updatesTimer invalidate]; 186 | self.updatesTimer = [NSTimer scheduledTimerWithTimeInterval:60*10 187 | target:self 188 | selector:@selector(updateTimerTicked:) 189 | userInfo:nil 190 | repeats:YES]; 191 | } 192 | 193 | - (void)stopTimer { 194 | [self.updatesTimer invalidate]; 195 | self.updatesTimer = nil; 196 | } 197 | 198 | - (void)updateTimerTicked:(NSTimer*)timer { 199 | [self updateAction:self]; 200 | } 201 | 202 | @end 203 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Categories/NSDictionary+Merge.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Merge.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 17/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (Merge) 12 | 13 | - (NSDictionary*)dictionaryByMergingDictionary:(NSDictionary*)dictionary; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Categories/NSDictionary+Merge.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+Merge.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 17/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+Merge.h" 10 | 11 | @implementation NSDictionary (Merge) 12 | 13 | - (NSDictionary*)dictionaryByMergingDictionary:(NSDictionary*)dictionary { 14 | NSMutableDictionary *result = [self mutableCopy]; 15 | for (id key in [dictionary allKeys]) { 16 | if (!result[key]) { 17 | result[key] = dictionary[key]; 18 | } 19 | } 20 | return [result copy]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Categories/NSString+Path.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Path.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 07/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Path) 12 | 13 | - (NSString *)stringBySanitizingFilename; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Categories/NSString+Path.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Path.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 07/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "NSString+Path.h" 10 | 11 | @implementation NSString (Path) 12 | 13 | - (NSString *)stringBySanitizingFilename { 14 | NSCharacterSet* illegalFileNameCharacters = [NSCharacterSet characterSetWithCharactersInString:@"/\\?%*|\"<>"]; 15 | return [[self componentsSeparatedByCharactersInSet:illegalFileNameCharacters] componentsJoinedByString:@""]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Categories/NSTask+Extras.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTask+Extras.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 09/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSTask (Extras) 12 | 13 | + (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments inCurrentDirectoryPath:(NSString*)directoryPath; 14 | + (NSTask *)launchAndWaitTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments inCurrentDirectoryPath:(NSString*)directoryPath standardOutputAndError:(NSString* __autoreleasing *)output; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Categories/NSTask+Extras.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSTask+Extras.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 09/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "NSTask+Extras.h" 10 | 11 | @implementation NSTask (Extras) 12 | 13 | + (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments inCurrentDirectoryPath:(NSString*)directoryPath { 14 | NSTask *task = [[NSTask alloc] init]; 15 | task.launchPath = path; 16 | task.arguments = arguments; 17 | task.currentDirectoryPath = directoryPath; 18 | [task launch]; 19 | return task; 20 | } 21 | 22 | 23 | + (NSTask *)launchAndWaitTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments inCurrentDirectoryPath:(NSString*)directoryPath standardOutputAndError:(NSString* __autoreleasing *)output { 24 | 25 | NSPipe *pipe = [NSPipe pipe]; 26 | 27 | NSTask *task = [[NSTask alloc] init]; 28 | task.launchPath = path; 29 | task.arguments = arguments; 30 | if (directoryPath) task.currentDirectoryPath = directoryPath; 31 | //task.standardOutput = task.standardError = pipe; //TODO: fix 32 | task.standardOutput = pipe; 33 | [task launch]; 34 | [task waitUntilExit]; 35 | 36 | NSData *data = [[pipe fileHandleForReading] availableData]; 37 | *output = [NSString stringWithFormat:@"$ %@ %@\n %@\n", 38 | task.launchPath, 39 | [task.arguments componentsJoinedByString:@" "], 40 | [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]]; 41 | return task; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Classes/ACGitRepository.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACGitRepository.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString * const ACGitRepositoryFileChangeModifiedKey; 12 | extern NSString * const ACGitRepositoryFileChangeCopiedKey; 13 | extern NSString * const ACGitRepositoryFileChangeRenamedKey; 14 | extern NSString * const ACGitRepositoryFileChangeAddedKey; 15 | extern NSString * const ACGitRepositoryFileChangeDeletedKey; 16 | extern NSString * const ACGitRepositoryFileChangeUnmergedKey; 17 | 18 | 19 | @interface ACGitRepository : NSObject 20 | 21 | @property (nonatomic, copy) NSURL *remoteRepositoryURL; 22 | @property (nonatomic, copy) NSString *localRepositoryPath; 23 | @property (nonatomic, copy) NSString *taskLog; 24 | 25 | - (instancetype)initWithLocalRepositoryDirectory:(NSString*)localRepositoryPath; 26 | 27 | - (BOOL)localRepositoryExists; 28 | 29 | - (void)initializeLocalRepository; 30 | - (void)initializeLocalRepositoryInDirectory:(NSString*)localRepositoryPath; 31 | 32 | - (void)forkRemoteRepositoryWithURL:(NSURL*)remoteRepositoryURL inDirectory:(NSString*)localRepositoryPath; 33 | 34 | - (NSString*)identifierForCurrentCommit; 35 | 36 | - (void)commit; 37 | - (void)commitWithMessage:(NSString*)message; 38 | - (void)fetch; 39 | - (void)pull; 40 | - (void)push; 41 | 42 | - (void)updateLocalWithRemoteRepository; 43 | 44 | - (NSDictionary*)changedFilesSinceCommitWithIdentifier:(NSString*)sinceIdentifier commitWithidentifier:(NSString*)toIdentifier; 45 | - (NSDictionary*)changedFilesSinceCommitWithIdentifier:(NSString*)identifier; 46 | - (NSDictionary*)changedFilesWithOrigin; 47 | 48 | - (void)removeLocalRepository; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Classes/ACGitRepository.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACGitRepository.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "ACGitRepository.h" 10 | #import "NSTask+Extras.h" 11 | 12 | NSString * const ACGitRepositoryFileChangeModifiedKey = @"M"; 13 | NSString * const ACGitRepositoryFileChangeCopiedKey = @"C"; 14 | NSString * const ACGitRepositoryFileChangeRenamedKey = @"R"; 15 | NSString * const ACGitRepositoryFileChangeAddedKey = @"A"; 16 | NSString * const ACGitRepositoryFileChangeDeletedKey = @"D"; 17 | NSString * const ACGitRepositoryFileChangeUnmergedKey = @"U"; 18 | 19 | 20 | @implementation ACGitRepository 21 | 22 | - (instancetype)initWithLocalRepositoryDirectory:(NSString*)localRepositoryPath { 23 | self = [super init]; 24 | if (self) { 25 | self.localRepositoryPath = localRepositoryPath; 26 | } 27 | return self; 28 | } 29 | 30 | - (NSURL*)remoteRepositoryURL { 31 | if (![self localRepositoryExists]) return nil; 32 | 33 | NSPipe *pipe = [NSPipe pipe]; 34 | 35 | NSTask *task = [[NSTask alloc] init]; 36 | task.launchPath = @"/usr/bin/git"; 37 | task.arguments = @[@"remote", @"-v"]; 38 | task.currentDirectoryPath = self.localRepositoryPath; 39 | task.standardOutput = pipe; 40 | [task launch]; 41 | [task waitUntilExit]; 42 | 43 | NSData *data = [[pipe fileHandleForReading] availableData]; 44 | NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 45 | 46 | NSArray *array = [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 47 | if (array.count > 2) { 48 | return [NSURL URLWithString:array[1]]; 49 | } 50 | 51 | return nil; 52 | } 53 | 54 | - (void)setRemoteRepositoryURL:(NSURL *)remoteRepositoryURL { 55 | if (![self localRepositoryExists]) return; 56 | 57 | NSString *output; 58 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 59 | arguments:@[@"remote", @"set-url", @"origin", remoteRepositoryURL.absoluteString] 60 | inCurrentDirectoryPath:self.localRepositoryPath 61 | standardOutputAndError:&output]; 62 | self.taskLog = [self.taskLog stringByAppendingString:output]; 63 | } 64 | 65 | 66 | - (BOOL)localRepositoryExists { 67 | return [[NSFileManager defaultManager] fileExistsAtPath:self.localRepositoryPath]; 68 | } 69 | 70 | - (void)initializeLocalRepository { 71 | [self initializeLocalRepositoryInDirectory:self.localRepositoryPath]; 72 | } 73 | 74 | - (void)initializeLocalRepositoryInDirectory:(NSString*)localRepositoryPath { 75 | if ( 76 | ![[NSFileManager defaultManager] fileExistsAtPath:localRepositoryPath]) { 77 | 78 | NSString *output; 79 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 80 | arguments:@[@"init", localRepositoryPath] 81 | inCurrentDirectoryPath:nil 82 | standardOutputAndError:&output]; 83 | self.taskLog = [self.taskLog stringByAppendingString:output]; 84 | 85 | self.localRepositoryPath = localRepositoryPath; 86 | } 87 | } 88 | 89 | - (void)forkRemoteRepositoryWithURL:(NSURL*)remoteRepositoryURL inDirectory:(NSString*)localRepositoryPath { 90 | if ( 91 | ![[NSFileManager defaultManager] fileExistsAtPath:localRepositoryPath] && 92 | remoteRepositoryURL) { 93 | 94 | NSString *output; 95 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 96 | arguments:@[@"clone", remoteRepositoryURL.absoluteString, localRepositoryPath] 97 | inCurrentDirectoryPath:nil 98 | standardOutputAndError:&output]; 99 | self.taskLog = [self.taskLog stringByAppendingString:output]; 100 | 101 | self.localRepositoryPath = localRepositoryPath; 102 | } 103 | } 104 | 105 | - (NSString*)identifierForCurrentCommit { 106 | if (![self localRepositoryExists]) return nil; 107 | 108 | NSPipe *pipe = [NSPipe pipe]; 109 | 110 | NSTask *task = [[NSTask alloc] init]; 111 | task.launchPath = @"/usr/bin/git"; 112 | task.arguments = @[@"rev-parse", @"HEAD"]; 113 | task.currentDirectoryPath = self.localRepositoryPath; 114 | task.standardOutput = pipe; 115 | [task launch]; 116 | [task waitUntilExit]; 117 | 118 | NSData *data = [[pipe fileHandleForReading] availableData]; 119 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 120 | } 121 | 122 | - (void)commit { 123 | [self commitWithMessage:@""]; 124 | } 125 | 126 | - (void)commitWithMessage:(NSString*)message { 127 | if (![self localRepositoryExists]) return; 128 | 129 | NSString *output; 130 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 131 | arguments:@[@"add", @"--all", @"."] 132 | inCurrentDirectoryPath:self.localRepositoryPath 133 | standardOutputAndError:&output]; 134 | self.taskLog = [self.taskLog stringByAppendingString:output]; 135 | 136 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 137 | arguments:@[@"commit", @"--allow-empty-message", @"-m", message] 138 | inCurrentDirectoryPath:self.localRepositoryPath 139 | standardOutputAndError:&output]; 140 | self.taskLog = [self.taskLog stringByAppendingString:output]; 141 | } 142 | 143 | - (void)fetch { 144 | if (![self localRepositoryExists]) return; 145 | 146 | NSString *output; 147 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 148 | arguments:@[@"fetch", @"origin"] 149 | inCurrentDirectoryPath:self.localRepositoryPath 150 | standardOutputAndError:&output]; 151 | self.taskLog = [self.taskLog stringByAppendingString:output]; 152 | } 153 | 154 | - (void)pull { 155 | if (![self localRepositoryExists]) return; 156 | 157 | NSString *output; 158 | NSTask *task = [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 159 | arguments:@[@"pull", @"-s", @"recursive", @"-X", @"theirs", @"--no-commit"] 160 | inCurrentDirectoryPath:self.localRepositoryPath 161 | standardOutputAndError:&output]; 162 | self.taskLog = [self.taskLog stringByAppendingString:output]; 163 | 164 | if (task.terminationStatus != 0) { 165 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 166 | arguments:@[@"pull", @"-s", @"theirs", @"--no-commit"] 167 | inCurrentDirectoryPath:self.localRepositoryPath 168 | standardOutputAndError:&output]; 169 | self.taskLog = [self.taskLog stringByAppendingString:output]; 170 | } 171 | 172 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 173 | arguments:@[@"commit", @"--allow-empty-message", @"-m", @""] 174 | inCurrentDirectoryPath:self.localRepositoryPath 175 | standardOutputAndError:&output]; 176 | self.taskLog = [self.taskLog stringByAppendingString:output]; 177 | } 178 | 179 | - (void)push { 180 | if (![self localRepositoryExists]) return; 181 | 182 | NSString *output; 183 | [NSTask launchAndWaitTaskWithLaunchPath:@"/usr/bin/git" 184 | arguments:@[@"push"] 185 | inCurrentDirectoryPath:self.localRepositoryPath 186 | standardOutputAndError:&output]; 187 | self.taskLog = [self.taskLog stringByAppendingString:output]; 188 | } 189 | 190 | - (void)updateLocalWithRemoteRepository { 191 | [self commit]; 192 | [self pull]; 193 | [self commit]; 194 | [self push]; 195 | } 196 | 197 | - (NSDictionary*)changedFilesSinceCommitWithIdentifier:(NSString*)identifier { 198 | return [self changedFilesSinceCommitWithIdentifier:identifier commitWithidentifier:@"HEAD"]; 199 | } 200 | 201 | - (NSDictionary*)changedFilesWithOrigin { 202 | return [self changedFilesSinceCommitWithIdentifier:@"HEAD" commitWithidentifier:@"origin"]; 203 | } 204 | 205 | - (NSDictionary*)changedFilesSinceCommitWithIdentifier:(NSString*)sinceIdentifier commitWithidentifier:(NSString*)toIdentifier { 206 | if (![self localRepositoryExists]) return nil; 207 | 208 | NSPipe *pipe = [NSPipe pipe]; 209 | 210 | NSTask *task = [[NSTask alloc] init]; 211 | task.launchPath = @"/usr/bin/git"; 212 | task.arguments = @[@"diff", @"--name-status", sinceIdentifier, toIdentifier]; 213 | task.currentDirectoryPath = self.localRepositoryPath; 214 | task.standardOutput = pipe; 215 | [task launch]; 216 | [task waitUntilExit]; 217 | 218 | NSData *data = [[pipe fileHandleForReading] availableData]; 219 | NSString *output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 220 | 221 | __block NSMutableDictionary *dictionary = [@{} mutableCopy]; 222 | 223 | [output enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) { 224 | NSError *error; 225 | NSString *pattern = @"(.?)\\s+(.*)"; 226 | __block NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern 227 | options:NSRegularExpressionCaseInsensitive 228 | error:&error]; 229 | [line enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) { 230 | 231 | [regex enumerateMatchesInString:line 232 | options:0 233 | range:NSMakeRange(0, line.length) 234 | usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 235 | 236 | NSString *key = [line substringWithRange:[result rangeAtIndex:1]]; 237 | NSString *value = [line substringWithRange:[result rangeAtIndex:2]]; 238 | 239 | NSMutableArray *files = dictionary[key]; 240 | if (!files) { 241 | dictionary[key] = files = [@[] mutableCopy]; 242 | } 243 | 244 | [files addObject:value]; 245 | 246 | }]; 247 | }]; 248 | }]; 249 | return dictionary; 250 | } 251 | 252 | - (void)removeLocalRepository { 253 | if (![self localRepositoryExists]) return; 254 | 255 | NSError *error; 256 | [[NSFileManager defaultManager] removeItemAtPath:self.localRepositoryPath error:&error]; 257 | } 258 | 259 | @end 260 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Classes/DataStores/ACCodeSnippetDataStoreProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetDataStoreProtocol.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 12/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "IDE.h" 11 | 12 | @protocol ACCodeSnippetDataStoreProtocol 13 | 14 | - (NSOperationQueue*)mainQueue; 15 | 16 | - (void)addCodeSnippet:(IDECodeSnippet*)snippet; 17 | - (void)removeCodeSnippet:(IDECodeSnippet*)snippet; 18 | 19 | - (void)syncCodeSnippets; 20 | 21 | - (void)importAllCodeSnippets; 22 | - (void)exportAllCodeSnippets; 23 | - (void)removeAllCodeSnippets; 24 | 25 | 26 | @optional 27 | - (void)dataStoreWillAdd; 28 | - (void)dataStoreDidAdd; 29 | - (void)dataStoreWillRemove; 30 | - (void)dataStoreDidRemove; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Classes/DataStores/ACCodeSnippetGitDataStore.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetGitDataStore.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 12/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ACCodeSnippetDataStoreProtocol.h" 11 | #import "ACGitRepository.h" 12 | 13 | @interface ACCodeSnippetGitDataStore : NSObject 14 | 15 | @property (nonatomic, strong) ACGitRepository *gitRepository; 16 | @property (nonatomic, strong) NSOperationQueue *mainQueue; 17 | @property (nonatomic, strong, readonly) NSString *localRepositoryPath; 18 | @property (nonatomic, copy) NSURL *remoteRepositoryURL; 19 | 20 | - (id)initWithGitRepository:(ACGitRepository*)gitRepository; 21 | - (id)initWithRemoteRepositoryURL:(NSURL*)remoteRepositoryURL; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Classes/DataStores/ACCodeSnippetGitDataStore.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetGitDataStore.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 12/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "ACCodeSnippetGitDataStore.h" 10 | #import "ACCodeSnippetSerialization.h" 11 | #import "NSString+Path.h" 12 | #import "IDECodeSnippetRepositorySwizzler.h" 13 | #import "NSDictionary+Merge.h" 14 | 15 | @implementation ACCodeSnippetGitDataStore 16 | 17 | - (instancetype)init { 18 | return [self initWithRemoteRepositoryURL:nil]; 19 | } 20 | 21 | - (id)initWithRemoteRepositoryURL:(NSURL*)remoteRepositoryURL { 22 | ACGitRepository *gitRepository = [[ACGitRepository alloc] initWithLocalRepositoryDirectory:self.localRepositoryPath]; 23 | if (remoteRepositoryURL && !gitRepository.localRepositoryExists) { 24 | [gitRepository forkRemoteRepositoryWithURL:remoteRepositoryURL inDirectory:self.localRepositoryPath]; 25 | } 26 | return [self initWithGitRepository:gitRepository]; 27 | } 28 | 29 | - (id)initWithGitRepository:(ACGitRepository*)gitRepository { 30 | self = [super init]; 31 | if (self) { 32 | self.mainQueue = [[NSOperationQueue alloc] init]; 33 | self.mainQueue.maxConcurrentOperationCount = 1; 34 | self.gitRepository = gitRepository; 35 | } 36 | return self; 37 | } 38 | 39 | 40 | #pragma mark - Properties 41 | 42 | - (void)setGitRepository:(ACGitRepository *)gitRepository { 43 | _gitRepository = gitRepository; 44 | gitRepository.localRepositoryPath = self.localRepositoryPath; 45 | } 46 | 47 | - (NSURL*)remoteRepositoryURL { 48 | return self.gitRepository.remoteRepositoryURL; 49 | } 50 | 51 | - (void)setRemoteRepositoryURL:(NSURL *)remoteRepositoryURL { 52 | self.gitRepository.remoteRepositoryURL = remoteRepositoryURL; 53 | } 54 | 55 | 56 | #pragma mark - ACCodeSnippetDataStoreProtocol 57 | 58 | - (void)dataStoreWillAdd { 59 | NSLog(@"%@ dataStoreWillAdd", self); 60 | if (![self.gitRepository localRepositoryExists]) { 61 | [self.gitRepository forkRemoteRepositoryWithURL:self.remoteRepositoryURL inDirectory:self.localRepositoryPath]; 62 | } 63 | } 64 | 65 | - (void)dataStoreDidAdd { 66 | NSLog(@"%@ dataStoreDidAdd", self); 67 | } 68 | 69 | - (void)dataStoreWillRemove { 70 | NSLog(@"%@ dataStoreWillRemove", self); 71 | [self.mainQueue waitUntilAllOperationsAreFinished]; 72 | } 73 | 74 | - (void)dataStoreDidRemove { 75 | NSLog(@"%@ dataStoreDidRemove", self); 76 | } 77 | 78 | 79 | - (void)addCodeSnippet:(IDECodeSnippet*)snippet { 80 | if (!self.gitRepository) return; 81 | 82 | __block IDECodeSnippet *blockSnippet = snippet; 83 | __weak typeof(self)weakSelf = self; 84 | 85 | NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ 86 | 87 | NSLog(@"%@ addCodeSnippet: %@", weakSelf, snippet); 88 | 89 | if (![blockSnippet.title isEqualToString:@"My Code Snippet"]) { 90 | //[weakSelf removeAllFilesInLocalRepositoryForSnippet:blockSnippet]; 91 | [weakSelf addFileInLocalRepositoryForSnippet:blockSnippet overwrite:YES]; 92 | [weakSelf.gitRepository commit]; 93 | [weakSelf.gitRepository push]; 94 | } 95 | }]; 96 | [self.mainQueue addOperation:blockOperation]; 97 | 98 | } 99 | 100 | - (void)removeCodeSnippet:(IDECodeSnippet*)snippet { 101 | if (!self.gitRepository) return; 102 | 103 | __block IDECodeSnippet *blockSnippet = snippet; 104 | __weak typeof(self)weakSelf = self; 105 | 106 | NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ 107 | 108 | NSLog(@"%@ removeCodeSnippet: %@", weakSelf, snippet); 109 | 110 | [weakSelf removeAllFilesInLocalRepositoryForSnippet:blockSnippet]; 111 | [weakSelf.gitRepository commit]; 112 | [weakSelf.gitRepository push]; 113 | }]; 114 | [self.mainQueue addOperation:blockOperation]; 115 | } 116 | 117 | - (void)syncCodeSnippets { 118 | if (!self.gitRepository) return; 119 | 120 | __weak typeof(self)weakSelf = self; 121 | 122 | NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ 123 | 124 | NSLog(@"%@ updateCodeSnippets", weakSelf); 125 | 126 | [weakSelf.gitRepository fetch]; 127 | 128 | NSMutableDictionary *changes = [[weakSelf.gitRepository changedFilesWithOrigin] mutableCopy]; 129 | 130 | [weakSelf removeSnippetsForFilesInLocalRepository:changes[ACGitRepositoryFileChangeDeletedKey]]; 131 | [weakSelf removeSnippetsForFilesInLocalRepository:changes[ACGitRepositoryFileChangeModifiedKey]]; 132 | 133 | [weakSelf.gitRepository pull]; 134 | 135 | [weakSelf updateSnippetsForFilesInLocalRepository:changes[ACGitRepositoryFileChangeAddedKey]]; 136 | [weakSelf updateSnippetsForFilesInLocalRepository:changes[ACGitRepositoryFileChangeModifiedKey]]; 137 | 138 | [weakSelf.gitRepository commit]; 139 | [weakSelf.gitRepository push]; 140 | }]; 141 | [self.mainQueue addOperation:blockOperation]; 142 | } 143 | 144 | - (void)importAllCodeSnippets { 145 | 146 | NSLog(@"%@ importCodeSnippets", self); 147 | 148 | NSError *error = nil; 149 | NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.localRepositoryPath 150 | error:&error]; 151 | [self updateSnippetsForFilesInLocalRepository:filenames]; 152 | } 153 | 154 | - (void)exportAllCodeSnippets { 155 | NSLog(@"%@ exportAllCodeSnippets", self); 156 | 157 | IDECodeSnippetRepository *codeSnippetRepository = [NSClassFromString(@"IDECodeSnippetRepository") sharedRepository]; 158 | for (IDECodeSnippet *snippet in codeSnippetRepository.codeSnippets) { 159 | [self addFileInLocalRepositoryForSnippet:snippet overwrite:NO]; 160 | } 161 | [self.gitRepository commitWithMessage:@"Imported user code snippets"]; 162 | [self.gitRepository push]; 163 | } 164 | 165 | - (void)removeAllCodeSnippets { 166 | 167 | NSLog(@"%@ removeAllCodeSnippets", self); 168 | 169 | NSError *error = nil; 170 | NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.localRepositoryPath 171 | error:&error]; 172 | [self removeSnippetsForFilesInLocalRepository:filenames]; 173 | } 174 | 175 | 176 | 177 | #pragma mark - File operations 178 | 179 | - (BOOL)addFileInLocalRepositoryForSnippet:(IDECodeSnippet*)snippet overwrite:(BOOL)overwrite { 180 | 181 | NSLog(@"%@ addFileInLocalRepositoryForSnippet: %@", self, snippet); 182 | 183 | NSData *data = [ACCodeSnippetSerialization dataWithDictionary:[snippet dictionaryRepresentation] 184 | format:0 185 | options:0 186 | error:nil]; 187 | 188 | NSString *filename = [self fileInLocalRepositoryForSnippet:snippet]; 189 | if (!filename) { 190 | filename = [[[[snippet.title lowercaseString] stringByAppendingString:@".m"] stringByReplacingOccurrencesOfString:@" " withString:@"_"] stringBySanitizingFilename]; 191 | } 192 | 193 | NSString *path = [NSString pathWithComponents:@[self.localRepositoryPath, filename]]; 194 | 195 | if (overwrite || ![[NSFileManager defaultManager] fileExistsAtPath:path]) { 196 | [data writeToFile:path atomically:YES]; 197 | return YES; 198 | } 199 | return NO; 200 | } 201 | 202 | - (void)removeAllFilesInLocalRepositoryForSnippet:(IDECodeSnippet*)snippet { 203 | 204 | NSLog(@"%@ removeAllFilesInLocalRepositoryForSnippet: %@", self, snippet); 205 | 206 | NSError *error = nil; 207 | for (NSString *filename in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.localRepositoryPath 208 | error:&error]) { 209 | 210 | NSString *path = [self.localRepositoryPath stringByAppendingPathComponent:filename]; 211 | 212 | if ([self isSnippetFileAtPath:path]) { 213 | 214 | NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; 215 | if ([s rangeOfString:snippet.identifier].location != NSNotFound) { 216 | [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; 217 | } 218 | } 219 | } 220 | } 221 | 222 | - (NSString*)fileInLocalRepositoryForSnippet:(IDECodeSnippet*)snippet { 223 | 224 | NSError *error = nil; 225 | for (NSString *filename in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.localRepositoryPath 226 | error:&error]) { 227 | 228 | NSString *path = [self.localRepositoryPath stringByAppendingPathComponent:filename]; 229 | 230 | if ([self isSnippetFileAtPath:path]) { 231 | 232 | NSString *s = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; 233 | if ([s rangeOfString:snippet.identifier].location != NSNotFound) { 234 | return filename; 235 | } 236 | } 237 | } 238 | return nil; 239 | } 240 | 241 | 242 | #pragma mark - Snippet operations 243 | 244 | - (void)updateSnippetsForFilesInLocalRepository:(NSArray*)array { 245 | 246 | NSLog(@"%@ updateSnippetsForFilesInLocalRepository: %@", self, array); 247 | 248 | NSError *error; 249 | 250 | for (NSString *filename in array) { 251 | 252 | NSString *path = [self.localRepositoryPath stringByAppendingPathComponent:filename]; 253 | 254 | if ([self isSnippetFileAtPath:path]) { 255 | 256 | NSData *data = [NSData dataWithContentsOfFile:path]; 257 | NSDictionary *dict = [ACCodeSnippetSerialization dictionaryWithData:data options:0 format:0 error:&error]; 258 | 259 | dict = [dict dictionaryByMergingDictionary:@{ 260 | ACCodeSnippetTitleKey: [filename stringByDeletingPathExtension], 261 | ACCodeSnippetIdentifierKey: [ACCodeSnippetSerialization identifier], 262 | ACCodeSnippetUserSnippetKey: @(YES), 263 | ACCodeSnippetLanguageKey: ACCodeSnippetLanguageObjectiveC, 264 | }]; 265 | 266 | __block IDECodeSnippet *snippet = [[NSClassFromString(@"IDECodeSnippet") alloc] initWithDictionaryRepresentation:dict]; 267 | 268 | dispatch_async(dispatch_get_main_queue(), ^{ 269 | 270 | IDECodeSnippetRepository *repository = [NSClassFromString(@"IDECodeSnippetRepository") sharedRepository]; 271 | [repository override_saveUserCodeSnippetToDisk:snippet]; 272 | 273 | if (![repository codeSnippetForIdentifier:snippet.identifier]) { 274 | [repository addCodeSnippet:snippet]; 275 | } 276 | 277 | NSData *data = [ACCodeSnippetSerialization dataWithDictionary:dict 278 | format:0 279 | options:0 280 | error:nil]; 281 | [data writeToFile:path atomically:YES]; 282 | }); 283 | } 284 | } 285 | } 286 | 287 | - (void)removeSnippetsForFilesInLocalRepository:(NSArray*)array { 288 | 289 | NSLog(@"%@ removeSnippetsForFilesInLocalRepository: %@", self, array); 290 | 291 | NSError *error; 292 | 293 | for (NSString *filename in array) { 294 | 295 | NSString *path = [self.localRepositoryPath stringByAppendingPathComponent:filename]; 296 | 297 | if ([self isSnippetFileAtPath:path]) { 298 | 299 | NSData *data = [NSData dataWithContentsOfFile:path]; 300 | NSDictionary *dict = [ACCodeSnippetSerialization dictionaryWithData:data options:0 format:0 error:&error]; 301 | 302 | if (dict[ACCodeSnippetIdentifierKey]) { 303 | 304 | // be sure to remove the snippet actually in the repository 305 | __block IDECodeSnippet *snippet = [[NSClassFromString(@"IDECodeSnippetRepository") sharedRepository] codeSnippetForIdentifier:dict[ACCodeSnippetIdentifierKey]]; 306 | 307 | if (snippet) { 308 | dispatch_async(dispatch_get_main_queue(), ^{ 309 | [[NSClassFromString(@"IDECodeSnippetRepository") sharedRepository] removeCodeSnippet:snippet]; 310 | }); 311 | } 312 | } 313 | 314 | } 315 | } 316 | } 317 | 318 | #pragma mark - path and files 319 | 320 | - (NSString*)pathForSnippetDirectory { 321 | NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject]; 322 | return [NSString pathWithComponents:@[libraryPath, @"Developer", @"Xcode", @"UserData", @"CodeSnippets"]]; 323 | } 324 | 325 | - (NSString*)localRepositoryPath { 326 | return [NSString pathWithComponents:@[self.pathForSnippetDirectory, @"git"]]; 327 | } 328 | 329 | - (BOOL)isSnippetFileAtPath:(NSString*)path { 330 | 331 | NSString *filename = [path lastPathComponent]; 332 | 333 | BOOL isDirectory; 334 | BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory]; 335 | 336 | return ( 337 | exists && 338 | !isDirectory && 339 | ![filename hasPrefix:@"."] && 340 | ( 341 | [filename hasSuffix:@".c"] || 342 | [filename hasSuffix:@".m"] || 343 | [filename hasSuffix:@".h"] || 344 | [filename hasSuffix:@".cpp"] || 345 | [filename hasSuffix:@".s"] 346 | ) 347 | ); 348 | } 349 | 350 | #pragma mark - description 351 | 352 | - (NSString*)description { 353 | return [NSString stringWithFormat:@"%@ (%@)", [super description], self.remoteRepositoryURL]; 354 | } 355 | 356 | @end 357 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Classes/Serialization/ACCodeSnippetSerialization.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetSerialization.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString * const ACCodeSnippetIdentifierKey; 12 | extern NSString * const ACCodeSnippetTitleKey; 13 | extern NSString * const ACCodeSnippetSummaryKey; 14 | extern NSString * const ACCodeSnippetContentsKey; 15 | extern NSString * const ACCodeSnippetUserSnippetKey; 16 | extern NSString * const ACCodeSnippetLanguageKey; 17 | 18 | extern NSString * const ACCodeSnippetLanguageObjectiveC; 19 | 20 | 21 | typedef NS_ENUM(NSUInteger, ACCodeSnippetSerializationFormat) { 22 | ACCodeSnippetSerializationFormatC 23 | }; 24 | 25 | typedef NSUInteger ACCodeSnippetSerializationWriteOptions; 26 | typedef NSUInteger ACCodeSnippetSerializationReadOptions; 27 | 28 | 29 | @interface ACCodeSnippetSerialization : NSObject 30 | 31 | + (NSData *)dataWithDictionary:(NSDictionary*)dict 32 | format:(ACCodeSnippetSerializationFormat)format 33 | options:(ACCodeSnippetSerializationWriteOptions)opt 34 | error:(NSError**)error; 35 | 36 | + (id)dictionaryWithData:(NSData*)data 37 | options:(ACCodeSnippetSerializationReadOptions)opt 38 | format:(ACCodeSnippetSerializationFormat)format 39 | error:(NSError**)error; 40 | 41 | + (NSString*)identifier; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Classes/Serialization/ACCodeSnippetSerialization.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetSerialization.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "ACCodeSnippetSerialization.h" 10 | 11 | NSString * const ACCodeSnippetIdentifierKey = @"IDECodeSnippetIdentifier"; 12 | NSString * const ACCodeSnippetTitleKey = @"IDECodeSnippetTitle"; 13 | NSString * const ACCodeSnippetSummaryKey = @"IDECodeSnippetSummary"; 14 | NSString * const ACCodeSnippetContentsKey = @"IDECodeSnippetContents"; 15 | NSString * const ACCodeSnippetUserSnippetKey = @"IDECodeSnippetUserSnippet"; 16 | NSString * const ACCodeSnippetLanguageKey = @"IDECodeSnippetLanguage"; 17 | 18 | NSString * const ACCodeSnippetLanguageObjectiveC = @"Xcode.SourceCodeLanguage.Objective-C"; 19 | 20 | 21 | @implementation ACCodeSnippetSerialization 22 | 23 | 24 | + (NSData *)dataWithDictionary:(NSDictionary*)dict 25 | format:(ACCodeSnippetSerializationFormat)format 26 | options:(ACCodeSnippetSerializationWriteOptions)opt 27 | error:(NSError**)error { 28 | 29 | NSString *title = dict[ACCodeSnippetTitleKey]; 30 | NSString *summary = dict[ACCodeSnippetSummaryKey]; 31 | NSString *contents = dict[ACCodeSnippetContentsKey]; 32 | 33 | NSMutableDictionary *mutableDictionary = [dict mutableCopy]; 34 | [mutableDictionary removeObjectsForKeys:@[ACCodeSnippetTitleKey, ACCodeSnippetSummaryKey, ACCodeSnippetContentsKey]]; 35 | dict = mutableDictionary; 36 | 37 | NSMutableString *string = [@"" mutableCopy]; 38 | 39 | [string appendFormat:@"// %@\n", (title?:@"")]; 40 | [string appendFormat:@"// %@\n", (summary?:@"")]; 41 | [string appendString:@"//\n"]; 42 | 43 | for (NSString *key in [[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]) { 44 | 45 | id value = dict[key]; 46 | 47 | if ([value isKindOfClass:NSArray.class]) { 48 | value = [NSString stringWithFormat:@"[%@]", [value componentsJoinedByString:@","]]; 49 | } 50 | [string appendFormat:@"// %@: %@\n", key, value]; 51 | } 52 | 53 | [string appendString:(contents?:@"")]; 54 | 55 | return [string dataUsingEncoding:NSUTF8StringEncoding]; 56 | } 57 | 58 | 59 | + (id)dictionaryWithData:(NSData*)data 60 | options:(ACCodeSnippetSerializationReadOptions)opt 61 | format:(ACCodeSnippetSerializationFormat)format 62 | error:(NSError**)error { 63 | 64 | NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 65 | 66 | NSMutableDictionary *dict = [@{} mutableCopy]; 67 | 68 | __block BOOL isParsingHeader = YES; 69 | __block NSString *contents = @""; 70 | 71 | NSString *pattern = @"//\\s*(\\w*)\\s*:\\s*(.*)"; 72 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern 73 | options:NSRegularExpressionCaseInsensitive 74 | error:error]; 75 | __block int i = 0; 76 | [string enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) { 77 | 78 | if (![line hasPrefix:@"//"]) { 79 | isParsingHeader = NO; 80 | } 81 | 82 | if (isParsingHeader) { 83 | __block NSString *key = nil; 84 | __block id value = nil; 85 | [regex enumerateMatchesInString:line 86 | options:0 87 | range:NSMakeRange(0, line.length) 88 | usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { 89 | 90 | key = [line substringWithRange:[result rangeAtIndex:1]]; 91 | value = [[line substringWithRange:[result rangeAtIndex:2]] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 92 | 93 | if ([value hasPrefix:@"["] && [value hasSuffix:@"]"]) { 94 | value = [[value substringWithRange:NSMakeRange(1, [value length]-2)] componentsSeparatedByString:@","]; 95 | } 96 | 97 | if ([@"title|name" rangeOfString:[key lowercaseString]].location != NSNotFound) { 98 | key = ACCodeSnippetTitleKey; 99 | } 100 | 101 | if ([@"description|summary" rangeOfString:[key lowercaseString]].location != NSNotFound) { 102 | key = ACCodeSnippetSummaryKey; 103 | } 104 | 105 | dict[key] = value; 106 | }]; 107 | 108 | if (!key && !value) { 109 | if (i < 2) { 110 | value = [[line substringWithRange:NSMakeRange(2, line.length-2)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 111 | if (i == 0) { 112 | dict[ACCodeSnippetTitleKey] = value; 113 | } 114 | if (i == 1) { 115 | dict[ACCodeSnippetSummaryKey] = value; 116 | } 117 | } 118 | } 119 | 120 | } else { 121 | contents = [contents stringByAppendingFormat:@"%@\n", line]; //stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 122 | } 123 | 124 | i++; 125 | }]; 126 | 127 | dict[ACCodeSnippetContentsKey] = contents; 128 | 129 | return [dict copy]; 130 | } 131 | 132 | #pragma mark - 133 | 134 | + (NSString*)identifier { 135 | CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault); 136 | CFStringRef strRef = CFUUIDCreateString(kCFAllocatorDefault, uuidRef); 137 | NSString *uuidString = [NSString stringWithString:(__bridge NSString*)strRef]; 138 | CFRelease(strRef); 139 | CFRelease(uuidRef); 140 | return uuidString; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Controllers/ACCodeSnippetRepositoryConfigurationWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetRepositoryConfigurationWindowController.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 06/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | extern NSString * const ACCodeSnippetRepositoryUpdateRegularlyKey; 13 | 14 | 15 | @class ACCodeSnippetRepositoryConfigurationWindowController; 16 | 17 | @protocol ACCodeSnippetRepositoryConfigurationWindowControllerDelegate 18 | - (NSArray*)dataStoresForCodeSnippetConfigurationWindowController:(ACCodeSnippetRepositoryConfigurationWindowController*)configurationWindowController; 19 | @end 20 | 21 | 22 | @interface ACCodeSnippetRepositoryConfigurationWindowController : NSWindowController 23 | 24 | @property (nonatomic, weak) id delegate; 25 | 26 | @property (nonatomic, weak) IBOutlet NSTextField *remoteRepositoryTextfield; 27 | @property (nonatomic, weak) IBOutlet NSButton *forkRemoteRepositoryButton; 28 | @property (nonatomic, weak) IBOutlet NSButton *importButton; 29 | 30 | @property (nonatomic, weak) IBOutlet NSPanel *progressPanel; 31 | @property (nonatomic, weak) IBOutlet NSProgressIndicator *progressIndicator; 32 | 33 | @property (nonatomic, weak) IBOutlet NSButton *updateRegularlyCheckbox; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Controllers/ACCodeSnippetRepositoryConfigurationWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACCodeSnippetRepositoryConfigurationWindowController.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 06/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "ACCodeSnippetRepositoryConfigurationWindowController.h" 10 | #import "ACCodeSnippetGitDataStore.h" 11 | #import "IDECodeSnippetRepositorySwizzler.h" 12 | #import "ACCodeSnippetGitDataStore.h" 13 | 14 | 15 | NSString * const ACCodeSnippetRepositoryUpdateRegularlyKey = @"ACCodeSnippetRepositoryUpdateRegularlyKey"; 16 | 17 | 18 | @interface ACCodeSnippetRepositoryConfigurationWindowController () 19 | @property (nonatomic, strong) NSURL *snippetRemoteRepositoryURL; 20 | @end 21 | 22 | @implementation ACCodeSnippetRepositoryConfigurationWindowController 23 | 24 | #pragma mark - Initialization 25 | 26 | 27 | - (id)initWithWindow:(NSWindow *)window { 28 | self = [super initWithWindow:window]; 29 | if (self) { 30 | // Initialization code here. 31 | } 32 | return self; 33 | } 34 | 35 | - (void)windowDidLoad { 36 | [super windowDidLoad]; 37 | self.remoteRepositoryTextfield.stringValue = self.gitDataStore.remoteRepositoryURL.absoluteString?:@""; 38 | 39 | self.updateRegularlyCheckbox.state = [[[NSUserDefaults standardUserDefaults] objectForKey:ACCodeSnippetRepositoryUpdateRegularlyKey] integerValue]; 40 | } 41 | 42 | - (ACCodeSnippetGitDataStore*)gitDataStore { 43 | if ([self.delegate respondsToSelector:@selector(dataStoresForCodeSnippetConfigurationWindowController:)]) { 44 | NSArray *dataStores = [self.delegate dataStoresForCodeSnippetConfigurationWindowController:self]; 45 | for (id dataStore in dataStores) { 46 | if ([dataStore isKindOfClass:ACCodeSnippetGitDataStore.class]) { 47 | return dataStore; 48 | } 49 | break; 50 | } 51 | } 52 | return nil; 53 | } 54 | 55 | #pragma mark - NSTextFieldDelegate 56 | 57 | - (void)controlTextDidChange:(NSNotification *)notification { 58 | NSTextField *textField = [notification object]; 59 | 60 | if (![[NSURL URLWithString:textField.stringValue] isEqualTo:self.gitDataStore.remoteRepositoryURL]) { 61 | self.forkRemoteRepositoryButton.enabled = YES; 62 | } else { 63 | self.forkRemoteRepositoryButton.enabled = NO; 64 | } 65 | 66 | if ([textField.stringValue length]) { 67 | self.importButton.enabled = YES; 68 | } else { 69 | self.importButton.enabled = NO; 70 | } 71 | } 72 | 73 | #pragma mark - Actions 74 | 75 | - (IBAction)updateCheckboxAction:(NSButton*)button { 76 | [[NSUserDefaults standardUserDefaults] setObject:@(button.state) forKey:ACCodeSnippetRepositoryUpdateRegularlyKey]; 77 | } 78 | 79 | 80 | - (IBAction)forkRemoteRepositoryAction:(id)sender { 81 | 82 | NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:@"Do you want to fork %@?", self.remoteRepositoryTextfield.stringValue] 83 | defaultButton:@"Fork" 84 | alternateButton:@"Cancel" 85 | otherButton:nil 86 | informativeTextWithFormat:@"This will remove all snippets from the current git repository and replace them with snippets from the new fork."]; 87 | 88 | __weak typeof(self)weakSelf = self; 89 | [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) { 90 | switch (returnCode) { 91 | 92 | case NSModalResponseCancel: { 93 | // nothing 94 | break; 95 | } 96 | 97 | case NSModalResponseOK: { 98 | 99 | __block ACCodeSnippetGitDataStore *dataStore = weakSelf.gitDataStore; 100 | 101 | [weakSelf.window beginSheet:weakSelf.progressPanel completionHandler:nil]; 102 | [weakSelf.progressIndicator startAnimation:weakSelf]; 103 | 104 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 105 | 106 | NSLog(@"----- backup"); 107 | [weakSelf backupUserSnippets]; 108 | 109 | NSLog(@"----- remove"); 110 | [[NSClassFromString(@"IDECodeSnippetRepository") sharedRepository] removeDataStore:dataStore]; 111 | [dataStore removeAllCodeSnippets]; 112 | [dataStore.gitRepository removeLocalRepository]; 113 | 114 | NSLog(@"----- add"); 115 | ACCodeSnippetGitDataStore *dataStore = [[ACCodeSnippetGitDataStore alloc] initWithRemoteRepositoryURL:[NSURL URLWithString:weakSelf.remoteRepositoryTextfield.stringValue]]; 116 | [[NSClassFromString(@"IDECodeSnippetRepository") sharedRepository] addDataStore:dataStore]; 117 | [dataStore importAllCodeSnippets]; 118 | 119 | dispatch_async(dispatch_get_main_queue(), ^{ 120 | [weakSelf.window endSheet:weakSelf.progressPanel]; 121 | [weakSelf.progressIndicator stopAnimation:weakSelf]; 122 | }); 123 | 124 | [weakSelf importUserSnippetsAction:weakSelf]; 125 | }); 126 | 127 | break; 128 | } 129 | 130 | default: 131 | break; 132 | } 133 | }]; 134 | } 135 | 136 | - (IBAction)openUserSnippetsDirectoryAction:(id)sender { 137 | [[NSWorkspace sharedWorkspace] openFile:[self pathForSnippetDirectory]]; 138 | } 139 | 140 | - (IBAction)backupUserSnippetsAction:(id)sender { 141 | NSLog(@"backupUserSnippetsAction"); 142 | [self backupUserSnippets]; 143 | } 144 | 145 | - (void)backupUserSnippets { 146 | NSError *error; 147 | if ([[NSFileManager defaultManager] createDirectoryAtPath:self.pathForBackupDirectory withIntermediateDirectories:YES attributes:nil error:&error]) { 148 | for (NSString *filename in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.pathForSnippetDirectory error:&error]) { 149 | if ([filename hasSuffix:@".codesnippet"]) { 150 | NSString *path = [NSString pathWithComponents:@[self.pathForSnippetDirectory, filename]]; 151 | NSString *toPath = [NSString pathWithComponents:@[self.pathForBackupDirectory, filename]]; 152 | [[NSFileManager defaultManager] copyItemAtPath:path toPath:toPath error:&error]; 153 | } 154 | } 155 | } 156 | } 157 | 158 | - (IBAction)importUserSnippetsAction:(id)sender { 159 | NSAlert *alert = [NSAlert alertWithMessageText:@"Do you want to import your existing user code snippets in the repository?" 160 | defaultButton:@"Import" 161 | alternateButton:@"Cancel" 162 | otherButton:nil 163 | informativeTextWithFormat:@"This will import all your user code snippets in the current git repository. System code snippets will not be imported."]; 164 | 165 | __weak typeof(self)weakSelf = self; 166 | 167 | [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) { 168 | switch (returnCode) { 169 | 170 | case NSModalResponseCancel: { 171 | // nothing 172 | break; 173 | } 174 | 175 | case NSModalResponseOK: { 176 | 177 | __block ACCodeSnippetGitDataStore *dataStore = weakSelf.gitDataStore; 178 | 179 | [weakSelf.window beginSheet:weakSelf.progressPanel completionHandler:nil]; 180 | [weakSelf.progressIndicator startAnimation:weakSelf]; 181 | 182 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 183 | 184 | [dataStore exportAllCodeSnippets]; 185 | 186 | dispatch_async(dispatch_get_main_queue(), ^{ 187 | [weakSelf.window endSheet:weakSelf.progressPanel]; 188 | [weakSelf.progressIndicator stopAnimation:weakSelf]; 189 | }); 190 | }); 191 | 192 | break; 193 | } 194 | 195 | default: 196 | break; 197 | } 198 | }]; 199 | } 200 | 201 | - (IBAction)removeSystemSnippets:(id)sender { 202 | NSError *error; 203 | 204 | if ([[NSFileManager defaultManager] fileExistsAtPath:self.systemSnippetsBackupPath isDirectory:nil] || 205 | [[NSFileManager defaultManager] moveItemAtPath:self.systemSnippetsPath 206 | toPath:self.systemSnippetsBackupPath 207 | error:&error] 208 | ) { 209 | 210 | // we need an empty file or Xcode will complain and crash at startup 211 | [[NSFileManager defaultManager] createFileAtPath:self.systemSnippetsPath 212 | contents:nil 213 | attributes:0]; 214 | 215 | [[NSAlert alertWithMessageText:@"Restart Xcode for changes to take effect." 216 | defaultButton:@"OK" 217 | alternateButton:nil 218 | otherButton:nil 219 | informativeTextWithFormat:@""] beginSheetModalForWindow:self.window completionHandler:nil]; 220 | } else { 221 | [[NSAlert alertWithError:error] beginSheetModalForWindow:self.window completionHandler:nil]; 222 | } 223 | } 224 | 225 | - (IBAction)restoreSystemSnippets:(id)sender { 226 | NSError *error; 227 | if ([[NSFileManager defaultManager] fileExistsAtPath:self.systemSnippetsBackupPath isDirectory:nil]) { 228 | [[NSFileManager defaultManager] removeItemAtPath:self.systemSnippetsPath error:&error]; 229 | 230 | if ([[NSFileManager defaultManager] copyItemAtPath:self.systemSnippetsBackupPath 231 | toPath:self.systemSnippetsPath 232 | error:&error]) { 233 | [[NSAlert alertWithMessageText:@"Restart Xcode for changes to take effect." 234 | defaultButton:@"OK" 235 | alternateButton:nil 236 | otherButton:nil 237 | informativeTextWithFormat:@""] beginSheetModalForWindow:self.window completionHandler:nil]; 238 | } else { 239 | [[NSAlert alertWithError:error] beginSheetModalForWindow:self.window completionHandler:nil]; 240 | } 241 | } 242 | } 243 | 244 | - (IBAction)openSystemSnippetsDirectoryAction:(id)sender { 245 | [[NSWorkspace sharedWorkspace] selectFile:[self systemSnippetsPath] inFileViewerRootedAtPath:nil]; 246 | } 247 | 248 | - (NSString*)systemSnippetsPath { 249 | NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(@"IDECodeSnippetRepository")]; 250 | return [bundle pathForResource:@"SystemCodeSnippets" ofType:@"codesnippets"]; 251 | } 252 | 253 | - (NSString*)systemSnippetsBackupPath { 254 | return [self.systemSnippetsPath stringByAppendingPathExtension:@"backup"]; 255 | } 256 | 257 | 258 | - (IBAction)openGithubAction:(id)sender { 259 | [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://github.com/acoomans/ACCodeSnippetRepositoryPlugin"]]; 260 | } 261 | 262 | 263 | #pragma mark - Paths 264 | 265 | - (NSString*)pathForSnippetDirectory { 266 | NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject]; 267 | return [NSString pathWithComponents:@[libraryPath, @"Developer", @"Xcode", @"UserData", @"CodeSnippets"]]; 268 | } 269 | 270 | - (NSString*)pathForBackupDirectory { 271 | NSDate *currentDate = [NSDate date]; 272 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 273 | [dateFormatter setDateFormat:@"YYMMdd-HHmm"]; 274 | return [NSString pathWithComponents:@[self.pathForSnippetDirectory, [NSString stringWithFormat:@"backup-%@", [dateFormatter stringFromDate:currentDate]]]]; 275 | } 276 | 277 | @end 278 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Controllers/ACCodeSnippetRepositoryConfigurationWindowController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | Don't hesitate to contribute by submitting pull requests at 78 | https://github.com/acoomans/ACCodeSnippetRepositoryPlugin 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 103 | 114 | 125 | 140 | 151 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 182 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/Headers/IDE.h: -------------------------------------------------------------------------------- 1 | #import "IDECodeSnippet.h" 2 | #import "IDECodeSnippetLibrary.h" 3 | #import "IDECodeSnippetRepository.h" -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/Headers/IDECodeSnippet.h: -------------------------------------------------------------------------------- 1 | // class-dump 2 | 3 | @class DVTCustomDataSpecifier, DVTPlatformFamily, DVTSourceCodeLanguage; 4 | 5 | @interface IDECodeSnippet : NSObject 6 | { 7 | DVTCustomDataSpecifier *_customDataSpecifier; 8 | DVTPlatformFamily *_platformFamily; 9 | DVTSourceCodeLanguage *_language; 10 | NSString *_completionPrefix; 11 | long long _relativePriority; 12 | NSSet *_completionScopes; 13 | NSString *_identifier; 14 | NSString *_contents; 15 | NSString *_summary; 16 | long long _version; 17 | NSString *_title; 18 | BOOL _userSnippet; 19 | } 20 | 21 | + (id)displayNameForCompletionScope:(id)arg1; 22 | + (id)completionScopesForLanguage:(id)arg1; 23 | + (id)keyPathsForValuesAffectingSystemSnippet; 24 | + (id)userEditableKeyPaths; 25 | @property(retain) DVTCustomDataSpecifier *customDataSpecifier; // @synthesize customDataSpecifier=_customDataSpecifier; 26 | @property long long version; // @synthesize version=_version; 27 | @property(readonly) NSString *identifier; // @synthesize identifier=_identifier; 28 | @property(getter=isUserSnippet) BOOL userSnippet; // @synthesize userSnippet=_userSnippet; 29 | @property(copy) NSSet *completionScopes; // @synthesize completionScopes=_completionScopes; 30 | @property long long relativePriority; // @synthesize relativePriority=_relativePriority; 31 | @property(copy) NSString *completionPrefix; // @synthesize completionPrefix=_completionPrefix; 32 | @property(copy) NSString *summary; // @synthesize summary=_summary; 33 | @property(copy) NSString *title; // @synthesize title=_title; 34 | @property(copy) NSString *contents; // @synthesize contents=_contents; 35 | @property(retain) DVTPlatformFamily *platformFamily; // @synthesize platformFamily=_platformFamily; 36 | @property(retain) DVTSourceCodeLanguage *language; // @synthesize language=_language; 37 | //- (void).cxx_destruct; 38 | - (id)dictionaryRepresentation; 39 | - (id)description; 40 | @property(readonly, getter=isSystemSnippet) BOOL systemSnippet; 41 | @property(readonly) NSImage *image; 42 | - (id)initWithDictionaryRepresentation:(id)arg1; 43 | - (id)initWithContents:(id)arg1 language:(id)arg2 platformFamily:(id)arg3 userSnippet:(BOOL)arg4; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/Headers/IDECodeSnippetLibrary.h: -------------------------------------------------------------------------------- 1 | // class-dump 2 | 3 | @class DVTObservingToken; 4 | 5 | @interface IDECodeSnippetLibrary : NSObject //DVTLibraryController 6 | { 7 | DVTObservingToken *_kvoSnippetRepositoryToken; 8 | NSMapTable *_strongSnippetToAssetMap; 9 | NSArray *_orderedPlatformFamilies; 10 | BOOL _isAddingUserCodeSnippet; 11 | NSSet *_lastSnippets; 12 | } 13 | 14 | //- (void).cxx_destruct; 15 | - (id)codeDetailController:(id)arg1 contentsForAsset:(id)arg2 representedObject:(id)arg3; 16 | - (id)codeDetailController:(id)arg1 languageForAsset:(id)arg2 representedObject:(id)arg3; 17 | - (id)editorViewControllerForAsset:(id)arg1; 18 | - (BOOL)canRemoveAsset:(id)arg1; 19 | - (BOOL)canEditAsset:(id)arg1; 20 | - (BOOL)removeAssets:(id)arg1 error:(id *)arg2; 21 | - (BOOL)createAsset:(id *)arg1 forLibrarySourceWithIdentifier:(id *)arg2 fromPasteboard:(id)arg3; 22 | - (BOOL)canCreateAssetsFromPasteboard:(id)arg1 targetingLibrarySourceIdentifier:(id *)arg2; 23 | - (id)readableAssetPasteboardTypes; 24 | - (void)dealloc; 25 | - (void)finalize; 26 | - (void)viewWillUninstall; 27 | - (void)primitiveInvalidate; 28 | - (void)libraryDidLoad; 29 | - (struct CGSize)detailAreaSize; 30 | - (void)populatePasteboard:(id)arg1 withAssets:(id)arg2; 31 | - (void)addUserSnippet:(id)arg1 withAsset:(id)arg2; 32 | - (void)codeSnippetsDidUpdate; 33 | - (void)removeAssetForCodeSnippet:(id)arg1; 34 | - (void)addAssetForCodeSnippet:(id)arg1; 35 | - (void)addAsset:(id)arg1 toLibrarySourceIdentifierForPlatformFamily:(id)arg2; 36 | - (void)addLibraryGroupsIfNeeded; 37 | - (void)setLibraryAsset:(id)arg1 forCodeSnippet:(id)arg2; 38 | - (void)observeValueForKeyPath:(id)arg1 ofObject:(id)arg2 change:(id)arg3 context:(void *)arg4; 39 | - (void)stopObservingSnippet:(id)arg1; 40 | - (void)startObservingSnippet:(id)arg1; 41 | - (id)observingKeyPathsForCodeSnippet:(id)arg1; 42 | - (id)libraryAssetForCodeSnippet:(id)arg1; 43 | - (id)createLibraryAssetForCodeSnippet:(id)arg1; 44 | - (id)platformIconForPlatformFamily:(id)arg1; 45 | - (id)defaultPlatformIcon; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/Headers/IDECodeSnippetRepository.h: -------------------------------------------------------------------------------- 1 | // class-dump 2 | 3 | @class DVTDelayedInvocation; 4 | 5 | @interface IDECodeSnippetRepository : NSObject 6 | { 7 | NSMutableDictionary *_systemSnippetsByIdentifier; 8 | NSMutableDictionary *_snippetsByIdentifier; 9 | NSMutableSet *_codeSnippetsNeedingSaving; 10 | DVTDelayedInvocation *_savingInvocation; 11 | NSMutableSet *_codeSnippets; 12 | } 13 | 14 | + (id)sharedRepository; 15 | @property(readonly) NSSet *codeSnippets; // @synthesize codeSnippets=_codeSnippets; 16 | //- (void).cxx_destruct; 17 | - (void)removeCodeSnippet:(id)arg1; 18 | - (void)addCodeSnippet:(id)arg1; 19 | - (void)observeValueForKeyPath:(id)arg1 ofObject:(id)arg2 change:(id)arg3 context:(void *)arg4; 20 | - (void)stopObservingSnippet:(id)arg1; 21 | - (void)startObservingSnippet:(id)arg1; 22 | - (void)_removeUserCodeSnippetFromDisk:(id)arg1; 23 | - (void)_saveUserCodeSnippetsToDisk; 24 | - (void)saveUserCodeSnippetToDisk:(id)arg1; 25 | - (void)setUserSnippetNeedsSaving:(id)arg1; 26 | - (id)_updatedUserSnippet:(id)arg1; 27 | - (void)_loadUserCodeSnippets; 28 | - (id)codeSnippetFromCustomDataSpecifier:(id)arg1 dataStore:(id)arg2; 29 | - (void)_loadSystemCodeSnippets; 30 | - (id)userDataStore; 31 | - (id)init; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/Swizzle/IDECodeSnippetRepositorySwizzler.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDECodeSnippetRepositorySwizzler.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "Swizzler.h" 10 | #import "IDE.h" 11 | #import "ACCodeSnippetDataStoreProtocol.h" 12 | 13 | @interface IDECodeSnippetRepository (Swizzled) 14 | 15 | @property (nonatomic, strong) NSArray *dataStores; 16 | - (void)addDataStore:(id)dataStore; 17 | - (void)removeDataStore:(id)dataStore; 18 | 19 | - (void)addCodeSnippet:(id)arg1; 20 | - (void)removeCodeSnippet:(id)arg1; 21 | 22 | - (IDECodeSnippet*)codeSnippetForIdentifier:(NSString*)identifier; 23 | 24 | - (void)override_saveUserCodeSnippetToDisk:(id)arg1; 25 | 26 | @end 27 | 28 | @interface IDECodeSnippetRepositorySwizzler : Swizzler 29 | @property (nonatomic, strong) NSArray *dataStores; 30 | @end 31 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/Swizzle/IDECodeSnippetRepositorySwizzler.m: -------------------------------------------------------------------------------- 1 | // 2 | // IDECodeSnippetRepositorySwizzler.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "IDECodeSnippetRepositorySwizzler.h" 10 | 11 | 12 | static char const * const kIDECodeSnippetRepositorySwizzledDataStores = "kIDECodeSnippetRepositorySwizzledDataStores"; 13 | 14 | 15 | @implementation IDECodeSnippetRepositorySwizzler 16 | 17 | + (void)load { 18 | static dispatch_once_t onceToken; 19 | dispatch_once(&onceToken, ^{ 20 | [[NSBundle bundleWithIdentifier:@"com.apple.dt.IDE.IDECodeSnippetLibrary"] load]; 21 | [self swizzleWithClass:NSClassFromString(@"IDECodeSnippetRepository")]; 22 | }); 23 | } 24 | 25 | #pragma mark - overrides 26 | 27 | 28 | - (IDECodeSnippet*)override_codeSnippetForIdentifier:(NSString*)identifier { 29 | for (IDECodeSnippet *snippet in [swelf codeSnippets]) { 30 | if ([snippet.identifier isEqualToString:identifier]) { 31 | return snippet; 32 | } 33 | } 34 | return nil; 35 | } 36 | 37 | - (void)override_saveUserCodeSnippetToDisk:(id)arg1 { // saveUserCodeSnippetToDisk: instead of addCodeSnippet: so to catch edits as well 38 | NSLog(@"ACCodeSnippetRepositoryPlugin -- saveUserCodeSnippetToDisk: %@", arg1); 39 | 40 | [self override_saveUserCodeSnippetToDisk:arg1]; 41 | 42 | for (id dataStore in [self dataStores]) { 43 | [dataStore addCodeSnippet:(IDECodeSnippet*)arg1]; 44 | } 45 | } 46 | 47 | - (void)override_removeCodeSnippet:(id)arg1 { 48 | NSLog(@"ACCodeSnippetRepositoryPlugin -- removeCodeSnippet: %@", arg1); 49 | 50 | [self override_removeCodeSnippet:arg1]; 51 | 52 | 53 | for (id dataStore in [self dataStores]) { 54 | [dataStore removeCodeSnippet:(IDECodeSnippet*)arg1]; 55 | } 56 | } 57 | 58 | 59 | #pragma mark - properties 60 | 61 | - (NSArray*)override_dataStores { 62 | return objc_getAssociatedObject(self, kIDECodeSnippetRepositorySwizzledDataStores); 63 | } 64 | 65 | - (void)override_setDataStores:(NSArray*)dataStores { 66 | objc_setAssociatedObject(self, kIDECodeSnippetRepositorySwizzledDataStores, dataStores, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 67 | } 68 | 69 | - (void)override_addDataStore:(id)dataStore { 70 | 71 | if ([dataStore respondsToSelector:@selector(dataStoreWillAdd)]) { 72 | [dataStore dataStoreWillAdd]; 73 | } 74 | 75 | NSMutableArray *dataStores = [[self dataStores] mutableCopy]; 76 | if (!dataStores) { 77 | dataStores = [@[] mutableCopy]; 78 | } 79 | [dataStores addObject:dataStore]; 80 | [self setDataStores:dataStores]; 81 | 82 | if ([dataStore respondsToSelector:@selector(dataStoreDidAdd)]) { 83 | [dataStore dataStoreDidAdd]; 84 | } 85 | } 86 | 87 | - (void)override_removeDataStore:(id)dataStore { 88 | 89 | if ([dataStore respondsToSelector:@selector(dataStoreWillRemove)]) { 90 | [dataStore dataStoreWillRemove]; 91 | } 92 | 93 | NSMutableArray *dataStores = [[self dataStores] mutableCopy]; 94 | if (!dataStores) { 95 | dataStores = [@[] mutableCopy]; 96 | } 97 | [dataStores removeObject:dataStore]; 98 | [self setDataStores:dataStores]; 99 | 100 | if ([dataStore respondsToSelector:@selector(dataStoreDidRemove)]) { 101 | [dataStore dataStoreDidRemove]; 102 | } 103 | } 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/Swizzle/Swizzler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Swizzler.h 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | #define swelf (IDECodeSnippetRepository*)self // swizzled self 14 | 15 | @interface Swizzler : NSObject 16 | 17 | + (void)swizzleWithClass:(Class)cls; 18 | + (void)swizzleMethodsWithPrefix:(NSString*)prefix class:(Class)cls; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/Swizzle/Swizzler.m: -------------------------------------------------------------------------------- 1 | // 2 | // Swizzler.m 3 | // ACCodeSnippetRepository 4 | // 5 | // Created by Arnaud Coomans on 11/02/14. 6 | // Copyright (c) 2014 Arnaud Coomans. All rights reserved. 7 | // 8 | 9 | #import "Swizzler.h" 10 | 11 | 12 | static NSString * const kSwizzlerOverridePrefix = @"override_"; 13 | 14 | @implementation Swizzler 15 | 16 | + (void)swizzleWithClass:(Class)original_cls { 17 | [self swizzleMethodsWithPrefix:kSwizzlerOverridePrefix class:original_cls]; 18 | } 19 | 20 | + (void)swizzleMethodsWithPrefix:(NSString*)prefix class:(Class)original_cls { 21 | 22 | int unsigned numMethods; 23 | Method *methods = class_copyMethodList(self.class, &numMethods); 24 | for (int i = 0; i < numMethods; i++) { 25 | 26 | NSString *overrideMethodName = NSStringFromSelector(method_getName(methods[i])); 27 | if ([overrideMethodName hasPrefix:prefix]) { 28 | 29 | NSString *originalMethodName = [overrideMethodName substringFromIndex:[prefix length]]; 30 | 31 | Method original_method = class_getInstanceMethod(original_cls, NSSelectorFromString(originalMethodName)); 32 | Method override_method = class_getInstanceMethod(self.class, NSSelectorFromString(overrideMethodName)); 33 | 34 | if (!original_method || class_addMethod(original_cls, NSSelectorFromString(overrideMethodName), method_getImplementation(original_method), method_getTypeEncoding(original_method))) { 35 | class_replaceMethod(original_cls, NSSelectorFromString(originalMethodName), method_getImplementation(override_method), method_getTypeEncoding(override_method)); 36 | } 37 | } 38 | 39 | } 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/IDE/classdump.txt: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard. 5 | // 6 | 7 | #pragma mark Blocks 8 | 9 | typedef void (^CDUnknownBlockType)(void); // return type and parameters are unknown 10 | 11 | #pragma mark Named Structures 12 | 13 | struct CGPoint { 14 | double _field1; 15 | double _field2; 16 | }; 17 | 18 | struct CGRect { 19 | struct CGPoint _field1; 20 | struct CGSize _field2; 21 | }; 22 | 23 | struct CGSize { 24 | double _field1; 25 | double _field2; 26 | }; 27 | 28 | struct _NSRange { 29 | unsigned long long _field1; 30 | unsigned long long _field2; 31 | }; 32 | 33 | #pragma mark - 34 | 35 | // 36 | // File: /Applications/Xcode-5.0.1.app/Contents/PlugIns/IDECodeSnippetLibrary.ideplugin/Contents/MacOS/IDECodeSnippetLibrary 37 | // UUID: 6CD77E6E-AC62-3126-B9CA-403D7B87CBF9 38 | // 39 | // Arch: x86_64 40 | // Current version: 3323.0.0 41 | // Compatibility version: 1.0.0 42 | // Source version: 3323.0.0.0.0 43 | // Minimum Mac OS X version: 10.8.0 44 | // SDK version: 10.9.0 45 | // 46 | // Objective-C Garbage Collection: Unsupported 47 | // 48 | 49 | @protocol DVTCompletingTextViewDelegate 50 | 51 | @optional 52 | - (void)setupTextViewContextMenuWithMenu:(NSMenu *)arg1; 53 | - (BOOL)completingTextViewHandleCancel:(DVTCompletingTextView *)arg1; 54 | - (unsigned long long)textView:(DVTCompletingTextView *)arg1 lineEndingForWritingSelectionToPasteboard:(NSPasteboard *)arg2 type:(NSString *)arg3; 55 | - (unsigned long long)textView:(DVTCompletingTextView *)arg1 lineEndingForReadingSelectionFromPasteboard:(NSPasteboard *)arg2 type:(NSString *)arg3; 56 | - (void)textView:(DVTCompletingTextView *)arg1 layoutManager:(NSLayoutManager *)arg2 didLayoutGlyphsUpToCharacterIndex:(unsigned long long)arg3; 57 | - (DVTTextDocumentLocation *)completingTextView:(DVTCompletingTextView *)arg1 documentLocationForWordStartLocation:(unsigned long long)arg2; 58 | - (void)completingTextView:(DVTCompletingTextView *)arg1 willPassContextToStrategies:(NSMutableDictionary *)arg2 atWordStartLocation:(unsigned long long)arg3; 59 | @end 60 | 61 | @protocol DVTSourceTextViewDelegate 62 | 63 | @optional 64 | - (NSString *)textViewWillReturnPrintJobTitle:(DVTSourceTextView *)arg1; 65 | - (void)textViewDidScroll:(DVTSourceTextView *)arg1; 66 | - (void)setupGutterContextMenuWithMenu:(NSMenu *)arg1; 67 | - (void)tokenizableItemsForItemAtRange:(struct _NSRange)arg1 completionBlock:(void (^)(NSArray *))arg2; 68 | - (void)textViewDidFinishAnimatingScroll:(DVTSourceTextView *)arg1; 69 | - (void)textViewDidLoadAnnotationProviders:(DVTSourceTextView *)arg1; 70 | - (void)textView:(DVTSourceTextView *)arg1 didRemoveAnnotations:(NSArray *)arg2; 71 | - (void)textView:(DVTSourceTextView *)arg1 didAddAnnotations:(NSArray *)arg2; 72 | - (DVTAnnotationContext *)annotationContextForTextView:(DVTSourceTextView *)arg1; 73 | - (NSDictionary *)syntaxColoringContextForTextView:(DVTSourceTextView *)arg1; 74 | - (void)textViewDidChangeFolding:(NSNotification *)arg1; 75 | - (void)textViewWillChangeFolding:(NSNotification *)arg1; 76 | - (void)textView:(DVTSourceTextView *)arg1 didClickOnTemporaryLinkAtCharacterIndex:(unsigned long long)arg2 event:(NSEvent *)arg3 isAltEvent:(BOOL)arg4; 77 | - (BOOL)textView:(DVTSourceTextView *)arg1 shouldShowTemporaryLinkForCharacterAtIndex:(unsigned long long)arg2 proposedRange:(struct _NSRange)arg3 effectiveRanges:(id *)arg4; 78 | - (void)textView:(DVTSourceTextView *)arg1 handleMouseDidExitSidebar:(NSEvent *)arg2; 79 | - (void)textView:(DVTSourceTextView *)arg1 handleMouseDidMoveOverSidebar:(NSEvent *)arg2 atLineNumber:(unsigned long long)arg3; 80 | - (void)textView:(DVTSourceTextView *)arg1 handleMouseDownInSidebar:(NSEvent *)arg2 atLineNumber:(unsigned long long)arg3; 81 | @end 82 | 83 | @protocol DVTTextCompletionItem 84 | @property(readonly) BOOL notRecommended; 85 | @property double priority; 86 | @property(readonly) NSImage *icon; 87 | @property(readonly) NSAttributedString *descriptionText; 88 | @property(readonly) NSString *parentText; 89 | @property(readonly) NSString *completionText; 90 | @property(readonly) NSString *displayType; 91 | @property(readonly) NSString *displayText; 92 | @property(readonly) NSString *name; 93 | 94 | @optional 95 | @property(readonly) NSImage *highlightedStatusIcon; 96 | @property(readonly) NSImage *statusIcon; 97 | @property(readonly) NSArray *additionalCompletions; 98 | @property(readonly) int completionItemStyle; 99 | - (void)infoViewControllerWithWidth:(double)arg1 context:(NSDictionary *)arg2 completionBlock:(void (^)(DVTViewController *))arg3; 100 | @end 101 | 102 | @protocol NSObject 103 | - (NSString *)description; 104 | - (unsigned long long)retainCount; 105 | - (id)autorelease; 106 | - (oneway void)release; 107 | - (id)retain; 108 | - (BOOL)respondsToSelector:(SEL)arg1; 109 | - (BOOL)conformsToProtocol:(Protocol *)arg1; 110 | - (BOOL)isMemberOfClass:(Class)arg1; 111 | - (BOOL)isKindOfClass:(Class)arg1; 112 | - (BOOL)isProxy; 113 | - (id)performSelector:(SEL)arg1 withObject:(id)arg2 withObject:(id)arg3; 114 | - (id)performSelector:(SEL)arg1 withObject:(id)arg2; 115 | - (id)performSelector:(SEL)arg1; 116 | - (struct _NSZone *)zone; 117 | - (id)self; 118 | - (Class)class; 119 | - (Class)superclass; 120 | - (unsigned long long)hash; 121 | - (BOOL)isEqual:(id)arg1; 122 | 123 | @optional 124 | - (NSString *)debugDescription; 125 | @end 126 | 127 | @protocol NSTextDelegate 128 | 129 | @optional 130 | - (void)textDidChange:(NSNotification *)arg1; 131 | - (void)textDidEndEditing:(NSNotification *)arg1; 132 | - (void)textDidBeginEditing:(NSNotification *)arg1; 133 | - (BOOL)textShouldEndEditing:(NSText *)arg1; 134 | - (BOOL)textShouldBeginEditing:(NSText *)arg1; 135 | @end 136 | 137 | @protocol NSTextViewDelegate 138 | 139 | @optional 140 | - (NSUndoManager *)undoManagerForTextView:(NSTextView *)arg1; 141 | - (void)textView:(NSTextView *)arg1 draggedCell:(id )arg2 inRect:(struct CGRect)arg3 event:(NSEvent *)arg4; 142 | - (void)textView:(NSTextView *)arg1 doubleClickedOnCell:(id )arg2 inRect:(struct CGRect)arg3; 143 | - (void)textView:(NSTextView *)arg1 clickedOnCell:(id )arg2 inRect:(struct CGRect)arg3; 144 | - (BOOL)textView:(NSTextView *)arg1 clickedOnLink:(id)arg2; 145 | - (NSSharingServicePicker *)textView:(NSTextView *)arg1 willShowSharingServicePicker:(NSSharingServicePicker *)arg2 forItems:(NSArray *)arg3; 146 | - (NSURL *)textView:(NSTextView *)arg1 URLForContentsOfTextAttachment:(NSTextAttachment *)arg2 atIndex:(unsigned long long)arg3; 147 | - (NSArray *)textView:(NSTextView *)arg1 didCheckTextInRange:(struct _NSRange)arg2 types:(unsigned long long)arg3 options:(NSDictionary *)arg4 results:(NSArray *)arg5 orthography:(NSOrthography *)arg6 wordCount:(long long)arg7; 148 | - (NSDictionary *)textView:(NSTextView *)arg1 willCheckTextInRange:(struct _NSRange)arg2 options:(NSDictionary *)arg3 types:(unsigned long long *)arg4; 149 | - (NSMenu *)textView:(NSTextView *)arg1 menu:(NSMenu *)arg2 forEvent:(NSEvent *)arg3 atIndex:(unsigned long long)arg4; 150 | - (long long)textView:(NSTextView *)arg1 shouldSetSpellingState:(long long)arg2 range:(struct _NSRange)arg3; 151 | - (BOOL)textView:(NSTextView *)arg1 doCommandBySelector:(SEL)arg2; 152 | - (BOOL)textView:(NSTextView *)arg1 shouldChangeTextInRange:(struct _NSRange)arg2 replacementString:(NSString *)arg3; 153 | - (NSArray *)textView:(NSTextView *)arg1 completions:(NSArray *)arg2 forPartialWordRange:(struct _NSRange)arg3 indexOfSelectedItem:(long long *)arg4; 154 | - (NSString *)textView:(NSTextView *)arg1 willDisplayToolTip:(NSString *)arg2 forCharacterAtIndex:(unsigned long long)arg3; 155 | - (void)textViewDidChangeTypingAttributes:(NSNotification *)arg1; 156 | - (void)textViewDidChangeSelection:(NSNotification *)arg1; 157 | - (NSDictionary *)textView:(NSTextView *)arg1 shouldChangeTypingAttributes:(NSDictionary *)arg2 toAttributes:(NSDictionary *)arg3; 158 | - (BOOL)textView:(NSTextView *)arg1 shouldChangeTextInRanges:(NSArray *)arg2 replacementStrings:(NSArray *)arg3; 159 | - (NSArray *)textView:(NSTextView *)arg1 willChangeSelectionFromCharacterRanges:(NSArray *)arg2 toCharacterRanges:(NSArray *)arg3; 160 | - (struct _NSRange)textView:(NSTextView *)arg1 willChangeSelectionFromCharacterRange:(struct _NSRange)arg2 toCharacterRange:(struct _NSRange)arg3; 161 | - (BOOL)textView:(NSTextView *)arg1 writeCell:(id )arg2 atIndex:(unsigned long long)arg3 toPasteboard:(NSPasteboard *)arg4 type:(NSString *)arg5; 162 | - (NSArray *)textView:(NSTextView *)arg1 writablePasteboardTypesForCell:(id )arg2 atIndex:(unsigned long long)arg3; 163 | - (void)textView:(NSTextView *)arg1 draggedCell:(id )arg2 inRect:(struct CGRect)arg3 event:(NSEvent *)arg4 atIndex:(unsigned long long)arg5; 164 | - (void)textView:(NSTextView *)arg1 doubleClickedOnCell:(id )arg2 inRect:(struct CGRect)arg3 atIndex:(unsigned long long)arg4; 165 | - (void)textView:(NSTextView *)arg1 clickedOnCell:(id )arg2 inRect:(struct CGRect)arg3 atIndex:(unsigned long long)arg4; 166 | - (BOOL)textView:(NSTextView *)arg1 clickedOnLink:(id)arg2 atIndex:(unsigned long long)arg3; 167 | @end 168 | 169 | @interface IDECodeSnippetLibrary : DVTLibraryController 170 | { 171 | DVTObservingToken *_kvoSnippetRepositoryToken; 172 | NSMapTable *_strongSnippetToAssetMap; 173 | NSArray *_orderedPlatformFamilies; 174 | BOOL _isAddingUserCodeSnippet; 175 | NSSet *_lastSnippets; 176 | } 177 | 178 | - (void).cxx_destruct; 179 | - (id)codeDetailController:(id)arg1 contentsForAsset:(id)arg2 representedObject:(id)arg3; 180 | - (id)codeDetailController:(id)arg1 languageForAsset:(id)arg2 representedObject:(id)arg3; 181 | - (id)editorViewControllerForAsset:(id)arg1; 182 | - (BOOL)canRemoveAsset:(id)arg1; 183 | - (BOOL)canEditAsset:(id)arg1; 184 | - (BOOL)removeAssets:(id)arg1 error:(id *)arg2; 185 | - (BOOL)createAsset:(id *)arg1 forLibrarySourceWithIdentifier:(id *)arg2 fromPasteboard:(id)arg3; 186 | - (BOOL)canCreateAssetsFromPasteboard:(id)arg1 targetingLibrarySourceIdentifier:(id *)arg2; 187 | - (id)readableAssetPasteboardTypes; 188 | - (void)dealloc; 189 | - (void)finalize; 190 | - (void)viewWillUninstall; 191 | - (void)primitiveInvalidate; 192 | - (void)libraryDidLoad; 193 | - (struct CGSize)detailAreaSize; 194 | - (void)populatePasteboard:(id)arg1 withAssets:(id)arg2; 195 | - (void)addUserSnippet:(id)arg1 withAsset:(id)arg2; 196 | - (void)codeSnippetsDidUpdate; 197 | - (void)removeAssetForCodeSnippet:(id)arg1; 198 | - (void)addAssetForCodeSnippet:(id)arg1; 199 | - (void)addAsset:(id)arg1 toLibrarySourceIdentifierForPlatformFamily:(id)arg2; 200 | - (void)addLibraryGroupsIfNeeded; 201 | - (void)setLibraryAsset:(id)arg1 forCodeSnippet:(id)arg2; 202 | - (void)observeValueForKeyPath:(id)arg1 ofObject:(id)arg2 change:(id)arg3 context:(void *)arg4; 203 | - (void)stopObservingSnippet:(id)arg1; 204 | - (void)startObservingSnippet:(id)arg1; 205 | - (id)observingKeyPathsForCodeSnippet:(id)arg1; 206 | - (id)libraryAssetForCodeSnippet:(id)arg1; 207 | - (id)createLibraryAssetForCodeSnippet:(id)arg1; 208 | - (id)platformIconForPlatformFamily:(id)arg1; 209 | - (id)defaultPlatformIcon; 210 | 211 | @end 212 | 213 | @interface IDECodeSnippet : NSObject 214 | { 215 | DVTCustomDataSpecifier *_customDataSpecifier; 216 | DVTPlatformFamily *_platformFamily; 217 | DVTSourceCodeLanguage *_language; 218 | NSString *_completionPrefix; 219 | long long _relativePriority; 220 | NSSet *_completionScopes; 221 | NSString *_identifier; 222 | NSString *_contents; 223 | NSString *_summary; 224 | long long _version; 225 | NSString *_title; 226 | BOOL _userSnippet; 227 | } 228 | 229 | + (id)displayNameForCompletionScope:(id)arg1; 230 | + (id)completionScopesForLanguage:(id)arg1; 231 | + (id)keyPathsForValuesAffectingSystemSnippet; 232 | + (id)userEditableKeyPaths; 233 | @property(retain) DVTCustomDataSpecifier *customDataSpecifier; // @synthesize customDataSpecifier=_customDataSpecifier; 234 | @property long long version; // @synthesize version=_version; 235 | @property(readonly) NSString *identifier; // @synthesize identifier=_identifier; 236 | @property(getter=isUserSnippet) BOOL userSnippet; // @synthesize userSnippet=_userSnippet; 237 | @property(copy) NSSet *completionScopes; // @synthesize completionScopes=_completionScopes; 238 | @property long long relativePriority; // @synthesize relativePriority=_relativePriority; 239 | @property(copy) NSString *completionPrefix; // @synthesize completionPrefix=_completionPrefix; 240 | @property(copy) NSString *summary; // @synthesize summary=_summary; 241 | @property(copy) NSString *title; // @synthesize title=_title; 242 | @property(copy) NSString *contents; // @synthesize contents=_contents; 243 | @property(retain) DVTPlatformFamily *platformFamily; // @synthesize platformFamily=_platformFamily; 244 | @property(retain) DVTSourceCodeLanguage *language; // @synthesize language=_language; 245 | - (void).cxx_destruct; 246 | - (id)dictionaryRepresentation; 247 | - (id)description; 248 | @property(readonly, getter=isSystemSnippet) BOOL systemSnippet; 249 | @property(readonly) NSImage *image; 250 | - (id)initWithDictionaryRepresentation:(id)arg1; 251 | - (id)initWithContents:(id)arg1 language:(id)arg2 platformFamily:(id)arg3 userSnippet:(BOOL)arg4; 252 | 253 | @end 254 | 255 | @interface IDECodeSnippetRepository : NSObject 256 | { 257 | NSMutableDictionary *_systemSnippetsByIdentifier; 258 | NSMutableDictionary *_snippetsByIdentifier; 259 | NSMutableSet *_codeSnippetsNeedingSaving; 260 | DVTDelayedInvocation *_savingInvocation; 261 | NSMutableSet *_codeSnippets; 262 | } 263 | 264 | + (id)sharedRepository; 265 | @property(readonly) NSSet *codeSnippets; // @synthesize codeSnippets=_codeSnippets; 266 | - (void).cxx_destruct; 267 | - (void)removeCodeSnippet:(id)arg1; 268 | - (void)addCodeSnippet:(id)arg1; 269 | - (void)observeValueForKeyPath:(id)arg1 ofObject:(id)arg2 change:(id)arg3 context:(void *)arg4; 270 | - (void)stopObservingSnippet:(id)arg1; 271 | - (void)startObservingSnippet:(id)arg1; 272 | - (void)_removeUserCodeSnippetFromDisk:(id)arg1; 273 | - (void)_saveUserCodeSnippetsToDisk; 274 | - (void)saveUserCodeSnippetToDisk:(id)arg1; 275 | - (void)setUserSnippetNeedsSaving:(id)arg1; 276 | - (id)_updatedUserSnippet:(id)arg1; 277 | - (void)_loadUserCodeSnippets; 278 | - (id)codeSnippetFromCustomDataSpecifier:(id)arg1 dataStore:(id)arg2; 279 | - (void)_loadSystemCodeSnippets; 280 | - (id)userDataStore; 281 | - (id)init; 282 | 283 | @end 284 | 285 | @interface _IDECodeSnippetLibraryAllPlatformsPlaceholder : NSObject 286 | { 287 | } 288 | 289 | - (id)name; 290 | 291 | @end 292 | 293 | @interface IDECodeSnippetLibraryDetailEditorController : DVTLibraryDetailEditorController 294 | { 295 | DVTStackView_ML *_completionScopesStackView; 296 | NSMutableArray *_scopeRowControllers; 297 | NSArray *_platformFamilies; 298 | NSArray *_languages; 299 | } 300 | 301 | + (id)keyPathsForValuesAffectingCanRemoveCompletionScope; 302 | + (id)keyPathsForValuesAffectingCanAddCompletionScope; 303 | + (id)keyPathsForValuesAffectingCompletionScopeRowValues; 304 | + (id)keyPathsForValuesAffectingEditedCodeSnippet; 305 | + (void)initialize; 306 | - (void).cxx_destruct; 307 | - (void)didChangeCurrentDetailController; 308 | - (void)willChangeCurrentDetailController; 309 | - (void)_fixKeyViewLoop; 310 | - (void)_updateScopesStackWithInsertHint:(unsigned long long)arg1; 311 | - (BOOL)replaceCompletionScope:(id)arg1 withScope:(id)arg2; 312 | - (BOOL)removeCompletionScope:(id)arg1; 313 | - (BOOL)addCompletionScopeAfterScope:(id)arg1; 314 | @property(readonly) BOOL canRemoveCompletionScope; 315 | @property(readonly) BOOL canAddCompletionScope; 316 | - (void)awakeFromNib; 317 | - (void)textDidChange:(id)arg1; 318 | @property(readonly) IDECodeSnippet *editedCodeSnippet; 319 | - (void)setEditedAsset:(id)arg1; 320 | - (id)sourceTextStorage; 321 | - (id)sourceTextView; 322 | - (id)currentDetailController; 323 | @property(readonly) NSArray *completionScopeRowValues; 324 | - (id)_completionScopesForCurrentLanguage; 325 | @property(readonly) NSArray *platformFamilies; 326 | @property(readonly) NSArray *languages; 327 | - (void)primitiveInvalidate; 328 | - (void)viewWillUninstall; 329 | - (id)initWithDidEditHandlerBlock:(CDUnknownBlockType)arg1; 330 | 331 | @end 332 | 333 | @interface IDECodeSnippetCompletionScopeRowValue : NSObject 334 | { 335 | NSString *_completionScope; 336 | } 337 | 338 | @property(readonly) NSString *completionScope; // @synthesize completionScope=_completionScope; 339 | - (void).cxx_destruct; 340 | - (id)description; 341 | @property(readonly) NSString *completionScopeDisplayName; 342 | - (id)initWithCompletionScope:(id)arg1; 343 | 344 | @end 345 | 346 | @interface IDECodeSnippetLibraryPlatformFamilyValueTransformer : NSValueTransformer 347 | { 348 | } 349 | 350 | + (BOOL)allowsReverseTransformation; 351 | - (id)reverseTransformedValue:(id)arg1; 352 | - (id)transformedValue:(id)arg1; 353 | 354 | @end 355 | 356 | @interface IDECodeSnippetLibraryCompletionStrategy : DVTTextCompletionStrategy 357 | { 358 | } 359 | 360 | + (id)_cacheKeyForSourceModelScopes:(id)arg1 language:(id)arg2 platformNames:(id)arg3 atBOL:(BOOL)arg4; 361 | + (void)_clearSnippetsCompletionsCache; 362 | + (void)codeSnippetDidChange:(id)arg1; 363 | + (void)_generateCompletionsForScopes:(id)arg1 language:(id)arg2 platformNames:(id)arg3 atBOL:(BOOL)arg4; 364 | + (id)_cacheKeyForPlatformFamilyNames:(id)arg1; 365 | + (BOOL)_isAtBOLAtLocation:(unsigned long long)arg1 inString:(id)arg2; 366 | + (BOOL)_shouldIncludeSnippet:(id)arg1 inSourceModelScopes:(id)arg2 atBOL:(BOOL)arg3; 367 | + (BOOL)_snippet:(id)arg1 matchesPlatforms:(id)arg2; 368 | + (id)bestCompletionScopeForSourceModelScopes:(id)arg1 atBOL:(BOOL)arg2 language:(id)arg3; 369 | + (BOOL)_scope:(id)arg1 matchesSourceModelScopes:(id)arg2 atBOL:(BOOL)arg3; 370 | - (id)completionItemsForDocumentLocation:(id)arg1 context:(id)arg2 areDefinitive:(char *)arg3; 371 | - (void)prepareForDocumentLocation:(id)arg1 context:(id)arg2; 372 | 373 | @end 374 | 375 | @interface IDECodeSnippetCompletionItem : NSObject 376 | { 377 | NSAttributedString *_descriptionText; 378 | NSString *_completionText; 379 | NSString *_displayText; 380 | NSString *_displayType; 381 | double _priority; 382 | NSString *_name; 383 | NSImage *_icon; 384 | } 385 | 386 | + (id)infoViewControllerFont; 387 | @property(readonly) NSImage *icon; // @synthesize icon=_icon; 388 | @property(readonly) NSAttributedString *descriptionText; // @synthesize descriptionText=_descriptionText; 389 | @property(readonly) NSString *completionText; // @synthesize completionText=_completionText; 390 | @property(readonly) NSString *displayType; // @synthesize displayType=_displayType; 391 | @property(readonly) NSString *displayText; // @synthesize displayText=_displayText; 392 | @property double priority; // @synthesize priority=_priority; 393 | @property(readonly) NSString *name; // @synthesize name=_name; 394 | - (void).cxx_destruct; 395 | - (void)infoViewControllerWithWidth:(double)arg1 context:(id)arg2 completionBlock:(CDUnknownBlockType)arg3; 396 | @property(readonly) BOOL notRecommended; 397 | @property(readonly) NSString *parentText; 398 | - (id)initWithCodeSnippet:(id)arg1; 399 | 400 | // Remaining properties 401 | @property(readonly) NSArray *additionalCompletions; 402 | @property(readonly) int completionItemStyle; 403 | @property(readonly) NSImage *highlightedStatusIcon; 404 | @property(readonly) NSImage *statusIcon; 405 | 406 | @end 407 | 408 | @interface IDECodeSnippetCompletionScopeRowController : DVTViewController 409 | { 410 | NSPopUpButton *_scopesPopupButton; 411 | NSButton *_addButton; 412 | NSButton *_deleteButton; 413 | IDECodeSnippetLibraryDetailEditorController *_detailController; 414 | NSString *_completionScope; 415 | } 416 | 417 | @property(readonly) IDECodeSnippetLibraryDetailEditorController *detailController; // @synthesize detailController=_detailController; 418 | @property(copy, nonatomic) NSString *completionScope; // @synthesize completionScope=_completionScope; 419 | - (void).cxx_destruct; 420 | - (void)removeScope:(id)arg1; 421 | - (void)addNewScope:(id)arg1; 422 | - (BOOL)validateValue:(id *)arg1 forKey:(id)arg2 error:(id *)arg3; 423 | @property(readonly) NSView *lastKeyView; 424 | @property(readonly) NSView *firstKeyView; 425 | - (void)primitiveInvalidate; 426 | - (void)awakeFromNib; 427 | - (id)initWithCompletionScope:(id)arg1 detailController:(id)arg2; 428 | 429 | @end 430 | 431 | @interface IDECodeSnippetCompletionItemInfoViewController : DVTViewController 432 | { 433 | NSTextField *textField; 434 | } 435 | 436 | + (id)defaultViewNibName; 437 | @property NSTextField *textField; // @synthesize textField; 438 | - (void)primitiveInvalidate; 439 | - (id)initWithNibName:(id)arg1 bundle:(id)arg2; 440 | 441 | @end 442 | 443 | -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Resources/Images/GitHub-Mark-120px-plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/ACCodeSnippetRepository/Resources/Images/GitHub-Mark-120px-plus.png -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Resources/Images/GitHub-Mark-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/ACCodeSnippetRepository/Resources/Images/GitHub-Mark-32px.png -------------------------------------------------------------------------------- /ACCodeSnippetRepository/Resources/Images/GitHub-Mark-64px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/ACCodeSnippetRepository/Resources/Images/GitHub-Mark-64px.png -------------------------------------------------------------------------------- /ACCodeSnippetRepository/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Documentation/architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/110809_FamilyChineseOahu_EN_00317_2040x1360-small-12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/110809_FamilyChineseOahu_EN_00317_2040x1360-small-12.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/110809_FamilyChineseOahu_EN_02016_981x654-small-14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/110809_FamilyChineseOahu_EN_02016_981x654-small-14.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/110809_FamilyChineseOahu_EN_02390_2880x1921-small-10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/110809_FamilyChineseOahu_EN_02390_2880x1921-small-10.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt10@2x-92.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt10@2x-92.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt1@2x-83.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt1@2x-83.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt2@2x-84.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt2@2x-84.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt3@2x-85.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt3@2x-85.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt4@2x-86.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt4@2x-86.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt5@2x-87.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt5@2x-87.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt6@2x-88.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt6@2x-88.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt7@2x-89.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt7@2x-89.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt8@2x-90.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt8@2x-90.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/mt9@2x-91.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/mt9@2x-91.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Data/st0-332.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Data/st0-332.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/Index.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Index.zip -------------------------------------------------------------------------------- /Documentation/architecture.key/Metadata/BuildVersionHistory.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Template: White (2013-12-16 11:11) 6 | M6.1-1769-1 7 | 8 | 9 | -------------------------------------------------------------------------------- /Documentation/architecture.key/Metadata/DocumentIdentifier: -------------------------------------------------------------------------------- 1 | D201E953-8EC1-4C9C-913C-4DF6172B7A00 -------------------------------------------------------------------------------- /Documentation/architecture.key/Metadata/Properties.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/Metadata/Properties.plist -------------------------------------------------------------------------------- /Documentation/architecture.key/preview-micro.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/preview-micro.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/preview-web.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/preview-web.jpg -------------------------------------------------------------------------------- /Documentation/architecture.key/preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Documentation/architecture.key/preview.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Arnaud Coomans 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ACCodeSnippetRepositoryPlugin 2 | 3 | ACCodeSnippetRepositoryPlugin is a Xcode plugin for seemless synchronization of snippets with a git repository. 4 | 5 | The snippets are synchronized as human-readable text (and not an obscure _.codesnippet_ plist). 6 | 7 | [![Build Status](https://api.travis-ci.org/acoomans/ACCodeSnippetRepositoryPlugin.png)](https://api.travis-ci.org/acoomans/ACCodeSnippetRepositoryPlugin.png) 8 | 9 | If you want to know more about snippets in Xcode, I recommend reading [Xcode Snippets on NSHipster](http://nshipster.com/xcode-snippets/). 10 | 11 | Want to try the plugin with an existing public repository? Try [acoomans](https://github.com/acoomans/xcode-snippets) or [mattt](https://github.com/mattt/Xcode-Snippets.git)'s snippets. 12 | 13 | 14 | ## Install 15 | 16 | 1. Build the project to install the plugin. The plugin is installed in `/Library/Application Support/Developer/Shared/Xcode/Plug-ins/ACCodeSnippetRepository.xcplugin`. 17 | 18 | 2. Restart Xcode for the plugin to be activated. 19 | 20 | Alternatively, install through [Alcatraz](https://github.com/supermarin/Alcatraz) plugin manager. 21 | 22 | 23 | ## Configuration 24 | 25 | There should be a `Plug-ins` item in the xcode menu: 26 | 27 | ![screenshots](Screenshots/screenshot01.png) 28 | 29 | First configure the plugin by forking a remote repository: 30 | 31 | ![screenshots](Screenshots/screenshot02.png) 32 | 33 | When you fork, all snippets from the repository (with the right format, see below _Format_) will be imported in Xcode. Your existing snippets, that do not belong to any repository yet, will not be affected. 34 | 35 | After forking, you will given the choice to import (user) snippets from Xcode to the repository. 36 | 37 | Also, you can remove the system snippets if you don't use them. 38 | 39 | In case of any problem (see below, _Bugs and limitations_), you can go to the user snippets folder and backup your user snippets. Note that user snippets are automatically backed up before any fork. 40 | 41 | 42 | ## Usage 43 | 44 | Use snippets like you always do in Xcode. Snippets are automatically added/edited/removed and pushed to the git repository. 45 | 46 | ![screenshots](Screenshots/screenshot03.png) 47 | 48 | ### Format 49 | 50 | The snippets are text files with a _.m_ file extension, in the following format: 51 | 52 | * a header, containing: 53 | * the title 54 | * description 55 | * various Xcode-related information in a _Key: Value_ format (keys ordered alphabetically) 56 | * the code 57 | 58 | If your snippet does not contain any header, the header will be added, committed and pushed when imported. 59 | 60 | **Note**: do not remove the Xcode-related information as they are needed for synchronization. 61 | 62 | **Note**: if you manually create a snippet by copying an existing one, change or remove the _IDECodeSnippetIdentifier_ as Xcode does not like having two snippets with the same identifier (will crash). 63 | 64 | ![screenshots](Screenshots/screenshot04.png) 65 | 66 | ### Synchronization 67 | 68 | Every change in a snippet is commited and pushed independently. 69 | 70 | Snippets are synchronized (pulled) with the remote repository is done every 10 minutes (if the option is enabled) or when the `Update snippets` item was chosen in the menu. 71 | 72 | In case of conflict during the merge, the remote repository has priority. 73 | 74 | 75 | ## Bugs and limitations 76 | 77 | Probably a lot. 78 | 79 | Backup your snippets and your git repository. Expect bugs, crashes, synchronization issues, data and hair loss. 80 | 81 | 82 | ## Contributing 83 | 84 | ### Architecture 85 | 86 | First a quick word on the architecture: 87 | 88 | The plugin does some swizzling with the _IDECodeSnippetRepository_ class from _IDECodeSnippetLibrary.ideplugin_ (_/Applications/Xcode.app/Contents/PlugIns/IDECodeSnippetLibrary.ideplugin_). 89 | 90 | _IDECodeSnippetRepository_ is modified so to make it possible to attach data stores (_ACCodeSnippetDataStoreProtocol_). 91 | 92 | Here's a colourful schematic to make you even more confused: 93 | 94 | ![screenshots](Documentation/architecture.jpg) 95 | 96 | ### Pull requests 97 | 98 | If you want to contribute, send me a pull request. 99 | 100 | ### Improvements 101 | 102 | Ideas of improvements: 103 | 104 | - synchronize _.codesnippet_ plists 105 | - multiple data stores (in progress but need to be careful when synchronizing) 106 | - github's gist support 107 | -------------------------------------------------------------------------------- /Screenshots/screenshot01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Screenshots/screenshot01.png -------------------------------------------------------------------------------- /Screenshots/screenshot02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Screenshots/screenshot02.png -------------------------------------------------------------------------------- /Screenshots/screenshot03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Screenshots/screenshot03.png -------------------------------------------------------------------------------- /Screenshots/screenshot04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acoomans/ACCodeSnippetRepositoryPlugin/1331d43bd680017cbd1d605a3c170c1c446a30d8/Screenshots/screenshot04.png --------------------------------------------------------------------------------