├── KSImageNamed ├── en.lproj │ └── InfoPlist.strings ├── KSImageNamed-Prefix.pch ├── IDEIndex+KSImageNamed.h ├── IDEWorkspace+KSImageNamed.h ├── DVTSourceTextView+KSImageNamed.h ├── DVTTextCompletionSession+KSImageNamed.h ├── DVTTextCompletionController+KSImageNamed.h ├── DVTTextCompletionListWindowController+KSImageNamed.h ├── KSImageNamedCompletionStrategy.h ├── KSImageNamedPreviewWindow.h ├── IDEIndex+KSImageNamed.m ├── IDEWorkspace+KSImageNamed.m ├── KSImageNamed.h ├── KSImageNamed.xcplugindata ├── MethodSwizzle.h ├── DVTTextCompletionController+KSImageNamed.m ├── DVTSourceTextView+KSImageNamed.m ├── KSImageNamed-Info.plist ├── DVTTextCompletionListWindowController+KSImageNamed.m ├── MethodSwizzle.m ├── Completions.plist ├── DVTTextCompletionSession+KSImageNamed.m ├── KSImageNamedIndexCompletionItem.h ├── KSImageNamedIndexCompletionItem.m ├── KSImageNamedPreviewWindow.m ├── KSImageNamedCompletionStrategy.m ├── XcodeMisc.h └── KSImageNamed.m ├── screenshot.gif ├── .gitignore ├── README.md └── KSImageNamed.xcodeproj └── project.pbxproj /KSImageNamed/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ksuther/KSImageNamed-Xcode/HEAD/screenshot.gif -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamed-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'KSImageNamed' target in the 'KSImageNamed' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /KSImageNamed/IDEIndex+KSImageNamed.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDEIndex+KSImageNamed.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/23/13. 6 | // 7 | // 8 | 9 | #import "XcodeMisc.h" 10 | 11 | @interface IDEIndex (KSImageNamed) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KSImageNamed/IDEWorkspace+KSImageNamed.h: -------------------------------------------------------------------------------- 1 | // 2 | // IDEWorkspace+KSImageNamed.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/23/13. 6 | // 7 | // 8 | 9 | #import "XcodeMisc.h" 10 | 11 | @interface IDEWorkspace (KSImageNamed) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KSImageNamed/DVTSourceTextView+KSImageNamed.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVTSourceTextView+KSImageNamed.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/19/13. 6 | // 7 | // 8 | 9 | #import "XcodeMisc.h" 10 | 11 | @interface DVTSourceTextView (KSImageNamed) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KSImageNamed/DVTTextCompletionSession+KSImageNamed.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVTTextCompletionSession+KSImageNamed.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 11/1/15. 6 | // 7 | // 8 | 9 | #import "XcodeMisc.h" 10 | 11 | @interface DVTTextCompletionSession (KSImageNamed) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xcworkspacedata 19 | -------------------------------------------------------------------------------- /KSImageNamed/DVTTextCompletionController+KSImageNamed.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVTTextCompletionController+KSImageNamed.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/22/13. 6 | // 7 | // 8 | 9 | #import "XcodeMisc.h" 10 | 11 | @interface DVTTextCompletionController (KSImageNamed) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KSImageNamed/DVTTextCompletionListWindowController+KSImageNamed.h: -------------------------------------------------------------------------------- 1 | // 2 | // DVTTextCompletionListWindowController+KSImageNamed.h 3 | // KSImageNamed 4 | // 5 | // Created by Jack Chen on 24/10/2013. 6 | // 7 | // 8 | 9 | #import "XcodeMisc.h" 10 | 11 | @interface DVTTextCompletionListWindowController (KSImageNamed) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamedCompletionStrategy.h: -------------------------------------------------------------------------------- 1 | // 2 | // KSImageNamedCompletionStrategy.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 10/3/15. 6 | // 7 | // 8 | 9 | #import 10 | #import "XcodeMisc.h" 11 | 12 | @interface KSImageNamedCompletionStrategy : DVTTextCompletionStrategy 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamedPreviewWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // KSImageNamedPreviewWindow.h 3 | // KSImageNamed 4 | // 5 | // Created by Friedrich Markgraf on 10.03.13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface KSImageNamedPreviewWindow : NSWindow 12 | 13 | //@property (nonatomic, strong) NSString *descriptionString; 14 | @property (nonatomic, strong) NSImage *image; 15 | 16 | - (void)setFrameTopRightPoint:(NSPoint)point; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /KSImageNamed/IDEIndex+KSImageNamed.m: -------------------------------------------------------------------------------- 1 | // 2 | // IDEIndex+KSImageNamed.m 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/23/13. 6 | // 7 | // 8 | 9 | #import "IDEIndex+KSImageNamed.h" 10 | #import "KSImageNamed.h" 11 | #import "MethodSwizzle.h" 12 | 13 | @implementation IDEIndex (KSImageNamed) 14 | 15 | + (void)load 16 | { 17 | MethodSwizzle(self, @selector(close), @selector(swizzle_close)); 18 | } 19 | 20 | - (void)swizzle_close 21 | { 22 | [[KSImageNamed sharedPlugin] removeImageCompletionsForIndex:self]; 23 | 24 | [self swizzle_close]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /KSImageNamed/IDEWorkspace+KSImageNamed.m: -------------------------------------------------------------------------------- 1 | // 2 | // IDEWorkspace+KSImageNamed.m 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/23/13. 6 | // 7 | // 8 | 9 | #import "IDEWorkspace+KSImageNamed.h" 10 | #import "MethodSwizzle.h" 11 | #import "KSImageNamed.h" 12 | 13 | @implementation IDEWorkspace (KSImageNamed) 14 | 15 | + (void)load 16 | { 17 | MethodSwizzle(self, @selector(_updateIndexableFiles:), @selector(swizzle__updateIndexableFiles:)); 18 | } 19 | 20 | - (void)swizzle__updateIndexableFiles:(id)arg1 21 | { 22 | [self swizzle__updateIndexableFiles:arg1]; 23 | 24 | [[KSImageNamed sharedPlugin] indexNeedsUpdate:[self index]]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamed.h: -------------------------------------------------------------------------------- 1 | // 2 | // KSImageNamed.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 9/10/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, KSImageNamedCompletionStringType) { 12 | KSImageNamedCompletionStringTypeClassAndMethod = 0, 13 | KSImageNamedCompletionStringTypeMethodDeclaration = 1, 14 | KSImageNamedCompletionStringTypeMethodName = 2, 15 | }; 16 | 17 | @class KSImageNamedPreviewWindow; 18 | 19 | @interface KSImageNamed : NSObject 20 | 21 | @property (nonatomic, strong, readonly) KSImageNamedPreviewWindow *imageWindow; 22 | 23 | + (instancetype)sharedPlugin; 24 | + (BOOL)shouldLoadPlugin; 25 | 26 | - (void)indexNeedsUpdate:(id)index; //IDEIndex 27 | - (void)removeImageCompletionsForIndex:(id)index; //IDEIndex 28 | - (NSArray *)imageCompletionsForIndex:(id)index language:(id)language; //IDEIndex 29 | 30 | - (NSSet *)completionStringsForType:(KSImageNamedCompletionStringType)type; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamed.xcplugindata: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | version 6 | 7 | compiler-build 8 | 8201 9 | file-format 10 | 1 11 | 12 | plug-in 13 | 14 | extensions 15 | 16 | KSImageNamed.CompletionStrategy.ImageNamed 17 | 18 | strategyClass 19 | KSImageNamedCompletionStrategy 20 | id 21 | KSImageNamed.CompletionStrategy.ImageNamed 22 | supportedLanguage 23 | 24 | 25 | languageID 26 | Xcode.SourceCodeLanguage.Objective-C 27 | 28 | 29 | languageID 30 | Xcode.SourceCodeLanguage.Swift 31 | 32 | 33 | priority 34 | 10 35 | point 36 | Xcode.DVTKit.TextCompletionStrategy 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /KSImageNamed/MethodSwizzle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MethodSwizzle.h 3 | * 4 | * Copyright (c) 2007-2011 Kent Sutherland 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | * this software and associated documentation files (the "Software"), to deal in 8 | * the Software without restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 10 | * Software, and to permit persons to whom the Software is furnished to do so, 11 | * subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #import 25 | 26 | void MethodSwizzle(Class aClass, SEL orig_sel, SEL alt_sel); 27 | void MethodSwizzleClass(Class aClass, SEL orig_sel, SEL alt_sel); 28 | -------------------------------------------------------------------------------- /KSImageNamed/DVTTextCompletionController+KSImageNamed.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVTTextCompletionController+KSImageNamed.m 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/22/13. 6 | // 7 | // 8 | 9 | #import "DVTTextCompletionController+KSImageNamed.h" 10 | #import "KSImageNamedIndexCompletionItem.h" 11 | #import "MethodSwizzle.h" 12 | #import "KSImageNamed.h" 13 | #import "KSImageNamedPreviewWindow.h" 14 | 15 | @implementation DVTTextCompletionController (KSImageNamed) 16 | 17 | + (void)load 18 | { 19 | MethodSwizzle(self, @selector(acceptCurrentCompletion), @selector(swizzle_acceptCurrentCompletion)); 20 | } 21 | 22 | - (BOOL)swizzle_acceptCurrentCompletion 23 | { 24 | BOOL success = [self swizzle_acceptCurrentCompletion]; 25 | 26 | if (success) { 27 | @try { 28 | NSRange range = [[self textView] selectedRange]; 29 | 30 | for (NSString *nextClassAndMethod in [[KSImageNamed sharedPlugin] completionStringsForType:KSImageNamedCompletionStringTypeClassAndMethod]) { 31 | //If an autocomplete causes imageNamed: to get inserted, remove the token and immediately pop up autocomplete 32 | if (range.location > [nextClassAndMethod length]) { 33 | NSString *insertedString = [[[self textView] string] substringWithRange:NSMakeRange(range.location - [nextClassAndMethod length], [nextClassAndMethod length])]; 34 | 35 | if ([insertedString isEqualToString:nextClassAndMethod]) { 36 | [[self textView] insertText:@"" replacementRange:range]; 37 | [self _showCompletionsAtCursorLocationExplicitly:YES]; 38 | } 39 | } 40 | } 41 | } @catch (NSException *exception) { 42 | //I'd rather not crash if Xcode chokes on something 43 | } 44 | } 45 | 46 | return success; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /KSImageNamed/DVTSourceTextView+KSImageNamed.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVTSourceTextView+KSImageNamed.m 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/19/13. 6 | // 7 | // 8 | 9 | #import "DVTSourceTextView+KSImageNamed.h" 10 | #import "MethodSwizzle.h" 11 | #import "XcodeMisc.h" 12 | #import "KSImageNamed.h" 13 | 14 | @implementation DVTSourceTextView (KSImageNamedSwizzle) 15 | 16 | + (void)load 17 | { 18 | MethodSwizzle(self, 19 | @selector(shouldAutoCompleteAtLocation:), 20 | @selector(swizzle_shouldAutoCompleteAtLocation:)); 21 | } 22 | 23 | - (BOOL)swizzle_shouldAutoCompleteAtLocation:(unsigned long long)arg1 24 | { 25 | BOOL shouldAutoComplete = [self swizzle_shouldAutoCompleteAtLocation:arg1]; 26 | 27 | if (!shouldAutoComplete) { 28 | @try { 29 | //Ensure that image autocomplete automatically pops up when you type imageNamed: 30 | //Search backwards from the current line 31 | NSRange range = NSMakeRange(0, arg1); 32 | NSString *string = [[self textStorage] string]; 33 | NSRange newlineRange = [string rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch range:range]; 34 | NSString *line = string; 35 | 36 | if (newlineRange.location != NSNotFound) { 37 | NSRange lineRange = NSMakeRange(newlineRange.location, arg1 - newlineRange.location); 38 | 39 | if (lineRange.location < [line length] && NSMaxRange(lineRange) < [line length]) { 40 | line = [string substringWithRange:lineRange]; 41 | } 42 | } 43 | 44 | for (NSString *nextClassAndMethod in [[KSImageNamed sharedPlugin] completionStringsForType:KSImageNamedCompletionStringTypeClassAndMethod]) { 45 | if ([line hasSuffix:nextClassAndMethod]) { 46 | shouldAutoComplete = YES; 47 | break; 48 | } 49 | } 50 | } @catch (NSException *exception) { 51 | //I'd rather not crash if Xcode chokes on something 52 | } 53 | } 54 | 55 | return shouldAutoComplete; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamed-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.ksuther.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 2 25 | CFPlugInDynamicRegisterFunction 26 | 27 | CFPlugInDynamicRegistration 28 | NO 29 | CFPlugInFactories 30 | 31 | 00000000-0000-0000-0000-000000000000 32 | MyFactoryFunction 33 | 34 | CFPlugInTypes 35 | 36 | 00000000-0000-0000-0000-000000000000 37 | 38 | 00000000-0000-0000-0000-000000000000 39 | 40 | 41 | CFPlugInUnloadFunction 42 | 43 | NSHumanReadableCopyright 44 | Copyright © Kent Sutherland 45 | XCGCReady 46 | 47 | XCPluginHasUI 48 | 49 | XC4Compatible 50 | 51 | DVTPlugInCompatibilityUUIDs 52 | 53 | DFFB3951-EB0A-4C09-9DAC-5F2D28CC839C 54 | DA4FDFD8-C509-4D8B-8B55-84A7B66AE701 55 | 7FDF5C7A-131F-4ABB-9EDC-8C5F8F0B8A90 56 | 0420B86A-AA43-4792-9ED0-6FE0F2B16A13 57 | CC0D0F4F-05B3-431A-8F33-F84AFCB2C651 58 | 7265231C-39B4-402C-89E1-16167C4CC990 59 | F41BD31E-2683-44B8-AE7F-5F09E919790E 60 | ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C 61 | 8A66E736-A720-4B3C-92F1-33D9962C69DF 62 | E0A62D1F-3C18-4D74-BFE5-A4167D643966 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /KSImageNamed/DVTTextCompletionListWindowController+KSImageNamed.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVTTextCompletionListWindowController+KSImageNamed.m 3 | // KSImageNamed 4 | // 5 | // Created by Jack Chen on 24/10/2013. 6 | // 7 | // 8 | 9 | #import "DVTTextCompletionListWindowController+KSImageNamed.h" 10 | #import "MethodSwizzle.h" 11 | #import "KSImageNamedIndexCompletionItem.h" 12 | #import "KSImageNamed.h" 13 | #import "KSImageNamedPreviewWindow.h" 14 | 15 | @implementation DVTTextCompletionListWindowController (KSImageNamed) 16 | 17 | + (void)load 18 | { 19 | MethodSwizzle(self, @selector(showInfoPaneForCompletionItem:), @selector(swizzle_showInfoPaneForCompletionItem:)); 20 | MethodSwizzle(self, @selector(_hideWindow), @selector(swizzle__hideWindow)); 21 | } 22 | 23 | - (void)swizzle_showInfoPaneForCompletionItem:(id)item 24 | { 25 | [self swizzle_showInfoPaneForCompletionItem:item]; 26 | 27 | if ([item isKindOfClass:[KSImageNamedIndexCompletionItem class]]) { 28 | NSImage *image = [[NSImage alloc] initWithContentsOfURL:((KSImageNamedIndexCompletionItem *)item).imageFileURL]; 29 | [self showPreviewForImage:image]; 30 | } 31 | } 32 | 33 | - (void)swizzle__hideWindow 34 | { 35 | [[KSImageNamed sharedPlugin].imageWindow orderOut:self]; 36 | [self swizzle__hideWindow]; 37 | } 38 | 39 | - (void)showPreviewForImage:(NSImage *)image 40 | { 41 | KSImageNamedPreviewWindow *imageWindow = [KSImageNamed sharedPlugin].imageWindow; 42 | 43 | imageWindow.image = image; 44 | 45 | if (!image) { 46 | [imageWindow orderOut:self]; 47 | } else { 48 | NSRect imgRect = NSMakeRect(0.0, 0.0, image.size.width, image.size.height); 49 | 50 | NSImageView *imageView = [[NSImageView alloc] initWithFrame:imgRect]; 51 | imageView.image = image; 52 | 53 | NSWindow *completionListWindow = [self window]; 54 | 55 | if ([completionListWindow isVisible]) { 56 | NSRect completionListWindowFrame = completionListWindow ? completionListWindow.frame : NSMakeRect(image.size.width, image.size.height, 0.0, 0.0); 57 | 58 | [imageWindow setFrameTopRightPoint:NSMakePoint(completionListWindowFrame.origin.x - 1.0, 59 | completionListWindowFrame.origin.y + completionListWindowFrame.size.height)]; 60 | 61 | [[NSApp keyWindow] addChildWindow:imageWindow ordered:NSWindowAbove]; 62 | } 63 | } 64 | } 65 | @end 66 | -------------------------------------------------------------------------------- /KSImageNamed/MethodSwizzle.m: -------------------------------------------------------------------------------- 1 | /* 2 | * MethodSwizzle.m 3 | * 4 | * Copyright (c) 2007-2011 Kent Sutherland 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | * this software and associated documentation files (the "Software"), to deal in 8 | * the Software without restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 10 | * Software, and to permit persons to whom the Software is furnished to do so, 11 | * subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #import "MethodSwizzle.h" 25 | #import "KSImageNamed.h" 26 | #import 27 | 28 | void MethodSwizzle(Class aClass, SEL orig_sel, SEL alt_sel) 29 | { 30 | if ([KSImageNamed shouldLoadPlugin]) { 31 | Method orig_method = nil, alt_method = nil; 32 | 33 | // First, look for the methods 34 | orig_method = class_getInstanceMethod(aClass, orig_sel); 35 | alt_method = class_getInstanceMethod(aClass, alt_sel); 36 | 37 | // If both are found, swizzle them 38 | if ((orig_method != nil) && (alt_method != nil)) { 39 | method_exchangeImplementations(orig_method, alt_method); 40 | } 41 | } 42 | } 43 | 44 | void MethodSwizzleClass(Class aClass, SEL orig_sel, SEL alt_sel) 45 | { 46 | if ([KSImageNamed shouldLoadPlugin]) { 47 | Method orig_method = nil, alt_method = nil; 48 | 49 | // First, look for the methods 50 | orig_method = class_getClassMethod(aClass, orig_sel); 51 | alt_method = class_getClassMethod(aClass, alt_sel); 52 | 53 | // If both are found, swizzle them 54 | if ((orig_method != nil) && (alt_method != nil)) { 55 | method_exchangeImplementations(orig_method, alt_method); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /KSImageNamed/Completions.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | classAndMethod 7 | mage imageNamed: 8 | methodDeclaration 9 | imageNamed: 10 | methodName 11 | imageNamed 12 | comment 13 | Standard NSImage/UIImage method in Objective-C 14 | 15 | 16 | classAndMethod 17 | Image.init(named: 18 | methodDeclaration 19 | init(named: 20 | methodName 21 | init(named: 22 | comment 23 | Standard NSImage/UIImage method in Swift 24 | 25 | 26 | classAndMethod 27 | Image(named: 28 | methodDeclaration 29 | Image(named: 30 | methodName 31 | Image(named: 32 | comment 33 | Shorthand NSImage/UIImage init in Swift 34 | 35 | 36 | classAndMethod 37 | prite spriteWithFile: 38 | methodDeclaration 39 | spriteWithFile: 40 | methodName 41 | spriteWithFile 42 | comment 43 | cocos2d's CCSprite 44 | 45 | 46 | classAndMethod 47 | priteFrame frameWithImageNamed: 48 | methodDeclaration 49 | frameWithImageNamed: 50 | methodName 51 | frameWithImageNamed 52 | comment 53 | cocos2d's CCSpriteFrame 54 | 55 | 56 | classAndMethod 57 | ode spriteNodeWithImageNamed: 58 | methodDeclaration 59 | spriteNodeWithImageNamed: 60 | methodName 61 | spriteNodeWithImageNamed 62 | comment 63 | SpriteKit's sprite node 64 | 65 | 66 | classAndMethod 67 | ure textureWithImageNamed: 68 | methodDeclaration 69 | textureWithImageNamed: 70 | methodName 71 | textureWithImageNamed 72 | comment 73 | SpriteKit's SKTexture 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KSImageNamed-Xcode 2 | --- 3 | 4 | ## What is this? 5 | 6 | Can't remember whether that image you just added to the project was called `button-separator-left` or `button-left-separator`? Now you don't have to, because this will autocomplete your `imageNamed:` calls like you'd expect. Just type in `[NSImage imageNamed:` or `[UIImage imageNamed:` and all the images in your project will conveniently appear in the autocomplete menu. You'll even get a handy preview of the image you're about to select. 7 | 8 | Developed and tested against Xcode 7. Objective-C and Swift are both supported. 9 | 10 | ![Screenshot](https://raw.github.com/ksuther/KSImageNamed-Xcode/master/screenshot.gif) 11 | 12 | ## How do I use it? 13 | 14 | ### Manually 15 | 16 | Build the KSImageNamed target in the Xcode project and the plug-in will automatically be installed in `~/Library/Developer/Xcode/Plug-ins`. Relaunch Xcode and `imageNamed:` will magically start autocompleting your images. 17 | 18 | **Important**: Old versions of KSImageNamed were installed in `~/Library/Developer/Application Support/Developer/Shared/Xcode/Plug-ins`. Make sure to remove `KSImageNamed.xcplugin` from there before installing the new one. 19 | 20 | ### Alcatraz 21 | 22 | Install [Alcatraz](http://alcatraz.io/), restart Xcode and press ⇧⌘9. You can find `KSImageNamed` in the list and click the icon on the left to install. 23 | 24 | ## How do I include file extensions when autocompleting? 25 | 26 | Enter the following command and relaunch Xcode: 27 | `defaults write com.apple.dt.Xcode KSShowExtensionInImageCompletion -bool YES` 28 | 29 | ## Possible future improvements 30 | 31 | Ideas for people who might want to hack on this: 32 | 33 | 1. Only include images that are in the current project. Currently all images in the workspace are shown. 34 | 2. Show an image preview and dimensions when clicking on an imageNamed: string in the editor 35 | 36 | ## License 37 | 38 | MIT License 39 | 40 | Copyright (c) 2013 Kent Sutherland 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy of 43 | this software and associated documentation files (the "Software"), to deal in 44 | the Software without restriction, including without limitation the rights to use, 45 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 46 | Software, and to permit persons to whom the Software is furnished to do so, 47 | subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in all 50 | copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 54 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 55 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 56 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 57 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 | -------------------------------------------------------------------------------- /KSImageNamed/DVTTextCompletionSession+KSImageNamed.m: -------------------------------------------------------------------------------- 1 | // 2 | // DVTTextCompletionSession+KSImageNamed.m 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 11/1/15. 6 | // 7 | // 8 | 9 | #import "DVTTextCompletionSession+KSImageNamed.h" 10 | #import "KSImageNamedIndexCompletionItem.h" 11 | #import "MethodSwizzle.h" 12 | 13 | @implementation DVTTextCompletionSession (KSImageNamed) 14 | 15 | + (void)load 16 | { 17 | MethodSwizzle(self, @selector(replacementRangeForSuggestedRange:), @selector(swizzle_replacementRangeForSuggestedRange:)); 18 | } 19 | 20 | - (NSRange)swizzle_replacementRangeForSuggestedRange:(NSRange)arg1 21 | { 22 | NSInteger selectedIndex = [self selectedCompletionIndex]; 23 | 24 | if (selectedIndex != -1) { 25 | id completion = [[self filteredCompletionsAlpha] objectAtIndex:selectedIndex]; 26 | 27 | if ([completion isKindOfClass:[KSImageNamedIndexCompletionItem class]]) { 28 | NSTextView *textView = [self textView]; 29 | NSRange selectedRange = [textView selectedRange]; 30 | 31 | // Check if we need to replace redundant text 32 | // This can happen in the following situation: 33 | // - Type in [NSImage imageNamed:@"image"] 34 | // - Move insertion point inside image, such as @"ima|ge" 35 | // - Press escape or F5 to trigger completion 36 | // - Accept the completion 37 | // Without this extra handling you would end up with @"ima@"image"ge 38 | if (selectedRange.length == 0 && selectedRange.location <= NSMaxRange(arg1)) { 39 | NSString *string = [[textView textStorage] string]; 40 | NSString *completionText = [completion completionText]; 41 | NSString *completionName = [completion name]; 42 | 43 | if (NSMaxRange(arg1) - selectedRange.location == 0) { 44 | // The completion is being accepted (through insertCurrentCompletion) 45 | // We want to include the entire string (include the leading and trailing quotation marks) to make sure it all gets replaced 46 | NSUInteger offsetInCompletionString = [completionText rangeOfString:completionName].location; 47 | NSString *textBeforeCompletionRange = [string substringWithRange:NSMakeRange(arg1.location - offsetInCompletionString, offsetInCompletionString)]; 48 | 49 | if (offsetInCompletionString != NSNotFound && [textBeforeCompletionRange isEqualToString:[completionText substringToIndex:offsetInCompletionString]]) { 50 | arg1.location -= offsetInCompletionString; 51 | arg1.length += offsetInCompletionString; 52 | } 53 | } 54 | 55 | // Replace up to the next quotation mark on the same line 56 | NSRange lineRange = [string lineRangeForRange:arg1]; 57 | NSRange nextQuoteRange = [string rangeOfString:@"\"" options:0 range:NSMakeRange(NSMaxRange(arg1), NSMaxRange(lineRange) - NSMaxRange(arg1))]; 58 | 59 | if (nextQuoteRange.location != NSNotFound) { 60 | return NSMakeRange(arg1.location, nextQuoteRange.location - arg1.location + 1); 61 | } 62 | } 63 | } 64 | } 65 | 66 | return [self swizzle_replacementRangeForSuggestedRange:arg1]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamedIndexCompletionItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // KSImageNamedIndexCompletionItem.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 9/10/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DVTSourceCodeSymbolKind : NSObject 12 | { 13 | NSString *_identifier; 14 | NSString *_localizedDescription; 15 | NSArray *_conformedToSymbolKindIdentifiers; 16 | NSArray *_conformedToSymbolKinds; 17 | NSArray *_allConformingSymbolKinds; 18 | } 19 | 20 | + (id)sourceCodeSymbolKinds; 21 | + (id)sourceCodeSymbolKindForIdentifier:(id)arg1; 22 | + (id)_sourceCodeSymbolKindForExtension:(id)arg1; 23 | + (void)initialize; 24 | + (id)classMethodTemplateSymbolKind; 25 | + (id)instanceMethodTemplateSymbolKind; 26 | + (id)functionTemplateSymbolKind; 27 | + (id)classTemplateSymbolKind; 28 | + (id)namespaceSymbolKind; 29 | + (id)ibOutletCollectionPropertySymbolKind; 30 | + (id)ibOutletCollectionVariableSymbolKind; 31 | + (id)ibOutletCollectionSymbolKind; 32 | + (id)ibOutletPropertySymbolKind; 33 | + (id)ibOutletVariableSymbolKind; 34 | + (id)ibOutletSymbolKind; 35 | + (id)ibActionMethodSymbolKind; 36 | + (id)globalVariableSymbolKind; 37 | + (id)localVariableSymbolKind; 38 | + (id)unionSymbolKind; 39 | + (id)typedefSymbolKind; 40 | + (id)structSymbolKind; 41 | + (id)protocolSymbolKind; 42 | + (id)propertySymbolKind; 43 | + (id)parameterSymbolKind; 44 | + (id)macroSymbolKind; 45 | + (id)classVariableSymbolKind; 46 | + (id)instanceVariableSymbolKind; 47 | + (id)instanceMethodSymbolKind; 48 | + (id)functionSymbolKind; 49 | + (id)fieldSymbolKind; 50 | + (id)enumConstantSymbolKind; 51 | + (id)enumSymbolKind; 52 | + (id)classSymbolKind; 53 | + (id)classMethodSymbolKind; 54 | + (id)categorySymbolKind; 55 | + (id)memberContainerSymbolKind; 56 | + (id)memberSymbolKind; 57 | + (id)callableSymbolKind; 58 | + (id)globalSymbolKind; 59 | + (id)containerSymbolKind; 60 | @property(readonly) NSString *localizedDescription; // @synthesize localizedDescription=_localizedDescription; 61 | @property(readonly) NSString *identifier; // @synthesize identifier=_identifier; 62 | - (BOOL)conformsToSymbolKind:(id)arg1; 63 | @property(readonly, getter=isContainer) BOOL container; 64 | @property(readonly) NSArray *allConformingSymbolKinds; 65 | @property(readonly) NSArray *conformedToSymbolKinds; 66 | - (id)copyWithZone:(struct _NSZone *)arg1; 67 | - (id)description; 68 | - (id)initWithSourceCodeSymbolKindExtension:(id)arg1; 69 | 70 | @end 71 | 72 | @interface IDEIndexCompletionItem : NSObject 73 | { 74 | void *_completionResult; 75 | NSString *_displayText; 76 | NSString *_displayType; 77 | NSString *_completionText; 78 | NSAttributedString *_descriptionText; 79 | NSString *_parentText; 80 | DVTSourceCodeSymbolKind *_symbolKind; 81 | double _priority; 82 | NSString *_name; 83 | BOOL _notRecommended; 84 | double _fuzzyMatchingScore; 85 | } 86 | 87 | @property double fuzzyMatchingScore; // @synthesize fuzzyMatchingScore=_fuzzyMatchingScore; 88 | @property double priority; // @synthesize priority=_priority; 89 | @property(readonly) NSString *name; // @synthesize name=_name; 90 | @property(readonly) BOOL notRecommended; 91 | @property(readonly) DVTSourceCodeSymbolKind *symbolKind; 92 | @property(readonly) NSAttributedString *descriptionText; 93 | @property(readonly, copy) NSString *parentText; 94 | @property(readonly) NSString *completionText; 95 | @property(readonly) NSString *displayType; 96 | @property(readonly) NSString *displayText; 97 | - (void)_fillInTheRest; 98 | - (id)description; 99 | - (id)initWithCompletionResult:(void *)arg1; 100 | 101 | @end 102 | 103 | @interface KSImageNamedIndexCompletionItem : IDEIndexCompletionItem 104 | 105 | @property(nonatomic, strong) NSURL *fileURL; 106 | @property(nonatomic, strong, readonly) NSURL *imageFileURL; //derived from fileURL 107 | @property(nonatomic, strong, readonly) NSString *fileName; 108 | @property(nonatomic, assign) BOOL has1x; 109 | @property(nonatomic, assign) BOOL has2x; 110 | @property(nonatomic, assign) BOOL forSwift; 111 | @property(nonatomic, assign, getter=isInAssetCatalog, readonly) BOOL inAssetCatalog; 112 | 113 | - (id)initWithFileURL:(NSURL *)fileURL includeExtension:(BOOL)includeExtension; 114 | - (id)initWithAssetFileURL:(NSURL *)fileURL namespace:(NSString *)namespace; 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamedIndexCompletionItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // KSImageNamedIndexCompletionItem.m 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 9/10/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "KSImageNamedIndexCompletionItem.h" 10 | #import 11 | 12 | @interface KSImageNamedIndexCompletionItem () { 13 | BOOL _imageIncludeExtension; 14 | } 15 | 16 | @property(nonatomic, assign, getter=isInAssetCatalog) BOOL inAssetCatalog; 17 | @property(nonatomic, copy) NSString *namespace; 18 | 19 | @end 20 | 21 | @implementation KSImageNamedIndexCompletionItem 22 | 23 | - (id)initWithFileURL:(NSURL *)fileURL includeExtension:(BOOL)includeExtension 24 | { 25 | if ( (self = [super init]) ) { 26 | [self setFileURL:fileURL]; 27 | 28 | _imageIncludeExtension = includeExtension; 29 | } 30 | return self; 31 | } 32 | 33 | - (id)initWithAssetFileURL:(NSURL *)fileURL namespace:(NSString *)namespace 34 | { 35 | if ( (self = [super init]) ) { 36 | [self setFileURL:fileURL]; 37 | [self setInAssetCatalog:YES]; 38 | [self setNamespace:namespace]; 39 | 40 | _imageIncludeExtension = NO; 41 | } 42 | return self; 43 | } 44 | 45 | - (void)_fillInTheRest 46 | { 47 | 48 | } 49 | 50 | - (double)priority 51 | { 52 | return 9999; 53 | } 54 | 55 | - (NSURL *)imageFileURL 56 | { 57 | NSURL *imageFileURL; 58 | 59 | if ([self isInAssetCatalog]) { 60 | //Pull the first image out of the imageset's Contents.json 61 | NSURL *contentsURL = [[self fileURL] URLByAppendingPathComponent:@"Contents.json"]; 62 | NSData *contentsData = [NSData dataWithContentsOfURL:contentsURL]; 63 | 64 | if (contentsData) { 65 | NSDictionary *contentsJSON = [NSJSONSerialization JSONObjectWithData:contentsData options:0 error:NULL]; 66 | 67 | if ([contentsJSON isKindOfClass:[NSDictionary class]]) { 68 | NSArray *images = [contentsJSON objectForKey:@"images"]; 69 | 70 | // Ignore idiom, scale, slicing for now 71 | for (NSDictionary *nextImageDictionary in images) { 72 | NSString *filename = [nextImageDictionary objectForKey:@"filename"]; 73 | 74 | if (filename) { 75 | imageFileURL = [[self fileURL] URLByAppendingPathComponent:filename]; 76 | break; 77 | } 78 | } 79 | } 80 | } 81 | } else { 82 | imageFileURL = [self fileURL]; 83 | } 84 | 85 | return imageFileURL; 86 | } 87 | 88 | - (NSString *)fileName 89 | { 90 | return [self _fileName]; 91 | } 92 | 93 | - (NSString *)name 94 | { 95 | return [self _fileName]; 96 | } 97 | 98 | - (BOOL)notRecommended 99 | { 100 | return NO; 101 | } 102 | 103 | - (DVTSourceCodeSymbolKind *)symbolKind 104 | { 105 | return nil; 106 | } 107 | 108 | - (NSString *)completionText 109 | { 110 | return [self _imageNamedText]; 111 | } 112 | 113 | - (NSString *)displayType 114 | { 115 | return @"NSString *"; 116 | } 117 | 118 | - (NSString *)displayText 119 | { 120 | NSString *displayFormat = @"%@ (%@)"; 121 | 122 | if (self.has1x && self.has2x) { 123 | displayFormat = @"%@ (%@, 1x and 2x)"; 124 | } else if (self.has1x) { 125 | displayFormat = @"%@ (%@, 1x only)"; 126 | } else if (self.has2x) { 127 | displayFormat = @"%@ (%@, 2x only)"; 128 | } 129 | 130 | return [NSString stringWithFormat:displayFormat, [self _imageNamedText], [[self fileURL] pathExtension]]; 131 | } 132 | 133 | - (NSString *)_fileName 134 | { 135 | NSString *fileName = [[self fileURL] lastPathComponent]; 136 | NSString *imageName = [fileName stringByDeletingPathExtension]; 137 | 138 | if ([imageName hasSuffix:@"@2x"]) { 139 | fileName = [[imageName substringToIndex:[imageName length] - 3] stringByAppendingFormat:@".%@", [fileName pathExtension]]; 140 | } else if ([imageName hasSuffix:@"@2x~ipad"]) { 141 | //2x iPad images need to be handled separately since (image~ipad and image@2x~ipad are valid pairs) 142 | fileName = [[[imageName substringToIndex:[imageName length] - 8] stringByAppendingString:@"~ipad"] stringByAppendingFormat:@".%@", [fileName pathExtension]]; 143 | } 144 | if (!_imageIncludeExtension) { 145 | fileName = [fileName stringByDeletingPathExtension]; 146 | } 147 | 148 | if ([self isInAssetCatalog] && [self namespace]) { 149 | fileName = [[self namespace] stringByAppendingPathComponent:fileName]; 150 | } 151 | 152 | return fileName; 153 | } 154 | 155 | - (NSString *)_imageNamedText 156 | { 157 | if ([self forSwift]) { 158 | return [NSString stringWithFormat:@"\"%@\"", [self _fileName]]; 159 | } else { 160 | return [NSString stringWithFormat:@"@\"%@\"", [self _fileName]]; 161 | } 162 | } 163 | 164 | @end 165 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamedPreviewWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // KSImageNamedPreviewWindow.m 3 | // KSImageNamed 4 | // 5 | // Created by Friedrich Markgraf on 10.03.13. 6 | // 7 | // 8 | 9 | #import "KSImageNamedPreviewWindow.h" 10 | 11 | @interface KSImageNamedPreviewWindow () { 12 | NSView *_contentView; 13 | NSTextField *_scalingLabel; 14 | NSTextField *_sizeLabel; 15 | NSImageView *_imageView; 16 | NSPoint _frameTopRightPoint; 17 | } 18 | @end 19 | 20 | @implementation KSImageNamedPreviewWindow 21 | 22 | - (instancetype)init 23 | { 24 | NSRect frame = NSMakeRect(0.0, 0.0, 10.0, 50.0); 25 | if ( (self = [super initWithContentRect:frame 26 | styleMask:NSBorderlessWindowMask 27 | backing:NSBackingStoreBuffered 28 | defer:NO]) ) { 29 | self.hasShadow = YES; 30 | _frameTopRightPoint = NSMakePoint(10.0, 50.0); 31 | 32 | _contentView = [[NSView alloc] initWithFrame:frame]; 33 | self.contentView = _contentView; 34 | 35 | _scalingLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(0.0, 33.0, 120.0, 16.0)]; 36 | _scalingLabel.autoresizingMask = NSViewMaxXMargin | NSViewMinYMargin; 37 | _scalingLabel.textColor = [NSColor blueColor]; 38 | _scalingLabel.bezeled = NO; 39 | _scalingLabel.drawsBackground = NO; 40 | _scalingLabel.editable = NO; 41 | _scalingLabel.selectable = NO; 42 | _scalingLabel.alignment = NSLeftTextAlignment; 43 | [_contentView addSubview:_scalingLabel]; 44 | 45 | _sizeLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(0.0, 33.0, 10.0, 16.0)]; 46 | _sizeLabel.autoresizingMask = NSViewWidthSizable | NSViewMinYMargin; 47 | _sizeLabel.font = [NSFont labelFontOfSize:[NSFont labelFontSize]]; 48 | _sizeLabel.textColor = [NSColor textColor]; 49 | _sizeLabel.bezeled = NO; 50 | _sizeLabel.drawsBackground = NO; 51 | _sizeLabel.editable = NO; 52 | _sizeLabel.selectable = YES; 53 | _sizeLabel.alignment = NSRightTextAlignment; 54 | [_contentView addSubview:_sizeLabel]; 55 | 56 | _imageView = [[NSImageView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)]; 57 | _imageView.wantsLayer = YES; 58 | _imageView.layer.borderColor = [[NSColor colorWithCalibratedWhite:0.0 alpha:0.3] CGColor]; 59 | _imageView.layer.borderWidth = 1.0; 60 | [_contentView addSubview:_imageView]; 61 | } 62 | return self; 63 | } 64 | 65 | - (void)setImage:(NSImage *)image 66 | { 67 | _image = image; 68 | NSString *infoString = @""; 69 | if (image) { 70 | CGFloat width = image.size.width; 71 | CGFloat height = image.size.height; 72 | for (NSImageRep *representation in image.representations) { 73 | width = fmax(width, representation.pixelsWide); 74 | height = fmax(height, representation.pixelsHigh); 75 | } 76 | infoString = [NSString stringWithFormat:@"%d × %d", (int)round(width), (int)round(height)]; 77 | } 78 | _sizeLabel.stringValue = infoString; 79 | 80 | [self _updateDisplay]; 81 | } 82 | 83 | - (void)setFrameTopRightPoint:(NSPoint)point 84 | { 85 | _frameTopRightPoint = point; 86 | [self _updateDisplay]; 87 | } 88 | 89 | - (void)_updateDisplay 90 | { 91 | int factor = 1; 92 | if (!_image) { 93 | return; 94 | } 95 | 96 | //Crash on multi monitors(Display) becuase some time value is in -ve 97 | NSPoint tempPoint = CGPointMake(fabs(_frameTopRightPoint.x), fabs(_frameTopRightPoint.y)); 98 | 99 | //if image doesn't fit screen, scale by even factors until it does 100 | while ((tempPoint.y < (_image.size.height / factor)) || (tempPoint.x < (_image.size.width / factor))) { 101 | factor += 1; 102 | } 103 | 104 | if (factor == 1) { 105 | _scalingLabel.stringValue = @""; 106 | } 107 | else { 108 | _scalingLabel.stringValue = [NSString stringWithFormat:@"(Scaled to 1/%d)", factor]; 109 | } 110 | 111 | NSSize imageSize = NSMakeSize(_image.size.width / (CGFloat)factor, _image.size.height / (CGFloat)factor); 112 | 113 | //ensure window is wide enough to display size info 114 | CGFloat stringWidth = [_sizeLabel.stringValue sizeWithAttributes: @{ NSFontAttributeName : _sizeLabel.font }].width; 115 | CGFloat width = fmax(stringWidth + 6.0, imageSize.width); 116 | 117 | NSRect displayFrame = NSMakeRect(_frameTopRightPoint.x - width, 118 | _frameTopRightPoint.y - imageSize.height - _sizeLabel.frame.size.height, 119 | width, 120 | imageSize.height + _sizeLabel.frame.size.height); 121 | 122 | _imageView.frame = NSMakeRect(width - imageSize.width, 0.0, imageSize.width, imageSize.height); 123 | _imageView.image = _image; 124 | 125 | [self setFrame:displayFrame display:YES animate:NO]; 126 | 127 | _contentView.frame = NSMakeRect(0.0, 0.0, displayFrame.size.width, displayFrame.size.height); 128 | } 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamedCompletionStrategy.m: -------------------------------------------------------------------------------- 1 | // 2 | // KSImageNamedCompletionStrategy.m 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 10/3/15. 6 | // 7 | // 8 | 9 | #import "KSImageNamedCompletionStrategy.h" 10 | #import "KSImageNamed.h" 11 | #import "XcodeMisc.h" 12 | 13 | @implementation KSImageNamedCompletionStrategy 14 | 15 | - (id)completionItemsForDocumentLocation:(DVTTextDocumentLocation *)arg1 context:(NSDictionary *)arg2 highlyLikelyCompletionItems:(id *)arg3 areDefinitive:(char *)arg4 16 | { 17 | NSArray *completions; 18 | id language = [arg2 objectForKey:@"DVTTextCompletionContextSourceCodeLanguage"]; 19 | 20 | @try { 21 | BOOL atImageNamed = NO; 22 | NSRange selectedRange = [arg1 characterRange]; 23 | NSString *string = [arg2 objectForKey:@"DVTTextCompletionContextTextStorageString"]; 24 | id textStorage = [arg2 objectForKey:@"DVTTextCompletionContextTextStorage"]; 25 | 26 | if ([[language identifier] isEqualToString:@"Xcode.SourceCodeLanguage.Swift"]) { 27 | // sourceModel isn't available in Swift, check the string manually 28 | NSRange newlineRange = [string rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch range:NSMakeRange(0, NSMaxRange(selectedRange))]; 29 | 30 | if (newlineRange.location != NSNotFound) { 31 | NSString *lineString = [string substringWithRange:NSMakeRange(newlineRange.location, NSMaxRange(selectedRange) - newlineRange.location)]; 32 | 33 | for (NSString *nextString in [[KSImageNamed sharedPlugin] completionStringsForType:KSImageNamedCompletionStringTypeClassAndMethod]) { 34 | if ([lineString hasSuffix:nextString]) { 35 | atImageNamed = YES; 36 | break; 37 | } 38 | } 39 | } 40 | } else { 41 | id item = [[textStorage sourceModel] enclosingItemAtLocation:selectedRange.location]; 42 | 43 | id previousItem = [item previousItem]; 44 | NSString *itemString; 45 | 46 | if (item) { 47 | NSRange itemRange = [item range]; 48 | 49 | if (NSMaxRange(itemRange) > selectedRange.location) { 50 | itemRange.length -= NSMaxRange(itemRange) - selectedRange.location; 51 | } 52 | 53 | itemString = [string substringWithRange:itemRange]; 54 | 55 | //Limit search to a single line 56 | //itemRange can be massive in some situations, such as -(void) 57 | NSRange newlineRange = [itemString rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch]; 58 | 59 | if (newlineRange.location != NSNotFound) { 60 | itemRange.length = itemRange.length - newlineRange.location; 61 | itemRange.location = itemRange.location + newlineRange.location; 62 | 63 | //Extra range check to prevent huge itemRange.location 64 | //Checking length and NSMaxRange in case NSMaxRange overflows 65 | if (itemRange.length < [string length] && NSMaxRange(itemRange) < [string length]) { 66 | itemString = [string substringWithRange:itemRange]; 67 | } 68 | } 69 | 70 | for (NSString *nextMethodDeclaration in [[KSImageNamed sharedPlugin] completionStringsForType:KSImageNamedCompletionStringTypeMethodDeclaration]) { 71 | NSRange imageNamedRange = [itemString rangeOfString:nextMethodDeclaration]; 72 | 73 | if (imageNamedRange.location != NSNotFound) { 74 | atImageNamed = YES; 75 | 76 | //We might be past imageNamed, such as 'imageNamed:@"name"] draw' 77 | //For now just check if the insertion point is past the closing bracket. This won't work if an image has a bracket in the name and other edge cases. 78 | //It'd probably be cleaner to use the source model to determine this 79 | NSRange closeBracketRange = [itemString rangeOfString:@"]" options:0 range:NSMakeRange(imageNamedRange.location, [itemString length] - imageNamedRange.location)]; 80 | 81 | if (closeBracketRange.location != NSNotFound) { 82 | atImageNamed = NO; 83 | } 84 | } 85 | } 86 | } 87 | 88 | if (!atImageNamed && previousItem) { 89 | NSRange previousItemRange = [previousItem range]; 90 | 91 | if (NSMaxRange(previousItemRange) > selectedRange.location) { 92 | previousItemRange.length -= NSMaxRange(previousItemRange) - selectedRange.location; 93 | } 94 | 95 | //Enlarge previousItemRange to ensure we're at a method call and not a variable declaration or something else 96 | //For example, previousItemRange could be hitting a variable declaration such as "NSImage *imageNamed = [" (issue #34) 97 | if (previousItemRange.location > 0) { 98 | previousItemRange.location--; 99 | previousItemRange.length += 2; 100 | } 101 | 102 | NSString *previousItemString = [string substringWithRange:previousItemRange]; 103 | 104 | if ([[[KSImageNamed sharedPlugin] completionStringsForType:KSImageNamedCompletionStringTypeMethodDeclaration] containsObject:previousItemString]) { 105 | atImageNamed = YES; 106 | } 107 | } 108 | } 109 | 110 | if (atImageNamed) { 111 | IDEWorkspace *workspace = [arg2 objectForKey:@"IDETextCompletionContextWorkspaceKey"]; 112 | IDEIndex *index = [workspace index]; 113 | 114 | completions = [[KSImageNamed sharedPlugin] imageCompletionsForIndex:index language:language]; 115 | 116 | if ([completions count] > 0) { 117 | // This makes it so that only image suggestions are shown (setting arg4 to 1 halts subsequent strategies) 118 | *arg3 = completions; 119 | *arg4 = 1; 120 | } 121 | } 122 | } @catch (NSException *exception) { 123 | //Handle this or something 124 | } 125 | 126 | return completions; 127 | } 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /KSImageNamed/XcodeMisc.h: -------------------------------------------------------------------------------- 1 | // 2 | // XcodeMisc.h 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 1/19/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | //Miscellaneous declarations pulled from class dumps of DVTFoundation, DVTKit, IDEFoundation, IDEKit 12 | 13 | @interface IDEIndex : NSObject 14 | - (void)close; 15 | @end 16 | 17 | @interface IDEWorkspace : NSObject 18 | @property(retain) IDEIndex *index; 19 | 20 | - (void)_updateIndexableFiles:(id)arg1; 21 | @end 22 | 23 | @interface IDEIndexCollection : NSObject 24 | { 25 | //IDEIndexDBTempTable *_tempTable; 26 | NSArray *_instantiatedRows; 27 | } 28 | 29 | //@property(readonly, nonatomic) IDEIndexDBTempTable *tempTable; // @synthesize tempTable=_tempTable; 30 | - (id)uniqueObjects; 31 | - (id)onlyObject; 32 | - (id)firstObject; 33 | //- (id)instantiateRow:(struct sqlite3_stmt *)arg1; 34 | - (id)tempTableSchema; 35 | - (id)allObjects; 36 | //- (unsigned long long)countByEnumeratingWithState:(CDStruct_70511ce9 *)arg1 objects:(id *)arg2 count:(unsigned long long)arg3; 37 | - (unsigned long long)instantiateRowsUpto:(unsigned long long)arg1; 38 | - (void)finalize; 39 | - (void)dropTempTable; 40 | - (id)description; 41 | - (id)initWithConnection:(id)arg1; 42 | - (id)initWithArrayNoCopy:(id)arg1; 43 | - (id)initWithArray:(id)arg1; 44 | - (id)initWithObject:(id)arg1; 45 | - (id)init; 46 | 47 | @end 48 | 49 | @interface NSObject () 50 | - (id)filesContaining:(id)arg1 anchorStart:(BOOL)arg2 anchorEnd:(BOOL)arg3 subsequence:(BOOL)arg4 ignoreCase:(BOOL)arg5 cancelWhen:(id)arg6; 51 | - (id)fileDataTypePresumed; 52 | - (BOOL)conformsTo:(id)arg1; 53 | - (BOOL)conformsToAnyIdentifierInSet:(id)arg1; 54 | - (id)databaseQueryProvider; 55 | - (id)codeCompletionsAtLocation:(id)arg1 withCurrentFileContentDictionary:(id)arg2 completionContext:(id *)arg3 sortedUsingBlock:(id)arg4; 56 | - (NSRange)characterRange; //DVTTextDocumentLocation 57 | - (NSRange)lineRange; //DVTTextDocumentLocation 58 | 59 | - (id)workspace; 60 | - (id)index; 61 | - (NSString *)workspaceName; 62 | 63 | - (id)symbolNameAtCharacterIndex:(unsigned long long)arg1 nameRanges:(id *)arg2; //DVTSourceTextStorage 64 | - (id)sourceModelItemAtCharacterIndex:(unsigned long long)arg1; //DVTSourceTextStorage in Xcode 5, DVTSourceLanguageSourceModelService protocol in Xcode 5.1 65 | - (id)sourceModel; //DVTSourceTextStorage 66 | 67 | @property(readonly) id sourceModelService; // DVTSourceTextStorage 68 | 69 | - (id)stringConstantAtLocation:(unsigned long long)arg1; //DVTSourceModel 70 | 71 | - (id)previousItem; //DVTSourceModelItem 72 | 73 | - (id)_listWindowController; //DVTTextCompletionSession 74 | @end 75 | 76 | @interface DVTCompletingTextView : NSTextView 77 | - (BOOL)shouldAutoCompleteAtLocation:(unsigned long long)arg1; 78 | @end 79 | 80 | @interface DVTSourceTextView : DVTCompletingTextView 81 | @end 82 | 83 | 84 | @interface DVTTextCompletionSession : NSObject 85 | @property(nonatomic) NSInteger selectedCompletionIndex; 86 | @property(retain) NSArray *filteredCompletionsAlpha; 87 | @property(retain) NSArray *allCompletions; 88 | @property(readonly) DVTCompletingTextView *textView; 89 | 90 | - (BOOL)shouldAutoSuggestForTextChange; 91 | - (NSRange)replacementRangeForSuggestedRange:(NSRange)arg1; 92 | @end 93 | 94 | @interface DVTTextCompletionController : NSObject 95 | @property(retain) DVTTextCompletionSession *currentSession; 96 | @property(readonly) DVTCompletingTextView *textView; 97 | @property(getter=isAutoCompletionEnabled) BOOL autoCompletionEnabled; 98 | 99 | - (void)textViewDidInsertText; 100 | - (BOOL)acceptCurrentCompletion; 101 | - (BOOL)_showCompletionsAtCursorLocationExplicitly:(BOOL)arg1; 102 | - (BOOL)textViewShouldChangeTextInRange:(NSRange)arg1 replacementString:(id)replacementString; 103 | @end 104 | 105 | @interface DVTTextCompletionListWindowController : NSWindowController 106 | - (id)_selectedCompletionItem; 107 | - (void)showInfoPaneForCompletionItem:(id)arg1; 108 | - (void)_hideWindow; 109 | @end 110 | 111 | @interface DVTTextCompletionStrategy : NSObject 112 | { 113 | } 114 | 115 | //+ (CDUnknownBlockType)priorityComparator; 116 | - (id)bestMatchForPrefix:(id)arg1 inCompletionItems:(id)arg2 withContext:(id)arg3; 117 | - (id)additionalCompletionItemsForDocumentLocation:(id)arg1 context:(id)arg2; 118 | - (id)completionItemsForDocumentLocation:(id)arg1 context:(id)arg2 highlyLikelyCompletionItems:(id *)arg3 areDefinitive:(char *)arg4; 119 | - (void)prepareForDocumentLocation:(id)arg1 context:(id)arg2; 120 | 121 | @end 122 | 123 | @interface IDEIndexCompletionStrategy : DVTTextCompletionStrategy 124 | - (id)completionItemsForDocumentLocation:(id)arg1 context:(id)arg2 areDefinitive:(char *)arg3; // Xcode 5 125 | - (id)completionItemsForDocumentLocation:(id)arg1 context:(id)arg2 highlyLikelyCompletionItems:(id *)arg3 areDefinitive:(char *)arg4; // Xcode 6 126 | @end 127 | 128 | @interface DVTDocumentLocation : NSObject 129 | { 130 | NSDictionary *_docParams; 131 | NSDictionary *_locParams; 132 | NSURL *_documentURL; 133 | NSNumber *_timestamp; 134 | } 135 | 136 | + (BOOL)supportsSecureCoding; 137 | + (id)documentLocationWithURLScheme:(id)arg1 path:(id)arg2 documentParameters:(id)arg3 locationParameters:(id)arg4; 138 | @property(readonly) NSNumber *timestamp; // @synthesize timestamp=_timestamp; 139 | @property(readonly) NSURL *documentURL; // @synthesize documentURL=_documentURL; 140 | - (id)locationParameters; 141 | - (id)documentParameters; 142 | - (id)documentPath; 143 | - (id)documentScheme; 144 | - (void)dvt_writeToSerializer:(id)arg1; 145 | - (id)dvt_initFromDeserializer:(id)arg1; 146 | - (void)encodeWithCoder:(id)arg1; 147 | - (id)initWithCoder:(id)arg1; 148 | - (id)dvt_persistableStringRepresentation; 149 | - (id)dvt_initFromPersistableStringRepresentation:(id)arg1 error:(id *)arg2; 150 | - (long long)compare:(id)arg1; 151 | @property(readonly, copy) NSString *description; 152 | - (BOOL)isEqualDisregardingTimestamp:(id)arg1; 153 | - (BOOL)isEqualToDocumentLocationDisregardingDocumentURL:(id)arg1; 154 | @property(readonly) unsigned long long hash; 155 | - (BOOL)isEqual:(id)arg1; 156 | - (id)copyWithURL:(id)arg1; 157 | - (id)copyWithZone:(struct _NSZone *)arg1; 158 | - (id)documentURLString; 159 | - (id)initWithDocumentURL:(id)arg1 timestamp:(id)arg2; 160 | - (id)init; 161 | 162 | // Remaining properties 163 | @property(readonly, copy) NSString *debugDescription; 164 | @property(readonly) Class superclass; 165 | 166 | @end 167 | 168 | @interface DVTTextDocumentLocation : DVTDocumentLocation 169 | { 170 | long long _startingColumnNumber; 171 | long long _endingColumnNumber; 172 | long long _startingLineNumber; 173 | long long _endingLineNumber; 174 | struct _NSRange _characterRange; 175 | long long _locationEncoding; 176 | } 177 | 178 | + (BOOL)supportsSecureCoding; 179 | @property(readonly) long long locationEncoding; // @synthesize locationEncoding=_locationEncoding; 180 | @property(readonly) struct _NSRange characterRange; // @synthesize characterRange=_characterRange; 181 | @property(readonly) long long endingLineNumber; // @synthesize endingLineNumber=_endingLineNumber; 182 | @property(readonly) long long startingLineNumber; // @synthesize startingLineNumber=_startingLineNumber; 183 | @property(readonly) long long endingColumnNumber; // @synthesize endingColumnNumber=_endingColumnNumber; 184 | @property(readonly) long long startingColumnNumber; // @synthesize startingColumnNumber=_startingColumnNumber; 185 | - (id)dvt_persistableStringRepresentation; 186 | - (id)dvt_initFromPersistableStringRepresentation:(id)arg1 error:(id *)arg2; 187 | - (id)copyWithURL:(id)arg1; 188 | - (long long)compare:(id)arg1; 189 | - (BOOL)isEqualDisregardingTimestamp:(id)arg1; 190 | - (BOOL)isEqualToDocumentLocationDisregardingDocumentURL:(id)arg1; 191 | - (BOOL)isEqual:(id)arg1; 192 | @property(readonly) struct _NSRange lineRange; 193 | - (id)description; 194 | - (void)dvt_writeToSerializer:(id)arg1; 195 | - (id)dvt_initFromDeserializer:(id)arg1; 196 | - (void)encodeWithCoder:(id)arg1; 197 | - (id)initWithCoder:(id)arg1; 198 | - (id)initWithDocumentURL:(id)arg1 timestamp:(id)arg2 characterRange:(struct _NSRange)arg3; 199 | - (id)initWithDocumentURL:(id)arg1 timestamp:(id)arg2 characterRange:(struct _NSRange)arg3 locationEncoding:(long long)arg4; 200 | - (id)initWithDocumentURL:(id)arg1 timestamp:(id)arg2 lineRange:(struct _NSRange)arg3; 201 | - (id)initWithDocumentURL:(id)arg1 timestamp:(id)arg2 startingColumnNumber:(long long)arg3 endingColumnNumber:(long long)arg4 startingLineNumber:(long long)arg5 endingLineNumber:(long long)arg6 characterRange:(struct _NSRange)arg7; 202 | - (id)initWithDocumentURL:(id)arg1 timestamp:(id)arg2 startingColumnNumber:(long long)arg3 endingColumnNumber:(long long)arg4 startingLineNumber:(long long)arg5 endingLineNumber:(long long)arg6 characterRange:(struct _NSRange)arg7 locationEncoding:(long long)arg8; 203 | 204 | @end 205 | 206 | @interface DVTSourceModel : NSObject 207 | { 208 | id _sourceBufferProvider; 209 | id _inputStream; 210 | id _scanner; 211 | struct _NSRange _dirtyRange; 212 | long long _batchDelta; 213 | id _sourceItems; 214 | BOOL _isDoingBatchEdit; 215 | id _nativeParser; 216 | } 217 | 218 | + (void)initialize; 219 | @property BOOL isDoingBatchEdit; // @synthesize isDoingBatchEdit=_isDoingBatchEdit; 220 | @property long long batchDelta; // @synthesize batchDelta=_batchDelta; 221 | @property struct _NSRange dirtyRange; // @synthesize dirtyRange=_dirtyRange; 222 | @property(retain) id scanner; // @synthesize scanner=_scanner; 223 | @property(retain) id sourceItems; // @synthesize sourceItems=_sourceItems; 224 | @property(retain) id inputStream; // @synthesize inputStream=_inputStream; 225 | @property(assign) id sourceBufferProvider; // @synthesize sourceBufferProvider=_sourceBufferProvider; 226 | - (id)objCMethodNameForItem:(id)arg1 nameRanges:(id *)arg2; 227 | - (BOOL)isItemDictionaryLiteral:(id)arg1; 228 | - (BOOL)isItemObjectLiteral:(id)arg1; 229 | - (BOOL)isItemForStatement:(id)arg1; 230 | - (BOOL)isItemSemanticBlock:(id)arg1; 231 | - (BOOL)isItemBracketExpression:(id)arg1; 232 | - (BOOL)isItemAngleExpression:(id)arg1; 233 | - (BOOL)isItemParenExpression:(id)arg1; 234 | - (BOOL)isPostfixExpressionAtLocation:(unsigned long long)arg1; 235 | - (BOOL)isInTokenizableCodeAtLocation:(unsigned long long)arg1; 236 | - (BOOL)isInPlainCodeAtLocation:(unsigned long long)arg1; 237 | - (BOOL)isInKeywordAtLocation:(unsigned long long)arg1; 238 | - (BOOL)isIncompletionPlaceholderAtLocation:(unsigned long long)arg1; 239 | - (BOOL)isInNumberConstantAtLocation:(unsigned long long)arg1; 240 | - (BOOL)isInCharacterConstantAtLocation:(unsigned long long)arg1; 241 | - (BOOL)isInIdentifierAtLocation:(unsigned long long)arg1; 242 | - (BOOL)isInStringConstantAtLocation:(unsigned long long)arg1; 243 | - (BOOL)isInIncludeStatementAtLocation:(unsigned long long)arg1; 244 | - (BOOL)isInPreprocessorStatementAtLocation:(unsigned long long)arg1; 245 | - (BOOL)isInDocCommentAtLocation:(unsigned long long)arg1; 246 | - (BOOL)isInCommentAtLocation:(unsigned long long)arg1; 247 | - (id)completionPlaceholderItemAtLocation:(unsigned long long)arg1; 248 | - (id)identOrKeywordItemAtLocation:(unsigned long long)arg1; 249 | - (id)objCDeclaratorItemAtLocation:(unsigned long long)arg1; 250 | - (id)numberConstantAtLocation:(unsigned long long)arg1; 251 | - (id)characterConstantAtLocation:(unsigned long long)arg1; 252 | - (id)stringConstantAtLocation:(unsigned long long)arg1; 253 | - (id)moduleImportStatementAtLocation:(unsigned long long)arg1; 254 | - (id)includeStatementAtLocation:(unsigned long long)arg1; 255 | - (id)preprocessorStatementAtLocation:(unsigned long long)arg1; 256 | - (id)docCommentAtLocation:(unsigned long long)arg1; 257 | - (id)commentAtLocation:(unsigned long long)arg1; 258 | - (id)placeholderItemsFromItem:(id)arg1; 259 | - (id)identifierItemsFromItem:(id)arg1; 260 | - (id)commentBlockItems; 261 | - (id)functionsAndMethodItems; 262 | - (id)classItems; 263 | - (void)addBlockItemsInTypeList:(long long *)arg1 fromItem:(id)arg2 toArray:(id)arg3; 264 | - (void)addIdentifierItemsFromItem:(id)arg1 toArray:(id)arg2; 265 | - (void)addItemsInTypeList:(long long *)arg1 fromItem:(id)arg2 toArray:(id)arg3; 266 | - (id)functionOrMethodDefinitionAtLocation:(unsigned long long)arg1; 267 | - (id)functionOrMethodAtLocation:(unsigned long long)arg1; 268 | - (id)interfaceDeclarationAtLocation:(unsigned long long)arg1; 269 | - (id)typeDeclarationAtLocation:(unsigned long long)arg1; 270 | - (id)classAtLocation:(unsigned long long)arg1; 271 | - (id)itemNameAtLocation:(unsigned long long)arg1 inTypeList:(long long *)arg2 nameRanges:(id *)arg3 scopeRange:(struct _NSRange *)arg4; 272 | - (id)nameOfItem:(id)arg1 nameRanges:(id *)arg2 scopeRange:(struct _NSRange *)arg3; 273 | //- (void)enumerateIdentifierItemsInRange:(struct _NSRange)arg1 usingBlock:(CDUnknownBlockType)arg2; 274 | - (id)itemAtLocation:(unsigned long long)arg1 ofType:(id)arg2; 275 | - (id)itemAtLocation:(unsigned long long)arg1 inTypeList:(long long *)arg2; 276 | - (id)builtUpNameForItem:(id)arg1 nameRanges:(id *)arg2; 277 | - (id)_builtUpNameForItem:(id)arg1 mutableNameRanges:(id)arg2; 278 | - (id)_builtUpNameForSubTree:(id)arg1 mutableNameRanges:(id)arg2; 279 | - (id)objectLiteralItemAtLocation:(unsigned long long)arg1; 280 | - (id)parenItemAtLocation:(unsigned long long)arg1; 281 | - (id)parenLikeItemAtLocation:(unsigned long long)arg1; 282 | - (id)foldableBlockItemForLocation:(unsigned long long)arg1; 283 | - (id)foldableBlockItemForLineAtLocation:(unsigned long long)arg1; 284 | - (id)blockItemAtLocation:(unsigned long long)arg1; 285 | - (long long)indentForItem:(id)arg1; 286 | - (id)adjoiningItemAtLocation:(unsigned long long)arg1; 287 | - (id)enclosingItemAtLocation:(unsigned long long)arg1; 288 | - (id)_topLevelSourceItem; 289 | - (void)parse; 290 | - (void)doingBatchEdit:(BOOL)arg1; 291 | - (void)dirtyRange:(struct _NSRange)arg1 changeInLength:(long long)arg2; 292 | - (id)initWithSourceBufferProvider:(id)arg1; 293 | 294 | @end 295 | -------------------------------------------------------------------------------- /KSImageNamed/KSImageNamed.m: -------------------------------------------------------------------------------- 1 | // 2 | // KSImageNamed.m 3 | // KSImageNamed 4 | // 5 | // Created by Kent Sutherland on 9/10/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "KSImageNamed.h" 10 | #import "KSImageNamedIndexCompletionItem.h" 11 | #import "KSImageNamedPreviewWindow.h" 12 | #import "XcodeMisc.h" 13 | #import "MethodSwizzle.h" 14 | 15 | NSString * const KSShowExtensionInImageCompletionDefaultKey = @"KSShowExtensionInImageCompletion"; 16 | 17 | @interface KSImageNamed () { 18 | NSTimer *_updateTimer; 19 | } 20 | @property(nonatomic, strong) NSMutableDictionary *imageCompletions; 21 | @property(nonatomic, strong) NSMutableSet *indexesToUpdate; 22 | @property(nonatomic, strong) KSImageNamedPreviewWindow *imageWindow; 23 | @end 24 | 25 | @implementation KSImageNamed 26 | 27 | + (void)pluginDidLoad:(NSBundle *)plugin 28 | { 29 | if ([self shouldLoadPlugin]) { 30 | [self sharedPlugin]; 31 | } 32 | } 33 | 34 | + (instancetype)sharedPlugin 35 | { 36 | static id sharedPlugin; 37 | static dispatch_once_t onceToken; 38 | dispatch_once(&onceToken, ^{ 39 | sharedPlugin = [[self alloc] init]; 40 | }); 41 | 42 | return sharedPlugin; 43 | } 44 | 45 | + (BOOL)shouldLoadPlugin 46 | { 47 | NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; 48 | 49 | return bundleIdentifier && [bundleIdentifier caseInsensitiveCompare:@"com.apple.dt.Xcode"] == NSOrderedSame; 50 | } 51 | 52 | - (id)init 53 | { 54 | if ( (self = [super init]) ) { 55 | [self setImageCompletions:[NSMutableDictionary dictionary]]; 56 | [self setIndexesToUpdate:[NSMutableSet set]]; 57 | } 58 | return self; 59 | } 60 | 61 | - (void)dealloc 62 | { 63 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 64 | } 65 | 66 | - (KSImageNamedPreviewWindow *)imageWindow 67 | { 68 | if (!_imageWindow) { 69 | _imageWindow = [[KSImageNamedPreviewWindow alloc] init]; 70 | } 71 | return _imageWindow; 72 | } 73 | 74 | - (void)indexNeedsUpdate:(id)index 75 | { 76 | //Coalesce completion rebuilds to avoid hangs when Xcode rebuilds an index one file a time 77 | [[self indexesToUpdate] addObject:index]; 78 | 79 | [_updateTimer invalidate]; 80 | _updateTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(_rebuildCompletionsTimerFired:) userInfo:nil repeats:NO]; 81 | } 82 | 83 | - (void)removeImageCompletionsForIndex:(id)index 84 | { 85 | NSString *workspaceName = [index respondsToSelector:@selector(workspaceName)] ? [index workspaceName] : [[index workspace] name]; 86 | 87 | if (workspaceName && [[self imageCompletions] objectForKey:workspaceName]) { 88 | [[self imageCompletions] removeObjectForKey:workspaceName]; 89 | } 90 | } 91 | 92 | - (NSArray *)imageCompletionsForIndex:(id)index language:(id)language 93 | { 94 | NSString *workspaceName = [index respondsToSelector:@selector(workspaceName)] ? [index workspaceName] : [[index workspace] name]; 95 | NSArray *completions = [[self imageCompletions] objectForKey:workspaceName]; 96 | 97 | if (!completions) { 98 | completions = [self _rebuildCompletionsForIndex:index]; 99 | } 100 | 101 | BOOL forSwift = [[language identifier] isEqualToString:@"Xcode.SourceCodeLanguage.Swift"]; 102 | 103 | for (KSImageNamedIndexCompletionItem *nextCompletionItem in completions) { 104 | [nextCompletionItem setForSwift:forSwift]; 105 | } 106 | 107 | return completions; 108 | } 109 | 110 | - (NSSet *)completionStringsForType:(KSImageNamedCompletionStringType)type 111 | { 112 | //Pulls completions out of Completions.plist and creates arrays so the rest of the plugin can do lookups to see if it should be autocompleting a particular method 113 | //The three different strings are needed because this plugin does raw string matching rather than doing anything fancy like looking at the AST 114 | static NSSet *classAndMethodCompletionStrings; 115 | static NSSet *methodDeclarationCompletionStrings; 116 | static NSSet *methodNameCompletionStrings; 117 | static dispatch_once_t onceToken; 118 | dispatch_once(&onceToken, ^{ 119 | NSURL *completionsURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"Completions" withExtension:@"plist"]; 120 | NSArray *completionStrings = [NSArray arrayWithContentsOfURL:completionsURL]; 121 | 122 | NSMutableSet *mutableClassAndMethodCompletionStrings = [[NSMutableSet alloc] init]; 123 | NSMutableSet *mutableMethodDeclarationCompletionStrings = [[NSMutableSet alloc] init]; 124 | NSMutableSet *mutableMethodNameCompletionStrings = [[NSMutableSet alloc] init]; 125 | 126 | for (NSDictionary *nextCompletionDictionary in completionStrings) { 127 | [mutableClassAndMethodCompletionStrings addObject:[nextCompletionDictionary objectForKey:@"classAndMethod"]]; 128 | [mutableMethodDeclarationCompletionStrings addObject:[nextCompletionDictionary objectForKey:@"methodDeclaration"]]; 129 | [mutableMethodNameCompletionStrings addObject:[nextCompletionDictionary objectForKey:@"methodName"]]; 130 | } 131 | 132 | classAndMethodCompletionStrings = [mutableClassAndMethodCompletionStrings copy]; 133 | methodDeclarationCompletionStrings = [mutableMethodDeclarationCompletionStrings copy]; 134 | methodNameCompletionStrings = [mutableMethodNameCompletionStrings copy]; 135 | }); 136 | 137 | NSSet *completionStrings; 138 | 139 | if (type == KSImageNamedCompletionStringTypeClassAndMethod) { 140 | completionStrings = classAndMethodCompletionStrings; 141 | } else if (type == KSImageNamedCompletionStringTypeMethodDeclaration) { 142 | completionStrings = methodDeclarationCompletionStrings; 143 | } else if (type == KSImageNamedCompletionStringTypeMethodName) { 144 | completionStrings = methodNameCompletionStrings; 145 | } 146 | 147 | return completionStrings; 148 | } 149 | 150 | #pragma mark - Private 151 | 152 | - (void)_rebuildCompletionsTimerFired:(NSTimer *)timer 153 | { 154 | for (id nextIndex in [self indexesToUpdate]) { 155 | [self _rebuildCompletionsForIndex:nextIndex]; 156 | } 157 | 158 | [[self indexesToUpdate] removeAllObjects]; 159 | 160 | _updateTimer = nil; 161 | } 162 | 163 | - (NSArray *)_rebuildCompletionsForIndex:(id)index 164 | { 165 | NSString *workspaceName = [index respondsToSelector:@selector(workspaceName)] ? [index workspaceName] : [[index workspace] name]; 166 | NSArray *completions; 167 | 168 | if (workspaceName) { 169 | if ([[self imageCompletions] objectForKey:workspaceName]) { 170 | [[self imageCompletions] removeObjectForKey:workspaceName]; 171 | } 172 | 173 | completions = [self _imageCompletionsForIndex:index]; 174 | 175 | if (completions) { 176 | [[self imageCompletions] setObject:completions forKey:workspaceName]; 177 | } 178 | } 179 | 180 | return completions; 181 | } 182 | 183 | - (NSArray *)_imageCompletionsForIndex:(id)index 184 | { 185 | id result = [index filesContaining:@"" anchorStart:NO anchorEnd:NO subsequence:NO ignoreCase:YES cancelWhen:nil]; 186 | NSSet *imageTypes = [NSSet setWithArray:[NSImage imageTypes]]; 187 | 188 | NSMutableArray *completionItems = [NSMutableArray array]; 189 | NSMutableDictionary *imageCompletionItems = [NSMutableDictionary dictionary]; 190 | 191 | //Sort results so @2x is sorted after the 1x image 192 | result = [[result uniqueObjects] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 193 | NSString *fileName1 = [obj1 fileName]; 194 | NSString *fileName2 = [obj2 fileName]; 195 | NSComparisonResult result = [fileName1 caseInsensitiveCompare:fileName2]; 196 | BOOL is2xiPad1 = [[fileName1 stringByDeletingPathExtension] hasSuffix:@"@2x~ipad"]; 197 | BOOL is2xiPad2 = [[fileName2 stringByDeletingPathExtension] hasSuffix:@"@2x~ipad"]; 198 | 199 | //@2x~ipad should be sorted after ~ipad 200 | //This ensures that the 2x detection in the loop below works correctly for 2x iPad images 201 | //Otherwise @2x~ipad will be checked before ~ipad and the 2x property won't be set correctly 202 | if (is2xiPad1 && !is2xiPad2) { 203 | result = NSOrderedDescending; 204 | } else if (!is2xiPad1 && is2xiPad2) { 205 | result = NSOrderedAscending; 206 | } 207 | 208 | return result; 209 | }]; 210 | 211 | BOOL includeExtension = [[NSUserDefaults standardUserDefaults] boolForKey:KSShowExtensionInImageCompletionDefaultKey]; 212 | BOOL encounteredAssetCatalog = NO; 213 | 214 | for (id nextResult in result) { 215 | NSString *fileName = [nextResult fileName]; 216 | 217 | if (![imageCompletionItems objectForKey:fileName]) { 218 | if ([[nextResult fileDataTypePresumed] conformsTo:@"com.apple.dt.assetcatalog"]) { 219 | //Iterate over asset catalog contents 220 | NSArray *assetCatalogCompletions = [self _imageCompletionsForAssetCatalog:nextResult]; 221 | 222 | [completionItems addObjectsFromArray:assetCatalogCompletions]; 223 | 224 | for (KSImageNamedIndexCompletionItem *nextImageCompletion in assetCatalogCompletions) { 225 | [imageCompletionItems setObject:nextImageCompletion forKey:[nextImageCompletion fileName]]; 226 | } 227 | 228 | encounteredAssetCatalog = YES; 229 | } else { 230 | //Is this a 2x image? Maybe we already added a 1x version that we can mark as having a 2x version 231 | NSString *imageName = [fileName stringByDeletingPathExtension]; 232 | NSString *normalFileName; 233 | BOOL skip = NO; 234 | BOOL is2x = NO; 235 | 236 | if ([imageName hasSuffix:@"@2x"]) { 237 | normalFileName = [[imageName substringToIndex:[imageName length] - 3] stringByAppendingFormat:@".%@", [fileName pathExtension]]; 238 | is2x = YES; 239 | } else if ([imageName hasSuffix:@"@2x~ipad"]) { 240 | //2x iPad images need to be handled separately since (image~ipad and image@2x~ipad are valid pairs) 241 | normalFileName = [[[imageName substringToIndex:[imageName length] - 8] stringByAppendingString:@"~ipad"] stringByAppendingFormat:@".%@", [fileName pathExtension]]; 242 | is2x = YES; 243 | } else { 244 | normalFileName = fileName; 245 | } 246 | 247 | KSImageNamedIndexCompletionItem *existingCompletionItem = [imageCompletionItems objectForKey:normalFileName]; 248 | 249 | if (existingCompletionItem) { 250 | if (is2x) { 251 | existingCompletionItem.has2x = YES; 252 | } else { 253 | existingCompletionItem.has1x = YES; 254 | } 255 | skip = YES; 256 | } 257 | 258 | if (!skip && [[nextResult fileDataTypePresumed] conformsToAnyIdentifierInSet:imageTypes]) { 259 | KSImageNamedIndexCompletionItem *imageCompletion = [[KSImageNamedIndexCompletionItem alloc] initWithFileURL:[nextResult fileReferenceURL] includeExtension:includeExtension]; 260 | imageCompletion.has2x = is2x; 261 | imageCompletion.has1x = !is2x; 262 | [completionItems addObject:imageCompletion]; 263 | [imageCompletionItems setObject:imageCompletion forKey:fileName]; 264 | } 265 | } 266 | } 267 | } 268 | 269 | if (encounteredAssetCatalog) { 270 | //Need to sort completionItems by fileName to ensure autocompletion in asset catalogs is handled correctly 271 | //Autocomplete doesn't work correctly if the completion items aren't in alphabetical order 272 | [completionItems sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"fileName" ascending:YES selector:@selector(caseInsensitiveCompare:)]]]; 273 | } 274 | 275 | return completionItems; 276 | } 277 | 278 | //arg1 is a DVTFilePath 279 | - (NSArray *)_imageCompletionsForAssetCatalog:(id)filePath 280 | { 281 | NSMutableArray *imageCompletions = [NSMutableArray array]; 282 | NSArray *properties = @[NSURLNameKey, NSURLIsDirectoryKey]; 283 | NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[filePath fileURL] includingPropertiesForKeys:properties options:NSDirectoryEnumerationSkipsHiddenFiles errorHandler:nil]; 284 | NSMutableDictionary *namespaces = [NSMutableDictionary dictionary]; 285 | 286 | for (NSURL *nextURL in enumerator) { 287 | NSString *fileName; 288 | NSNumber *isDirectory; 289 | 290 | if ([nextURL getResourceValue:&fileName forKey:NSURLNameKey error:NULL] && [nextURL getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:NULL] && [isDirectory boolValue]) { 291 | if ([[fileName pathExtension] caseInsensitiveCompare:@"imageset"] == NSOrderedSame) { 292 | NSString *namespace = [namespaces objectForKey:[nextURL URLByDeletingLastPathComponent]]; 293 | KSImageNamedIndexCompletionItem *imageCompletion = [[KSImageNamedIndexCompletionItem alloc] initWithAssetFileURL:nextURL namespace:namespace]; 294 | 295 | if ([imageCompletion imageFileURL]) { 296 | // Only add the completion if there's an image in the set 297 | [imageCompletions addObject:imageCompletion]; 298 | } 299 | 300 | [enumerator skipDescendants]; 301 | } else if ([[fileName pathExtension] length] == 0) { 302 | // Check if this directory defines a namespace 303 | NSURL *contentsURL = [nextURL URLByAppendingPathComponent:@"Contents.json"]; 304 | NSData *contentsData = [NSData dataWithContentsOfURL:contentsURL]; 305 | BOOL registeredNamespace = NO; 306 | 307 | if (contentsData) { 308 | NSDictionary *contentsJSON = [NSJSONSerialization JSONObjectWithData:contentsData options:0 error:NULL]; 309 | 310 | if ([contentsJSON isKindOfClass:[NSDictionary class]]) { 311 | BOOL providesNamespace = [[[contentsJSON objectForKey:@"properties"] objectForKey:@"provides-namespace"] boolValue]; 312 | 313 | if (providesNamespace) { 314 | // Add the namespace to the namespaces dictionary 315 | NSURL *namespaceKey = nextURL; 316 | NSString *namespace = fileName; 317 | 318 | // Check if there's a parent namespace (namespaces can be nested) 319 | NSURL *parentNamespaceKey = [namespaceKey URLByDeletingLastPathComponent]; 320 | NSString *parentNamespace = [namespaces objectForKey:parentNamespaceKey]; 321 | 322 | if (parentNamespace) { 323 | namespace = [parentNamespace stringByAppendingPathComponent:namespace]; 324 | } 325 | 326 | [namespaces setObject:namespace forKey:namespaceKey]; 327 | 328 | registeredNamespace = YES; 329 | } 330 | } 331 | } 332 | 333 | if (!registeredNamespace) { 334 | // There may be a parent namespace that we need to inherit 335 | NSURL *inheritedNamespaceKey = [nextURL URLByDeletingLastPathComponent]; 336 | NSString *inheritedNamespace = [namespaces objectForKey:inheritedNamespaceKey]; 337 | 338 | if (inheritedNamespace) { 339 | [namespaces setObject:inheritedNamespace forKey:nextURL]; 340 | } 341 | } 342 | } 343 | } 344 | } 345 | 346 | return imageCompletions; 347 | } 348 | 349 | @end 350 | -------------------------------------------------------------------------------- /KSImageNamed.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1F4ED06816ECBE7500250F46 /* KSImageNamedPreviewWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F4ED06716ECBE7500250F46 /* KSImageNamedPreviewWindow.m */; }; 11 | 372424AC1BC0413000C55103 /* KSImageNamed.xcplugindata in Resources */ = {isa = PBXBuildFile; fileRef = 372424AB1BC0413000C55103 /* KSImageNamed.xcplugindata */; }; 12 | 3727E3B516AB350F007DACD3 /* DVTSourceTextView+KSImageNamed.m in Sources */ = {isa = PBXBuildFile; fileRef = 3727E3B416AB350F007DACD3 /* DVTSourceTextView+KSImageNamed.m */; }; 13 | 37642FEA16B0C754002CC70F /* IDEIndex+KSImageNamed.m in Sources */ = {isa = PBXBuildFile; fileRef = 37642FE916B0C754002CC70F /* IDEIndex+KSImageNamed.m */; }; 14 | 3772077C16AFD84B005666C3 /* IDEWorkspace+KSImageNamed.m in Sources */ = {isa = PBXBuildFile; fileRef = 3772077B16AFD84B005666C3 /* IDEWorkspace+KSImageNamed.m */; }; 15 | 377E049417C98A0A003665B1 /* Completions.plist in Resources */ = {isa = PBXBuildFile; fileRef = 377E049317C98A0A003665B1 /* Completions.plist */; }; 16 | 37A2B52D15FE927F00D9AE1E /* MethodSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 37A2B52C15FE927F00D9AE1E /* MethodSwizzle.m */; }; 17 | 37B5873616AF5BD500B4787D /* DVTTextCompletionController+KSImageNamed.m in Sources */ = {isa = PBXBuildFile; fileRef = 37B5873516AF5BD500B4787D /* DVTTextCompletionController+KSImageNamed.m */; }; 18 | 37C5C45D15FE93BB0003BD79 /* IDEFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37C5C45C15FE93BB0003BD79 /* IDEFoundation.framework */; }; 19 | 37C6B61116A7CDF4000247EB /* DVTKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37C6B61016A7CDF4000247EB /* DVTKit.framework */; }; 20 | 37CEBA7815FE96F40090E015 /* KSImageNamedIndexCompletionItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 37CEBA7715FE96F40090E015 /* KSImageNamedIndexCompletionItem.m */; }; 21 | 37CEBA7B15FE98740090E015 /* DVTFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37CEBA7A15FE98740090E015 /* DVTFoundation.framework */; }; 22 | 37D1FD0116A7C6A500616DCD /* IDEKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37D1FD0016A7C6A500616DCD /* IDEKit.framework */; }; 23 | 37E5302A15FE7DDB00753EB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 37E5302815FE7DDB00753EB4 /* InfoPlist.strings */; }; 24 | 37E5303315FE7E6300753EB4 /* KSImageNamed.m in Sources */ = {isa = PBXBuildFile; fileRef = 37E5303215FE7E6300753EB4 /* KSImageNamed.m */; }; 25 | 37E5303515FE7F4200753EB4 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37E5303415FE7F4200753EB4 /* AppKit.framework */; }; 26 | 37E5303715FE7F4600753EB4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37E5303615FE7F4600753EB4 /* Foundation.framework */; }; 27 | 37FD092E1BC078FD00C57E2D /* KSImageNamedCompletionStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = 37FD092D1BC078FD00C57E2D /* KSImageNamedCompletionStrategy.m */; }; 28 | 37FE67221BE69ACB0010B371 /* DVTTextCompletionSession+KSImageNamed.m in Sources */ = {isa = PBXBuildFile; fileRef = 37FE67211BE69ACB0010B371 /* DVTTextCompletionSession+KSImageNamed.m */; }; 29 | 586F70C51818C1C900A91B84 /* DVTTextCompletionListWindowController+KSImageNamed.m in Sources */ = {isa = PBXBuildFile; fileRef = 586F70C41818C1C900A91B84 /* DVTTextCompletionListWindowController+KSImageNamed.m */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 1F4ED06616ECBE7500250F46 /* KSImageNamedPreviewWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSImageNamedPreviewWindow.h; sourceTree = ""; }; 34 | 1F4ED06716ECBE7500250F46 /* KSImageNamedPreviewWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSImageNamedPreviewWindow.m; sourceTree = ""; }; 35 | 372424AB1BC0413000C55103 /* KSImageNamed.xcplugindata */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = KSImageNamed.xcplugindata; sourceTree = ""; }; 36 | 3727E3AE16AB341A007DACD3 /* XcodeMisc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XcodeMisc.h; sourceTree = ""; }; 37 | 3727E3B316AB350F007DACD3 /* DVTSourceTextView+KSImageNamed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DVTSourceTextView+KSImageNamed.h"; sourceTree = ""; }; 38 | 3727E3B416AB350F007DACD3 /* DVTSourceTextView+KSImageNamed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "DVTSourceTextView+KSImageNamed.m"; sourceTree = ""; }; 39 | 37642FE816B0C754002CC70F /* IDEIndex+KSImageNamed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IDEIndex+KSImageNamed.h"; sourceTree = ""; }; 40 | 37642FE916B0C754002CC70F /* IDEIndex+KSImageNamed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IDEIndex+KSImageNamed.m"; sourceTree = ""; }; 41 | 3772077A16AFD84B005666C3 /* IDEWorkspace+KSImageNamed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IDEWorkspace+KSImageNamed.h"; sourceTree = ""; }; 42 | 3772077B16AFD84B005666C3 /* IDEWorkspace+KSImageNamed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IDEWorkspace+KSImageNamed.m"; sourceTree = ""; }; 43 | 377E049317C98A0A003665B1 /* Completions.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Completions.plist; sourceTree = ""; }; 44 | 3791502916AB3B98005A124A /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = ""; }; 45 | 3795759717CF1E4E00C1258C /* screenshot.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = screenshot.gif; sourceTree = ""; }; 46 | 37A2B52B15FE927F00D9AE1E /* MethodSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodSwizzle.h; sourceTree = ""; }; 47 | 37A2B52C15FE927F00D9AE1E /* MethodSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MethodSwizzle.m; sourceTree = ""; }; 48 | 37B5873416AF5BD500B4787D /* DVTTextCompletionController+KSImageNamed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DVTTextCompletionController+KSImageNamed.h"; sourceTree = ""; }; 49 | 37B5873516AF5BD500B4787D /* DVTTextCompletionController+KSImageNamed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "DVTTextCompletionController+KSImageNamed.m"; sourceTree = ""; }; 50 | 37C5C45C15FE93BB0003BD79 /* IDEFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IDEFoundation.framework; path = ../Frameworks/IDEFoundation.framework; sourceTree = DEVELOPER_DIR; }; 51 | 37C6B61016A7CDF4000247EB /* DVTKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DVTKit.framework; path = ../SharedFrameworks/DVTKit.framework; sourceTree = DEVELOPER_DIR; }; 52 | 37CEBA7615FE96F40090E015 /* KSImageNamedIndexCompletionItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSImageNamedIndexCompletionItem.h; sourceTree = ""; }; 53 | 37CEBA7715FE96F40090E015 /* KSImageNamedIndexCompletionItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSImageNamedIndexCompletionItem.m; sourceTree = ""; }; 54 | 37CEBA7A15FE98740090E015 /* DVTFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DVTFoundation.framework; path = ../SharedFrameworks/DVTFoundation.framework; sourceTree = DEVELOPER_DIR; }; 55 | 37D1FD0016A7C6A500616DCD /* IDEKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IDEKit.framework; path = ../Frameworks/IDEKit.framework; sourceTree = DEVELOPER_DIR; }; 56 | 37E5302015FE7DDB00753EB4 /* KSImageNamed.ideplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KSImageNamed.ideplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 37E5302715FE7DDB00753EB4 /* KSImageNamed-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KSImageNamed-Info.plist"; sourceTree = ""; }; 58 | 37E5302915FE7DDB00753EB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 59 | 37E5302B15FE7DDB00753EB4 /* KSImageNamed-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KSImageNamed-Prefix.pch"; sourceTree = ""; }; 60 | 37E5303115FE7E6300753EB4 /* KSImageNamed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSImageNamed.h; sourceTree = ""; }; 61 | 37E5303215FE7E6300753EB4 /* KSImageNamed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSImageNamed.m; sourceTree = ""; }; 62 | 37E5303415FE7F4200753EB4 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 63 | 37E5303615FE7F4600753EB4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 64 | 37FD092C1BC078FD00C57E2D /* KSImageNamedCompletionStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSImageNamedCompletionStrategy.h; sourceTree = ""; }; 65 | 37FD092D1BC078FD00C57E2D /* KSImageNamedCompletionStrategy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSImageNamedCompletionStrategy.m; sourceTree = ""; }; 66 | 37FE67201BE69ACB0010B371 /* DVTTextCompletionSession+KSImageNamed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DVTTextCompletionSession+KSImageNamed.h"; sourceTree = ""; }; 67 | 37FE67211BE69ACB0010B371 /* DVTTextCompletionSession+KSImageNamed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "DVTTextCompletionSession+KSImageNamed.m"; sourceTree = ""; }; 68 | 586F70C31818C1C900A91B84 /* DVTTextCompletionListWindowController+KSImageNamed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DVTTextCompletionListWindowController+KSImageNamed.h"; sourceTree = ""; }; 69 | 586F70C41818C1C900A91B84 /* DVTTextCompletionListWindowController+KSImageNamed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "DVTTextCompletionListWindowController+KSImageNamed.m"; sourceTree = ""; }; 70 | /* End PBXFileReference section */ 71 | 72 | /* Begin PBXFrameworksBuildPhase section */ 73 | 37E5301D15FE7DDB00753EB4 /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | 37E5303715FE7F4600753EB4 /* Foundation.framework in Frameworks */, 78 | 37E5303515FE7F4200753EB4 /* AppKit.framework in Frameworks */, 79 | 37C5C45D15FE93BB0003BD79 /* IDEFoundation.framework in Frameworks */, 80 | 37CEBA7B15FE98740090E015 /* DVTFoundation.framework in Frameworks */, 81 | 37D1FD0116A7C6A500616DCD /* IDEKit.framework in Frameworks */, 82 | 37C6B61116A7CDF4000247EB /* DVTKit.framework in Frameworks */, 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | /* End PBXFrameworksBuildPhase section */ 87 | 88 | /* Begin PBXGroup section */ 89 | 37E5301515FE7DDB00753EB4 = { 90 | isa = PBXGroup; 91 | children = ( 92 | 3791502916AB3B98005A124A /* README.md */, 93 | 3795759717CF1E4E00C1258C /* screenshot.gif */, 94 | 37E5302515FE7DDB00753EB4 /* KSImageNamed */, 95 | 37E5302215FE7DDB00753EB4 /* Frameworks */, 96 | 37E5302115FE7DDB00753EB4 /* Products */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | 37E5302115FE7DDB00753EB4 /* Products */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 37E5302015FE7DDB00753EB4 /* KSImageNamed.ideplugin */, 104 | ); 105 | name = Products; 106 | sourceTree = ""; 107 | }; 108 | 37E5302215FE7DDB00753EB4 /* Frameworks */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 37E5303415FE7F4200753EB4 /* AppKit.framework */, 112 | 37E5303615FE7F4600753EB4 /* Foundation.framework */, 113 | 37C5C45C15FE93BB0003BD79 /* IDEFoundation.framework */, 114 | 37D1FD0016A7C6A500616DCD /* IDEKit.framework */, 115 | 37CEBA7A15FE98740090E015 /* DVTFoundation.framework */, 116 | 37C6B61016A7CDF4000247EB /* DVTKit.framework */, 117 | ); 118 | name = Frameworks; 119 | sourceTree = ""; 120 | }; 121 | 37E5302515FE7DDB00753EB4 /* KSImageNamed */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 37E5303115FE7E6300753EB4 /* KSImageNamed.h */, 125 | 37E5303215FE7E6300753EB4 /* KSImageNamed.m */, 126 | 1F4ED06616ECBE7500250F46 /* KSImageNamedPreviewWindow.h */, 127 | 1F4ED06716ECBE7500250F46 /* KSImageNamedPreviewWindow.m */, 128 | 37CEBA7615FE96F40090E015 /* KSImageNamedIndexCompletionItem.h */, 129 | 37CEBA7715FE96F40090E015 /* KSImageNamedIndexCompletionItem.m */, 130 | 37FD092C1BC078FD00C57E2D /* KSImageNamedCompletionStrategy.h */, 131 | 37FD092D1BC078FD00C57E2D /* KSImageNamedCompletionStrategy.m */, 132 | 3772077A16AFD84B005666C3 /* IDEWorkspace+KSImageNamed.h */, 133 | 3772077B16AFD84B005666C3 /* IDEWorkspace+KSImageNamed.m */, 134 | 37642FE816B0C754002CC70F /* IDEIndex+KSImageNamed.h */, 135 | 37642FE916B0C754002CC70F /* IDEIndex+KSImageNamed.m */, 136 | 3727E3B316AB350F007DACD3 /* DVTSourceTextView+KSImageNamed.h */, 137 | 3727E3B416AB350F007DACD3 /* DVTSourceTextView+KSImageNamed.m */, 138 | 37B5873416AF5BD500B4787D /* DVTTextCompletionController+KSImageNamed.h */, 139 | 37B5873516AF5BD500B4787D /* DVTTextCompletionController+KSImageNamed.m */, 140 | 37FE67201BE69ACB0010B371 /* DVTTextCompletionSession+KSImageNamed.h */, 141 | 37FE67211BE69ACB0010B371 /* DVTTextCompletionSession+KSImageNamed.m */, 142 | 586F70C31818C1C900A91B84 /* DVTTextCompletionListWindowController+KSImageNamed.h */, 143 | 586F70C41818C1C900A91B84 /* DVTTextCompletionListWindowController+KSImageNamed.m */, 144 | 37A2B52B15FE927F00D9AE1E /* MethodSwizzle.h */, 145 | 37A2B52C15FE927F00D9AE1E /* MethodSwizzle.m */, 146 | 3727E3AE16AB341A007DACD3 /* XcodeMisc.h */, 147 | 37E5302615FE7DDB00753EB4 /* Supporting Files */, 148 | ); 149 | path = KSImageNamed; 150 | sourceTree = ""; 151 | }; 152 | 37E5302615FE7DDB00753EB4 /* Supporting Files */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 377E049317C98A0A003665B1 /* Completions.plist */, 156 | 37E5302715FE7DDB00753EB4 /* KSImageNamed-Info.plist */, 157 | 372424AB1BC0413000C55103 /* KSImageNamed.xcplugindata */, 158 | 37E5302815FE7DDB00753EB4 /* InfoPlist.strings */, 159 | 37E5302B15FE7DDB00753EB4 /* KSImageNamed-Prefix.pch */, 160 | ); 161 | name = "Supporting Files"; 162 | sourceTree = ""; 163 | }; 164 | /* End PBXGroup section */ 165 | 166 | /* Begin PBXNativeTarget section */ 167 | 37E5301F15FE7DDB00753EB4 /* KSImageNamed */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = 37E5302E15FE7DDB00753EB4 /* Build configuration list for PBXNativeTarget "KSImageNamed" */; 170 | buildPhases = ( 171 | 37E5301C15FE7DDB00753EB4 /* Sources */, 172 | 37E5301D15FE7DDB00753EB4 /* Frameworks */, 173 | 37E5301E15FE7DDB00753EB4 /* Resources */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = KSImageNamed; 180 | productName = ImageNamed; 181 | productReference = 37E5302015FE7DDB00753EB4 /* KSImageNamed.ideplugin */; 182 | productType = "com.apple.product-type.bundle"; 183 | }; 184 | /* End PBXNativeTarget section */ 185 | 186 | /* Begin PBXProject section */ 187 | 37E5301715FE7DDB00753EB4 /* Project object */ = { 188 | isa = PBXProject; 189 | attributes = { 190 | CLASSPREFIX = KS; 191 | LastUpgradeCheck = 0510; 192 | }; 193 | buildConfigurationList = 37E5301A15FE7DDB00753EB4 /* Build configuration list for PBXProject "KSImageNamed" */; 194 | compatibilityVersion = "Xcode 3.2"; 195 | developmentRegion = English; 196 | hasScannedForEncodings = 0; 197 | knownRegions = ( 198 | en, 199 | ); 200 | mainGroup = 37E5301515FE7DDB00753EB4; 201 | productRefGroup = 37E5302115FE7DDB00753EB4 /* Products */; 202 | projectDirPath = ""; 203 | projectRoot = ""; 204 | targets = ( 205 | 37E5301F15FE7DDB00753EB4 /* KSImageNamed */, 206 | ); 207 | }; 208 | /* End PBXProject section */ 209 | 210 | /* Begin PBXResourcesBuildPhase section */ 211 | 37E5301E15FE7DDB00753EB4 /* Resources */ = { 212 | isa = PBXResourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 377E049417C98A0A003665B1 /* Completions.plist in Resources */, 216 | 37E5302A15FE7DDB00753EB4 /* InfoPlist.strings in Resources */, 217 | 372424AC1BC0413000C55103 /* KSImageNamed.xcplugindata in Resources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXResourcesBuildPhase section */ 222 | 223 | /* Begin PBXSourcesBuildPhase section */ 224 | 37E5301C15FE7DDB00753EB4 /* Sources */ = { 225 | isa = PBXSourcesBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | 37E5303315FE7E6300753EB4 /* KSImageNamed.m in Sources */, 229 | 37A2B52D15FE927F00D9AE1E /* MethodSwizzle.m in Sources */, 230 | 37CEBA7815FE96F40090E015 /* KSImageNamedIndexCompletionItem.m in Sources */, 231 | 37FD092E1BC078FD00C57E2D /* KSImageNamedCompletionStrategy.m in Sources */, 232 | 586F70C51818C1C900A91B84 /* DVTTextCompletionListWindowController+KSImageNamed.m in Sources */, 233 | 37FE67221BE69ACB0010B371 /* DVTTextCompletionSession+KSImageNamed.m in Sources */, 234 | 3727E3B516AB350F007DACD3 /* DVTSourceTextView+KSImageNamed.m in Sources */, 235 | 37B5873616AF5BD500B4787D /* DVTTextCompletionController+KSImageNamed.m in Sources */, 236 | 3772077C16AFD84B005666C3 /* IDEWorkspace+KSImageNamed.m in Sources */, 237 | 37642FEA16B0C754002CC70F /* IDEIndex+KSImageNamed.m in Sources */, 238 | 1F4ED06816ECBE7500250F46 /* KSImageNamedPreviewWindow.m in Sources */, 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | }; 242 | /* End PBXSourcesBuildPhase section */ 243 | 244 | /* Begin PBXVariantGroup section */ 245 | 37E5302815FE7DDB00753EB4 /* InfoPlist.strings */ = { 246 | isa = PBXVariantGroup; 247 | children = ( 248 | 37E5302915FE7DDB00753EB4 /* en */, 249 | ); 250 | name = InfoPlist.strings; 251 | sourceTree = ""; 252 | }; 253 | /* End PBXVariantGroup section */ 254 | 255 | /* Begin XCBuildConfiguration section */ 256 | 37E5302C15FE7DDB00753EB4 /* Debug */ = { 257 | isa = XCBuildConfiguration; 258 | buildSettings = { 259 | ALWAYS_SEARCH_USER_PATHS = NO; 260 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 261 | CLANG_ENABLE_OBJC_ARC = YES; 262 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 263 | CLANG_WARN_EMPTY_BODY = YES; 264 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 265 | COPY_PHASE_STRIP = NO; 266 | GCC_C_LANGUAGE_STANDARD = gnu99; 267 | GCC_DYNAMIC_NO_PIC = NO; 268 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 269 | GCC_OPTIMIZATION_LEVEL = 0; 270 | GCC_PREPROCESSOR_DEFINITIONS = ( 271 | "DEBUG=1", 272 | "$(inherited)", 273 | ); 274 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 275 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 276 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 277 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 278 | GCC_WARN_UNDECLARED_SELECTOR = YES; 279 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 280 | GCC_WARN_UNUSED_VARIABLE = YES; 281 | MACOSX_DEPLOYMENT_TARGET = 10.10; 282 | ONLY_ACTIVE_ARCH = YES; 283 | SDKROOT = macosx; 284 | }; 285 | name = Debug; 286 | }; 287 | 37E5302D15FE7DDB00753EB4 /* Release */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | ALWAYS_SEARCH_USER_PATHS = NO; 291 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 292 | CLANG_ENABLE_OBJC_ARC = YES; 293 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 294 | CLANG_WARN_EMPTY_BODY = YES; 295 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 296 | COPY_PHASE_STRIP = YES; 297 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 298 | GCC_C_LANGUAGE_STANDARD = gnu99; 299 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 300 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 301 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 302 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 303 | GCC_WARN_UNDECLARED_SELECTOR = YES; 304 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 305 | GCC_WARN_UNUSED_VARIABLE = YES; 306 | MACOSX_DEPLOYMENT_TARGET = 10.10; 307 | SDKROOT = macosx; 308 | }; 309 | name = Release; 310 | }; 311 | 37E5302F15FE7DDB00753EB4 /* Debug */ = { 312 | isa = XCBuildConfiguration; 313 | buildSettings = { 314 | DEPLOYMENT_LOCATION = YES; 315 | DSTROOT = "$(HOME)"; 316 | FRAMEWORK_SEARCH_PATHS = ( 317 | "$(inherited)", 318 | "$(DEVELOPER_DIR)/../Frameworks", 319 | "$(DEVELOPER_DIR)/../SharedFrameworks", 320 | ); 321 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 322 | GCC_PREFIX_HEADER = "KSImageNamed/KSImageNamed-Prefix.pch"; 323 | INFOPLIST_FILE = "KSImageNamed/KSImageNamed-Info.plist"; 324 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Developer/Xcode/Plug-ins"; 325 | PRODUCT_NAME = KSImageNamed; 326 | WRAPPER_EXTENSION = ideplugin; 327 | }; 328 | name = Debug; 329 | }; 330 | 37E5303015FE7DDB00753EB4 /* Release */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | DEPLOYMENT_LOCATION = YES; 334 | DSTROOT = "$(HOME)"; 335 | FRAMEWORK_SEARCH_PATHS = ( 336 | "$(inherited)", 337 | "$(DEVELOPER_DIR)/../Frameworks", 338 | "$(DEVELOPER_DIR)/../SharedFrameworks", 339 | ); 340 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 341 | GCC_PREFIX_HEADER = "KSImageNamed/KSImageNamed-Prefix.pch"; 342 | INFOPLIST_FILE = "KSImageNamed/KSImageNamed-Info.plist"; 343 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Developer/Xcode/Plug-ins"; 344 | PRODUCT_NAME = KSImageNamed; 345 | WRAPPER_EXTENSION = ideplugin; 346 | }; 347 | name = Release; 348 | }; 349 | /* End XCBuildConfiguration section */ 350 | 351 | /* Begin XCConfigurationList section */ 352 | 37E5301A15FE7DDB00753EB4 /* Build configuration list for PBXProject "KSImageNamed" */ = { 353 | isa = XCConfigurationList; 354 | buildConfigurations = ( 355 | 37E5302C15FE7DDB00753EB4 /* Debug */, 356 | 37E5302D15FE7DDB00753EB4 /* Release */, 357 | ); 358 | defaultConfigurationIsVisible = 0; 359 | defaultConfigurationName = Release; 360 | }; 361 | 37E5302E15FE7DDB00753EB4 /* Build configuration list for PBXNativeTarget "KSImageNamed" */ = { 362 | isa = XCConfigurationList; 363 | buildConfigurations = ( 364 | 37E5302F15FE7DDB00753EB4 /* Debug */, 365 | 37E5303015FE7DDB00753EB4 /* Release */, 366 | ); 367 | defaultConfigurationIsVisible = 0; 368 | defaultConfigurationName = Release; 369 | }; 370 | /* End XCConfigurationList section */ 371 | }; 372 | rootObject = 37E5301715FE7DDB00753EB4 /* Project object */; 373 | } 374 | --------------------------------------------------------------------------------