├── .gitignore
├── Images
├── demo1.gif
├── demo2.gif
├── setting1.png
├── setting2.png
└── setting3.png
├── HKSnippet.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ ├── apple.xcuserdatad
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── hunk.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── xcshareddata
│ └── xcschemes
│ │ └── HKSnippet.xcscheme
└── project.pbxproj
├── Setting
├── HKSnippetSettingController.h
├── HKSnippetSetting.h
├── HKSnippetEditViewController.h
├── HKSnippetEditViewController.m
├── HKSnippetSetting.m
├── HKSnippetSettingController.m
├── HKSnippetEditViewController.xib
└── HKSnippetSettingController.xib
├── HKSnippet
├── HKSnippet.h
├── Info.plist
├── HKSnippet.m
└── default_snippets.plist
├── Category
├── NSString+Snippet.h
├── NSTextView+Snippet.h
├── HKTextResult.h
├── HKTextResult.m
├── NSTextView+Snippet.m
├── NSString+Snippet.m
├── HKKeyboardEventSender.h
└── HKKeyboardEventSender.m
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | HKSnippet.xcodeproj/xcuserdata
2 |
--------------------------------------------------------------------------------
/Images/demo1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hunk3000/HKSnippet/HEAD/Images/demo1.gif
--------------------------------------------------------------------------------
/Images/demo2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hunk3000/HKSnippet/HEAD/Images/demo2.gif
--------------------------------------------------------------------------------
/Images/setting1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hunk3000/HKSnippet/HEAD/Images/setting1.png
--------------------------------------------------------------------------------
/Images/setting2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hunk3000/HKSnippet/HEAD/Images/setting2.png
--------------------------------------------------------------------------------
/Images/setting3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hunk3000/HKSnippet/HEAD/Images/setting3.png
--------------------------------------------------------------------------------
/HKSnippet.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Setting/HKSnippetSettingController.h:
--------------------------------------------------------------------------------
1 | //
2 | // HKSnippetSettingController.h
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface HKSnippetSettingController : NSWindowController
13 |
14 | @end
--------------------------------------------------------------------------------
/HKSnippet/HKSnippet.h:
--------------------------------------------------------------------------------
1 | //
2 | // HKSnippet.h
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HKSnippet : NSObject
12 |
13 | + (instancetype)sharedPlugin;
14 |
15 | @property (nonatomic, strong, readonly) NSBundle* bundle;
16 |
17 | @end
--------------------------------------------------------------------------------
/Category/NSString+Snippet.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+TextGetter.h
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HKTextResult;
12 |
13 | @interface NSString (Snippet)
14 |
15 | - (HKTextResult *)textResultOfCurrentLineAtLocation:(NSInteger)location;
16 |
17 | @end
--------------------------------------------------------------------------------
/Category/NSTextView+Snippet.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSTextView+TextGetter.h
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HKTextResult;
12 |
13 | @interface NSTextView (Snippet)
14 |
15 | - (NSInteger)currentCurseLocation;
16 | - (HKTextResult *)textResultOfCurrentLine;
17 |
18 | @end
--------------------------------------------------------------------------------
/HKSnippet.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SuppressBuildableAutocreation
6 |
7 | 18194CA71B169D93007A3FB0
8 |
9 | primary
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/HKSnippet.xcodeproj/xcuserdata/hunk.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SuppressBuildableAutocreation
6 |
7 | 18194CA71B169D93007A3FB0
8 |
9 | primary
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Category/HKTextResult.h:
--------------------------------------------------------------------------------
1 | //
2 | // HKTextResult.h
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HKTextResult : NSObject
12 |
13 | @property (nonatomic, assign) NSRange range;
14 | @property (nonatomic, copy) NSString *string;
15 |
16 | - (instancetype)initWithRange:(NSRange)range
17 | string:(NSString *)string;
18 |
19 | @end
--------------------------------------------------------------------------------
/Category/HKTextResult.m:
--------------------------------------------------------------------------------
1 | //
2 | // HKTextResult.m
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import "HKTextResult.h"
10 |
11 | @implementation HKTextResult
12 |
13 | - (instancetype)initWithRange:(NSRange)range
14 | string:(NSString *)string {
15 | if (self = [super init]) {
16 | _range = range;
17 | _string = string;
18 | }
19 | return self;
20 | }
21 |
22 | @end
--------------------------------------------------------------------------------
/Category/NSTextView+Snippet.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSTextView+TextGetter.m
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import "NSTextView+Snippet.h"
10 | #import "NSString+Snippet.h"
11 |
12 | @implementation NSTextView (Snippet)
13 |
14 | - (NSInteger)currentCurseLocation {
15 | return [[self selectedRanges][0] rangeValue].location;
16 | }
17 |
18 | - (HKTextResult *)textResultOfCurrentLine {
19 | return [self.textStorage.string textResultOfCurrentLineAtLocation:[self currentCurseLocation]];
20 | }
21 |
22 | @end
--------------------------------------------------------------------------------
/Setting/HKSnippetSetting.h:
--------------------------------------------------------------------------------
1 | //
2 | // HKSnippetSetting.h
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | extern NSString *const kHKSnippetsKey;
12 |
13 | @interface HKSnippetSetting : NSObject
14 |
15 | @property (nonatomic, assign) BOOL enabled;
16 | @property (nonatomic, strong) NSMutableDictionary *snippets;
17 | @property (nonatomic, copy) NSArray *systemTriggers;
18 |
19 | + (HKSnippetSetting *)defaultSetting;
20 | - (void)sychronizeSetting;
21 | - (void)resetToDefaultSetting;
22 |
23 | @end
--------------------------------------------------------------------------------
/Setting/HKSnippetEditViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // HKSnippetEditViewController.h
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/14.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef void(^save_snippet_block)(NSString *oldTrigger, NSString *newTrigger, NSString *snippet);
12 |
13 | @interface HKSnippetEditViewController : NSWindowController
14 |
15 | @property (nonatomic, weak) IBOutlet NSTextField *triggerTextField;
16 | @property (nonatomic, unsafe_unretained) IBOutlet NSTextView *snippetTextView;
17 | @property (nonatomic, copy) NSString *triggerString;
18 | @property (nonatomic, copy) NSString *snippet;
19 | @property (nonatomic, copy) save_snippet_block saveBlock;
20 |
21 | - (IBAction)saveSnippet:(id)sender;
22 | - (IBAction)cancelSnippet:(id)sender;
23 |
24 | @end
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
21 |
--------------------------------------------------------------------------------
/Category/NSString+Snippet.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+TextGetter.m
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import "NSString+Snippet.h"
10 | #import "HKTextResult.h"
11 |
12 | @implementation NSString (Snippet)
13 |
14 | - (HKTextResult *)textResultOfCurrentLineAtLocation:(NSInteger)location {
15 | NSInteger curseLocation = location;
16 | NSRange range = NSMakeRange(0, curseLocation);
17 | NSRange currentLineRange = [self rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]
18 | options:NSBackwardsSearch range:range];
19 | NSString *line = nil;
20 | if (currentLineRange.location != NSNotFound) {
21 | NSRange lineRange = NSMakeRange(currentLineRange.location + 1, curseLocation - currentLineRange.location - 1);
22 | if (lineRange.location < [self length] && NSMaxRange(lineRange) < [self length]) {
23 | line = [self substringWithRange:lineRange];
24 | line = [line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
25 | return [[HKTextResult alloc] initWithRange:lineRange string:line];
26 | }
27 | }
28 | return nil;
29 | }
30 |
31 | @end
--------------------------------------------------------------------------------
/Category/HKKeyboardEventSender.h:
--------------------------------------------------------------------------------
1 | //
2 | // VVKeyboardEventSender.h
3 | // VVDocumenter-Xcode
4 | //
5 | // Created by 王 巍 on 13-7-26.
6 | //
7 | // Copyright (c) 2015 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 | #import
29 |
30 |
31 | @interface HKKeyboardEventSender : NSObject
32 | -(void) beginKeyBoradEvents;
33 | -(void) sendKeyCode:(NSInteger)keyCode;
34 | -(void) sendKeyCode:(NSInteger)keyCode withModifierCommand:(BOOL)command
35 | alt:(BOOL)alt
36 | shift:(BOOL)shift
37 | control:(BOOL)control;
38 | -(void) sendKeyCode:(NSInteger)keyCode withModifier:(NSInteger)modifierMask;
39 | -(void) endKeyBoradEvents;
40 | -(NSInteger) keyVCode;
41 | @end
42 |
--------------------------------------------------------------------------------
/HKSnippet/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | BNDL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | DVTPlugInCompatibilityUUIDs
26 |
27 | 37B30044-3B14-46BA-ABAA-F01000C27B63
28 | 640F884E-CE55-4B40-87C0-8869546CAB7A
29 | A2E4D43F-41F4-4FB9-BB94-7177011C9AED
30 | AD68E85B-441B-4301-B564-A45E4919A6AD
31 | C4A681B0-4A26-480E-93EC-1218098B9AA0
32 | FEC992CC-CA4A-4CFD-8881-77300FCB848A
33 | A16FF353-8441-459E-A50C-B071F53F51B7
34 | 992275C1-432A-4CF7-B659-D84ED6D42D3F
35 | 9F75337B-21B4-4ADC-B558-F9CADF7073A7
36 | E969541F-E6F9-4D25-8158-72DC3545A6C6
37 | 8DC44374-2B35-4C57-A6FE-2AD66A36AAD9
38 | 5EDAC44F-8E0B-42C9-9BEF-E9C12EEC4949
39 | 7FDF5C7A-131F-4ABB-9EDC-8C5F8F0B8A90
40 | AABB7188-E14E-4433-AD3B-5CD791EAD9A3
41 | 0420B86A-AA43-4792-9ED0-6FE0F2B16A13
42 | CC0D0F4F-05B3-431A-8F33-F84AFCB2C651
43 | 7265231C-39B4-402C-89E1-16167C4CC990
44 | 9AFF134A-08DC-4096-8CEE-62A4BB123046
45 | F41BD31E-2683-44B8-AE7F-5F09E919790E
46 | ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C
47 | 1637F4D5-0B27-416B-A78D-498965D64877
48 | 8A66E736-A720-4B3C-92F1-33D9962C69DF
49 | E0A62D1F-3C18-4D74-BFE5-A4167D643966
50 |
51 | LSMinimumSystemVersion
52 | $(MACOSX_DEPLOYMENT_TARGET)
53 | NSPrincipalClass
54 | HKSnippet
55 | XC4Compatible
56 |
57 | XCPluginHasUI
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Setting/HKSnippetEditViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // HKSnippetEditViewController.m
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/14.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import "HKSnippetEditViewController.h"
10 | #import "HKSnippetSetting.h"
11 |
12 | typedef void(^Void_Block)(void);
13 |
14 | @interface HKSnippetEditViewController ()
15 |
16 | @end
17 |
18 | @implementation HKSnippetEditViewController
19 |
20 | - (void)windowDidLoad {
21 | [super windowDidLoad];
22 | _snippetTextView.font = [NSFont systemFontOfSize:18.0f];
23 | }
24 |
25 | - (IBAction)saveSnippet:(id)sender {
26 | // Check trigger conflict with system keyword
27 | for (NSString *sysTrigger in [HKSnippetSetting defaultSetting].systemTriggers) {
28 | if ([sysTrigger containsString:_triggerTextField.stringValue]) {
29 | NSString *msg = [NSString stringWithFormat:@"The trigger %@ has conflict with system keyword %@ , Continue?",
30 | _triggerTextField.stringValue,
31 | sysTrigger];
32 | __weak typeof(self) weakSelf = self;
33 | [self showConfirmWithMessage:msg
34 | positiveAction:^{
35 | if (weakSelf.saveBlock) {
36 | weakSelf.saveBlock(_triggerString,
37 | _triggerTextField.stringValue,
38 | _snippetTextView.textStorage.string);
39 | }
40 | [weakSelf close];
41 | } negativeAction:nil];
42 | return;
43 | }
44 | }
45 |
46 | if (self.saveBlock) {
47 | self.saveBlock(_triggerString,
48 | _triggerTextField.stringValue,
49 | _snippetTextView.textStorage.string);
50 | }
51 | [self close];
52 | }
53 |
54 | - (IBAction)cancelSnippet:(id)sender {
55 | [self close];
56 | }
57 |
58 | #pragma mark - Private Method
59 | - (void)showConfirmWithMessage:(NSString *)message
60 | positiveAction:(Void_Block)postiveAction
61 | negativeAction:(Void_Block)negativeAction {
62 |
63 | NSAlert *alert = [[NSAlert alloc] init];
64 | [alert addButtonWithTitle:@"YES"];
65 | [alert addButtonWithTitle:@"NO"];
66 | [alert setMessageText:@"Warnning"];
67 | [alert setInformativeText:message];
68 | [alert setAlertStyle:NSWarningAlertStyle];
69 | [alert beginSheetModalForWindow:self.window
70 | completionHandler:^(NSModalResponse returnCode) {
71 | if (returnCode == NSAlertFirstButtonReturn) {
72 | if (postiveAction) {
73 | postiveAction();
74 | }
75 | }
76 | if (returnCode == NSAlertSecondButtonReturn) {
77 | if (negativeAction) {
78 | negativeAction();
79 | }
80 | }
81 | }];
82 | }
83 |
84 | #pragma mark - Getters & Setters
85 | - (void)setTriggerString:(NSString *)triggerString {
86 | _triggerString = triggerString;
87 | _triggerTextField.stringValue = _triggerString;
88 | }
89 |
90 | - (void)setSnippet:(NSString *)snippet {
91 | _snippet = snippet;
92 | NSAttributedString* attr = [[NSAttributedString alloc] initWithString:_snippet];
93 | [_snippetTextView.textStorage appendAttributedString:attr];
94 | }
95 |
96 | @end
--------------------------------------------------------------------------------
/HKSnippet.xcodeproj/xcshareddata/xcschemes/HKSnippet.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
61 |
64 |
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Setting/HKSnippetSetting.m:
--------------------------------------------------------------------------------
1 | //
2 | // HKSnippetSetting.m
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import "HKSnippetSetting.h"
10 |
11 | NSString * const kHKSnippetsKey = @"snippets";
12 | NSString * const kHKSnippetEnabled = @"enabled";
13 |
14 | @implementation HKSnippetSetting
15 |
16 | - (instancetype)init {
17 | self = [super init];
18 | if (self) {
19 | _systemTriggers = @[@"@autoreleasepool",
20 | @"@catch",
21 | @"@class",
22 | @"@compatibility_alias",
23 | @"@defs",
24 | @"@dynamic",
25 | @"@encode",
26 | @"@end",
27 | @"@finally",
28 | @"@import",
29 | @"@interface",
30 | @"@implementation",
31 | @"@optional",
32 | @"@package",
33 | @"@private",
34 | @"@property",
35 | @"@protected",
36 | @"@protocol",
37 | @"@public",
38 | @"@required",
39 | @"@selector",
40 | @"@synchronized",
41 | @"@synthesize",
42 | @"@throw"
43 | ];
44 | _snippets = [NSMutableDictionary dictionaryWithDictionary:[self defaultConfig]];
45 | }
46 | return self;
47 | }
48 |
49 | + (HKSnippetSetting *)defaultSetting {
50 | static HKSnippetSetting *defaultSetting;
51 | static dispatch_once_t once;
52 | dispatch_once(&once, ^ {
53 | defaultSetting = [[[self class] alloc] init];
54 |
55 | NSDictionary *defaults = @{kHKSnippetEnabled: @YES,
56 | kHKSnippetsKey : defaultSetting.snippets ?: @{}};
57 | [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
58 | });
59 | return defaultSetting;
60 | }
61 |
62 | - (BOOL)enabled {
63 | return [[NSUserDefaults standardUserDefaults] boolForKey:kHKSnippetEnabled];
64 | }
65 |
66 | - (void)setEnabled:(BOOL)enabled {
67 | [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:kHKSnippetEnabled];
68 | [[NSUserDefaults standardUserDefaults] synchronize];
69 | }
70 |
71 | - (void)sychronizeSetting {
72 | NSMutableDictionary *snippets = [[self class] defaultSetting].snippets;
73 | [[NSUserDefaults standardUserDefaults] setObject:snippets forKey:kHKSnippetsKey];
74 | [[NSUserDefaults standardUserDefaults] synchronize];
75 | }
76 |
77 | - (void)resetToDefaultSetting {
78 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:kHKSnippetsKey];
79 | [[NSUserDefaults standardUserDefaults] setObject:@{} forKey:kHKSnippetsKey];
80 | [[NSUserDefaults standardUserDefaults] synchronize];
81 |
82 | _snippets = nil;
83 | _snippets = [NSMutableDictionary dictionaryWithDictionary:[self defaultConfig]];
84 | [[NSUserDefaults standardUserDefaults] setObject:[self defaultConfig] forKey:kHKSnippetsKey];
85 | [self setEnabled:YES];
86 | }
87 |
88 | - (NSDictionary *)defaultConfig {
89 | NSDictionary *config = [[NSUserDefaults standardUserDefaults] objectForKey:kHKSnippetsKey];
90 | if (0 < config.count) {
91 | return config;
92 | }
93 |
94 | NSString *selfPath = @"~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/HKSnippet.xcplugin";
95 | NSBundle *selfBundle = [NSBundle bundleWithPath:[selfPath stringByExpandingTildeInPath]];
96 | NSString *default_snippet_file = [selfBundle pathForResource:@"default_snippets"
97 | ofType:@"plist"];
98 | config = [NSDictionary dictionaryWithContentsOfFile:default_snippet_file];
99 | return config;
100 | }
101 |
102 | @end
--------------------------------------------------------------------------------
/Category/HKKeyboardEventSender.m:
--------------------------------------------------------------------------------
1 | //
2 | // VVKeyboardEventSender.m
3 | // VVDocumenter-Xcode
4 | //
5 | // Created by 王 巍 on 13-7-26.
6 | //
7 | // Copyright (c) 2015 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "HKKeyboardEventSender.h"
28 |
29 | @interface HKKeyboardEventSender()
30 | {
31 | CGEventSourceRef _source;
32 | CGEventTapLocation _location;
33 | }
34 | @end
35 |
36 | @implementation HKKeyboardEventSender
37 | -(void) beginKeyBoradEvents
38 | {
39 | _source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
40 | _location = kCGHIDEventTap;
41 | }
42 |
43 | -(void) sendKeyCode:(NSInteger)keyCode
44 | {
45 | [self sendKeyCode:keyCode withModifier:0];
46 | }
47 |
48 | -(void) sendKeyCode:(NSInteger)keyCode withModifierCommand:(BOOL)command
49 | alt:(BOOL)alt
50 | shift:(BOOL)shift
51 | control:(BOOL)control
52 | {
53 | NSInteger modifier = 0;
54 | if (command) {
55 | modifier = modifier ^ kCGEventFlagMaskCommand;
56 | }
57 | if (alt) {
58 | modifier = modifier ^ kCGEventFlagMaskAlternate;
59 | }
60 | if (shift) {
61 | modifier = modifier ^ kCGEventFlagMaskShift;
62 | }
63 | if (control) {
64 | modifier = modifier ^ kCGEventFlagMaskControl;
65 | }
66 |
67 | [self sendKeyCode:keyCode withModifier:modifier];
68 | }
69 |
70 | -(void) sendKeyCode:(NSInteger)keyCode withModifier:(NSInteger)modifierMask
71 | {
72 | NSAssert(_source != NULL, @"You should call -beginKeyBoradEvents before sending a key event");
73 | CGEventRef event;
74 | event = CGEventCreateKeyboardEvent(_source, keyCode, true);
75 | CGEventSetFlags(event, modifierMask);
76 | CGEventPost(_location, event);
77 | CFRelease(event);
78 |
79 | event = CGEventCreateKeyboardEvent(_source, keyCode, false);
80 | CGEventSetFlags(event, modifierMask);
81 | CGEventPost(_location, event);
82 | CFRelease(event);
83 | }
84 |
85 | -(void) endKeyBoradEvents
86 | {
87 | NSAssert(_source != NULL, @"You should call -beginKeyBoradEvents before end current keyborad event");
88 | CFRelease(_source);
89 | _source = nil;
90 | }
91 |
92 | -(NSInteger) keyVCode
93 | {
94 | TISInputSourceRef inputSource = TISCopyCurrentKeyboardLayoutInputSource();
95 | NSString *layoutID = (__bridge NSString *)TISGetInputSourceProperty(inputSource, kTISPropertyInputSourceID);
96 | CFRelease(inputSource);
97 |
98 | // Possible dvorak layout SourceIDs:
99 | // com.apple.keylayout.Dvorak (System Qwerty)
100 | // But exclude:
101 | // com.apple.keylayout.DVORAK-QWERTYCMD (System Qwerty ⌘)
102 | // org.unknown.keylayout.DvorakImproved-Qwerty⌘ (http://www.macupdate.com/app/mac/24137/dvorak-improved-keyboard-layout)
103 | if ([layoutID localizedCaseInsensitiveContainsString:@"dvorak"] && ![layoutID localizedCaseInsensitiveContainsString: @"qwerty"]) {
104 | return kVK_ANSI_Period;
105 | }
106 |
107 | // Possible workman layout SourceIDs (https://github.com/ojbucao/Workman):
108 | // org.sil.ukelele.keyboardlayout.workman.workman
109 | // org.sil.ukelele.keyboardlayout.workman.workmanextended
110 | // org.sil.ukelele.keyboardlayout.workman.workman-io
111 | // org.sil.ukelele.keyboardlayout.workman.workman-p
112 | // org.sil.ukelele.keyboardlayout.workman.workman-pextended
113 | // org.sil.ukelele.keyboardlayout.workman.workman-dead
114 | if ([layoutID localizedCaseInsensitiveContainsString:@"workman"]) {
115 | return kVK_ANSI_B;
116 | }
117 |
118 | return kVK_ANSI_V;
119 | }
120 | @end
121 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HKSnippet - Xcode plug-in
2 |
3 | HKSnippet is a xcode plug-in for creating code snippet with triggers strings.
4 |
5 | 
6 |
7 |
8 | ## What Can it do ?
9 | - minimize input for often used code snippet.
10 | - Input code sinppet with paramters. ( NEW! )
11 | - define your own trigger & snippet.
12 | - export & import your customized snippet to and from config file.
13 | - support undo - redo operation.
14 |
15 |
16 | ## Install
17 |
18 | - The recommanded way to install HKSnippet is to use [Alcatraz](http://alcatraz.io/). Install Alcatraz followed by the instruction, restart your Xcode. You can find `HKSnippet` in the list. Just click the install button.
19 |
20 | - another way is to clone this repo, Build the project and it's done!
21 |
22 | - or you can also download from [this link](http://exibitioncenter-data.stor.sinaapp.com/download%2FHKSnippet.xcplugin.zip) and move the plugin to path
23 | `~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/`
24 | then restart Xcode
25 |
26 | ## Usage
27 |
28 | This plug-in is very easy to use. By typing the trigger string , you will get the corresponding snippet.
29 |
30 | for example , you want to write a property with noatomic and strong, you can type **@pns**
31 | , and you will get
32 |
33 | @property (noatomic, strong) <#type#> *<#name#>
34 |
35 | The belowing part is pre-defined triggers and snippet :
36 |
37 | * Strong
38 |
39 | ```
40 | @ps @property (strong) type *value;
41 |
42 | @prs @property (strong, readonly) type *value;
43 |
44 | @pns @property (noatomic, strong) type *value;
45 |
46 | @prns @property (nonatomic, strong, readonly) type *value;
47 |
48 |
49 | ```
50 |
51 | * Weak
52 |
53 | ```
54 | @pw @property (weak) type *value;
55 |
56 | @prw @property (weak, readonly) type *value;
57 |
58 | @pnw @property (noatomic, weak) type *value;
59 |
60 | @prnw @property (nonatomic, weak, readonly) type *value;
61 |
62 | ```
63 |
64 | * Copy
65 |
66 | ```
67 | @pc @property (copy) type *value;
68 |
69 | @prc @property (copy, readonly) type *value;
70 |
71 | @pnc @property (noatomic, copy) type *value;
72 |
73 | @prnc @property (nonatomic, copy, readonly) type *value;
74 |
75 | ```
76 |
77 | * Assign
78 |
79 | ```
80 | @pa @property (assign) type *value;
81 |
82 | @pra @property (assign, readonly) type *value;
83 |
84 | @pna @property (noatomic, assign) type *value;
85 |
86 | @prna @property (nonatomic, assign, readonly) type *value;
87 |
88 | ```
89 | * @ff - General Getter
90 |
91 | ```
92 | @ff
93 |
94 | - (type *)name {
95 | if(!_name) {
96 | //Init Code
97 | }
98 | return _name;
99 | }
100 |
101 | ```
102 |
103 |
104 |
105 | * @fv - UIView Getter
106 |
107 | ```
108 | @fv
109 |
110 | - (UIView *)name {
111 | if(!_name) {
112 | _name = [UIView new];
113 | _name.backgroundColor = color;
114 | }
115 | return _name;
116 | }
117 |
118 | ```
119 |
120 | * @fl - UILabel Getter
121 |
122 | ```
123 | @fl
124 |
125 | - (UILabel *)name {
126 | if(!_name) {
127 | _name = [UILabel new];
128 | _name.backgroundColor = [UIColor clearColor];
129 | _name.textAlignment = NSTextAlignmentCenter;
130 | _name.numberOfLines = 0;
131 | _name.textColor = color;
132 | _name.font = font;
133 | _name.text = text;
134 | }
135 | return _name;
136 | }
137 |
138 | ```
139 |
140 | * @fi - UIImageView Getter
141 |
142 | ```
143 | @fi
144 |
145 | - (UIImageView *)name {
146 | if(!_name) {
147 | _name = [UIImageView new];
148 | _name.layer.cornerRadius = radius;
149 | _name.layer.masksToBounds = YES;
150 | _name.backgroundColor = [UIColor clearColor];
151 | _name.image = image;
152 | }
153 | return _name;
154 | }
155 |
156 | ```
157 |
158 | * @fb - UIButton Getter
159 |
160 | ```
161 | @fb
162 |
163 | - (UIButton *)name {
164 | if(!_name) {
165 | _name = [UIButton new];
166 | _name.layer.cornerRadius = radius;
167 | _name.layer.masksToBounds = YES;
168 | _name.backgroundColor = [UIColor clearColor];
169 | [_name setTitleColor:title color forState:UIControlStateNormal];
170 | [_name setTitle: title forState:UIControlStateNormal];
171 | [_name setImage:image forState:UIControlStateNormal];
172 | }
173 | return _name;
174 | }
175 |
176 | ```
177 |
178 | * @ft - UITableView Getter
179 |
180 | ```
181 | @ft
182 |
183 | - (UITableView *)name {
184 | if(!_name) {
185 | _name = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
186 | _name.backgroundColor = [UIColor clearColor];
187 | _name.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
188 | _name.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
189 | _name.separatorColor = color;
190 | _name.delegate = table delegate;
191 | _name.dataSource = table datasource;
192 |
193 | [_name registerClass:[class name class] forCellReuseIdentifier:cellId];
194 | }
195 | return _name;
196 | }
197 |
198 | ```
199 |
200 | * Declear
201 |
202 | ```
203 | @cs static NSString * const name = @\"value\";
204 |
205 | @log NSLog(@\"format\",data);
206 |
207 | @ws __weak typeof(self) weakSelf = self;
208 |
209 | @ss __strong typeof(weakSelf) strongSelf = weakSelf;
210 |
211 | @mk #pragma mark - section title
212 |
213 | @pmk #pragma mark - Private Method
214 |
215 | @lmk #pragma mark - LifeCycle
216 |
217 | @gmk #pragma mark - Getters & Setters
218 |
219 | ```
220 |
221 | * @lv - LoadView
222 |
223 | ```
224 | @lv
225 |
226 | - (void)loadView {
227 | [super loadView];
228 | }
229 |
230 | ```
231 |
232 | * @ls - Layout Subviews
233 |
234 | ```
235 | @ls
236 |
237 | - (void)layoutSubviews {
238 | [super layoutSubviews];
239 | CGFloat w = self.frame.size.width;
240 | CGFloat h = self.frame.size.height;
241 | //set subview frames
242 | }
243 |
244 | ```
245 |
246 | * @vl - ViewWillLayoutSubviews
247 |
248 | ```
249 | @vl
250 |
251 | - (void)viewWillLayoutSubviews {
252 | [super viewWillLayoutSubviews];
253 | CGFloat w = self.frame.size.width;
254 | CGFloat h = self.frame.size.height;
255 | //set subview frames
256 | }
257 |
258 | ```
259 |
260 | * @init - Initialization
261 |
262 | ```
263 | @init
264 |
265 | - (instancetype)init {
266 | self = [super init];
267 | if (self) {
268 | //statements
269 | }
270 | return self;
271 | }
272 |
273 | ```
274 |
275 | * @de - De-Init
276 |
277 | ```
278 | @de
279 |
280 | - (void)dealloc {
281 | [[NSNotificationCenter defaultCenter] removeObserver:self];
282 | }
283 |
284 | ```
285 |
286 | * @tdd - UITableView Delegate & Datasource
287 |
288 | ```
289 | @tdd
290 |
291 | #pragma mark - UITableViewDataSource
292 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
293 | return rows;
294 | }
295 |
296 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
297 |
298 | UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellId];
299 |
300 | return cell;
301 | }
302 |
303 | #pragma mark - UITableViewDelegate
304 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
305 | return height;
306 | }
307 |
308 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
309 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
310 |
311 | }
312 |
313 | ```
314 |
315 | ## Advanced
316 | You can even input a snippet with parameters, the format is as below:
317 |
318 | **@triger**
319 |
320 | for example , you want to declare a property getter for a label named "usernameLabel", and the font for the label is [UIFont systemFontOfSize:12.0f], you can type
321 |
322 | usernameLabel,[UIFont systemFontOfSize:12.0f]@fl , and then the magic happens, you will got below code:
323 |
324 | ```
325 | - (UILabel *)usernameLabel {
326 | if(!_usernameLabel) {
327 | _usernameLabel = [UILabel new];
328 | _usernameLabel.backgroundColor = [UIColor clearColor];
329 | _usernameLabel.textAlignment = NSTextAlignmentCenter;
330 | _usernameLabel.numberOfLines = 0;
331 | _usernameLabel.textColor = <#color#>;
332 | _usernameLabel.font = [UIFont systemFontOfSize:12.0f];
333 | _usernameLabel.text = <#text#>;
334 | }
335 | return _usernameLabel;
336 | }
337 | ```
338 |
339 | ## Setting
340 | After the install of the plug-in ,you will find the menu in the top "Plugins -> HKSnippet", Click that menu, you can see the belowing pannel where you can define your own triggers or edit the existing triggers & snippets.
341 |
342 | You can alse export your trigger & sniippet to a configuration file which can be use to share with others.
343 |
344 | 
345 |
346 |
347 | You can search snippet with trigger
348 | 
349 |
350 | Edit the snippet
351 | 
352 |
353 |
354 | ## LICENCE
355 |
356 | HKSnippet is available under the MIT license. See the LICENSE file for more info.
357 |
--------------------------------------------------------------------------------
/Setting/HKSnippetSettingController.m:
--------------------------------------------------------------------------------
1 | //
2 | // HKSnippetSettingController.m
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import "HKSnippetSettingController.h"
10 | #import "HKSnippetSetting.h"
11 | #import "HKSnippetEditViewController.h"
12 |
13 | @interface HKSnippetSettingController ()
14 |
15 | @property (nonatomic, weak) IBOutlet NSButton *btnEnabled;
16 | @property (nonatomic, weak) IBOutlet NSTableView *tableView;
17 | @property (nonatomic, weak) IBOutlet NSSearchField *searchField;
18 |
19 | @property (nonatomic, strong) HKSnippetEditViewController *snippetEditViewController;
20 | @property (nonatomic, strong) NSMutableArray *listOfKeys;
21 |
22 | @end
23 |
24 | @implementation HKSnippetSettingController
25 |
26 | #pragma mark - LifeCycle
27 | - (void)awakeFromNib {
28 | [super awakeFromNib];
29 | _listOfKeys = [NSMutableArray array];
30 | [self reloadDataWithKeyFilter:nil];
31 | }
32 |
33 | - (void)windowDidLoad {
34 | [super windowDidLoad];
35 | self.tableView.delegate = self;
36 | self.tableView.dataSource = self;
37 | self.btnEnabled.state = (NSCellStateValue)[[HKSnippetSetting defaultSetting] enabled];
38 | }
39 |
40 | - (void)dealloc {
41 | _tableView.delegate = nil;
42 | _tableView.dataSource = nil;
43 | [[NSNotificationCenter defaultCenter] removeObserver:self];
44 | }
45 |
46 | #pragma mark - UI Action
47 | - (IBAction)btnEnabledPressed:(NSButton *)sender {
48 | [[HKSnippetSetting defaultSetting] setEnabled:sender.state];
49 | }
50 |
51 | - (IBAction)btnResetPressed:(NSButton *)sender {
52 | [[HKSnippetSetting defaultSetting] resetToDefaultSetting];
53 | self.btnEnabled.state = (NSCellStateValue)[[HKSnippetSetting defaultSetting] enabled];
54 | [self reloadDataWithKeyFilter:nil];
55 | }
56 |
57 | - (IBAction)addNewSnippet:(id)sender {
58 | [self showEditViewControllerWithTriggerString:@""
59 | snippet:@""
60 | sender:sender];
61 | }
62 |
63 | - (IBAction)removeSelectedSnippet:(id)sender {
64 | NSInteger row = self.tableView.selectedRow;
65 | if (row == -1) {
66 | [self showErrorAlertWithMessage:@"You didn't select any row."];
67 | return;
68 | }
69 |
70 | __weak typeof(self) weakSelf = self;
71 | NSAlert *alert = [[NSAlert alloc] init];
72 | [alert addButtonWithTitle:@"OK"];
73 | [alert addButtonWithTitle:@"Cancel"];
74 | [alert setMessageText:@"Delete the snippet?"];
75 | [alert setInformativeText:@"Deleted snippet cannot be restored."];
76 | [alert setAlertStyle:NSWarningAlertStyle];
77 | [alert beginSheetModalForWindow:self.window
78 | completionHandler:^(NSModalResponse returnCode) {
79 | if (returnCode == NSAlertFirstButtonReturn) {
80 | NSString *triggerString = _listOfKeys[row];
81 | [[HKSnippetSetting defaultSetting].snippets removeObjectForKey:triggerString];
82 | [[HKSnippetSetting defaultSetting] sychronizeSetting];
83 | [weakSelf reloadDataWithKeyFilter:nil];
84 | }
85 | }];
86 | }
87 |
88 | - (IBAction)editSnippet:(id)sender {
89 | NSInteger row = self.tableView.selectedRow;
90 | if (row == -1) {
91 | [self showErrorAlertWithMessage:@"You didn't select any row."];
92 | return;
93 | }
94 |
95 | NSString *triggerString = _listOfKeys[row];
96 | NSString *snippetString = [HKSnippetSetting defaultSetting].snippets[triggerString];
97 | [self showEditViewControllerWithTriggerString:triggerString
98 | snippet:snippetString
99 | sender:sender];
100 | }
101 |
102 | - (IBAction)checkTriggers:(id)sender {
103 | NSMutableArray *conflictMessages = [NSMutableArray array];
104 |
105 | // Check trigger conflict with system keyword
106 | for (NSString *trigger in _listOfKeys) {
107 | for (NSString *sysTrigger in [HKSnippetSetting defaultSetting].systemTriggers) {
108 | if ([sysTrigger containsString:trigger]) {
109 | [conflictMessages addObject:[NSString stringWithFormat:@"%@ conflict with %@", trigger, sysTrigger]];
110 | }
111 | }
112 | }
113 | [self showErrorAlertWithMessage:[conflictMessages description]];
114 | }
115 | - (IBAction)SearchTextFieldAction:(NSSearchField *)sender {
116 | //NSLog(@"SearchTextFieldAction %@",sender);
117 | if (sender.stringValue.length == 0) {
118 | [self reloadDataWithKeyFilter:nil];
119 | } else {
120 | [self reloadDataWithKeyFilter:sender.stringValue];
121 | }
122 | }
123 |
124 | #pragma mark - Private Method
125 | - (void)reloadDataWithKeyFilter:(NSString *)filter {
126 | NSArray *allKeys = [[HKSnippetSetting defaultSetting].snippets allKeys];
127 | NSArray *sortedKeys = [allKeys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
128 | return [obj1 compare:obj2];
129 | }];
130 | [_listOfKeys removeAllObjects];
131 | if (0 < filter.length) {
132 | for (NSString *key in sortedKeys) {
133 | if ([key containsString:filter]) {
134 | [_listOfKeys addObject:key];
135 | }
136 | }
137 | } else {
138 | [_listOfKeys addObjectsFromArray:sortedKeys];
139 | }
140 |
141 | [self.tableView reloadData];
142 | }
143 |
144 | - (void)showEditViewControllerWithTriggerString:(NSString *)triggerString
145 | snippet:(NSString *)snippet
146 | sender:(id)sender {
147 | _snippetEditViewController = [[HKSnippetEditViewController alloc] initWithWindowNibName:@"HKSnippetEditViewController"];
148 |
149 | NSRect windowFrame = [[self window] frame];
150 | NSRect prefsFrame = [[_snippetEditViewController window] frame];
151 | prefsFrame.origin = NSMakePoint(windowFrame.origin.x + (windowFrame.size.width - prefsFrame.size.width) / 2.0,
152 | NSMaxY(windowFrame) - NSHeight(prefsFrame) - 20.0);
153 | [[_snippetEditViewController window] setFrame:prefsFrame
154 | display:NO];
155 | self.snippetEditViewController.triggerString = triggerString;
156 | self.snippetEditViewController.snippet = snippet;
157 |
158 | __weak typeof(self) weakSelf = self;
159 | self.snippetEditViewController.saveBlock = ^(NSString *oldTrigger, NSString *newTrigger, NSString *snippet) {
160 | // Check trigger length
161 | if (newTrigger.length < 2) {
162 | [weakSelf showErrorAlertWithMessage:@"Trigger is too short, 2 characters at least."];
163 | return;
164 | }
165 | // trigger string changed, remove old trigger
166 | if (![oldTrigger isEqualToString:newTrigger]) {
167 | [[HKSnippetSetting defaultSetting].snippets removeObjectForKey:oldTrigger];
168 | }
169 |
170 | [HKSnippetSetting defaultSetting].snippets[newTrigger] = snippet;
171 | [[HKSnippetSetting defaultSetting] sychronizeSetting];
172 | [weakSelf reloadDataWithKeyFilter:nil];
173 | };
174 | [self.snippetEditViewController showWindow:sender];
175 | }
176 |
177 | - (void)showErrorAlertWithMessage:(NSString *)message {
178 | NSAlert *alert = [[NSAlert alloc] init];
179 | [alert addButtonWithTitle:@"OK"];
180 | [alert setMessageText:@"Error"];
181 | [alert setInformativeText:message];
182 | [alert setAlertStyle:NSWarningAlertStyle];
183 | [alert beginSheetModalForWindow:self.window
184 | completionHandler:^(NSModalResponse returnCode) {
185 | if (returnCode == NSAlertFirstButtonReturn) {
186 | }
187 | }];
188 | }
189 |
190 | - (IBAction)exportSnippets:(id)sender {
191 | NSSavePanel *panel = [NSSavePanel savePanel];
192 | [panel setNameFieldStringValue:@"Untitle.plist"];
193 | [panel setMessage:@"Choose the path to save the config file."];
194 | [panel setAllowsOtherFileTypes:YES];
195 | [panel setAllowedFileTypes:@[@"plist"]];
196 | [panel setExtensionHidden:YES];
197 | [panel setCanCreateDirectories:YES];
198 | [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result){
199 | if (result == NSFileHandlingPanelOKButton)
200 | {
201 | NSString *path = [[panel URL] path];
202 | [[HKSnippetSetting defaultSetting].snippets writeToFile:path
203 | atomically:YES];
204 | }
205 | }];
206 | }
207 |
208 | - (IBAction)importSnippets:(id)sender {
209 | NSOpenPanel *openPanel = [NSOpenPanel openPanel];
210 | [openPanel setTitle:@"Choose a config file"];
211 | [openPanel setCanChooseDirectories:NO];
212 |
213 | if([openPanel runModal] == NSModalResponseOK) {
214 | NSURL *theFileURL = [openPanel URL];
215 | NSDictionary *dic = [NSDictionary dictionaryWithContentsOfURL:theFileURL];
216 | [HKSnippetSetting defaultSetting].snippets = [NSMutableDictionary dictionaryWithDictionary:dic];
217 | [[HKSnippetSetting defaultSetting] sychronizeSetting];
218 | [self reloadDataWithKeyFilter:nil];
219 | }
220 | }
221 |
222 | #pragma mark - NSTableView Datasource
223 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
224 | return _listOfKeys.count;
225 | }
226 |
227 | - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
228 |
229 | NSString *key = _listOfKeys[row];
230 | NSString *value = [HKSnippetSetting defaultSetting].snippets[key];
231 |
232 | if(tableColumn == tableView.tableColumns[0]) {
233 | tableColumn.title = @"Trigger";
234 | return key;
235 | }
236 | if (tableColumn == tableView.tableColumns[1]) {
237 | tableColumn.title = @"Snippet";
238 | return value;
239 | }
240 |
241 | return nil;
242 | }
243 |
244 | #pragma mark - NSTableView Delegate
245 |
246 | - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row {
247 | NSString *value = [HKSnippetSetting defaultSetting].snippets[_listOfKeys[row]];
248 | NSArray *lines = [value componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
249 | if (lines.count == 0 || lines.count == 1) {
250 | return 30;
251 | }
252 | return lines.count * 18;
253 | }
254 |
255 | @end
--------------------------------------------------------------------------------
/HKSnippet/HKSnippet.m:
--------------------------------------------------------------------------------
1 | //
2 | // HKSnippet.m
3 | // HKSnippet
4 | //
5 | // Created by Hunk on 16/2/4.
6 | // Copyright © 2016年 Taobao.com. All rights reserved.
7 | //
8 |
9 | #import "HKSnippet.h"
10 | #import "HKTextResult.h"
11 | #import "HKSnippetSetting.h"
12 | #import "NSTextView+Snippet.h"
13 | #import "HKSnippetSettingController.h"
14 | #import "HKKeyboardEventSender.h"
15 |
16 | static HKSnippet *sharedPlugin;
17 |
18 | @interface HKSnippet()
19 |
20 | @property (nonatomic, strong, readwrite) NSBundle *bundle;
21 | @property (nonatomic, strong) HKSnippetSettingController *settingWindow;
22 | @property (nonatomic, strong) id eventMonitor;
23 | @property (nonatomic, assign) BOOL shouldReplace;
24 |
25 | @end
26 |
27 | @implementation HKSnippet
28 |
29 | #pragma mark - LifeCycle
30 | + (void)pluginDidLoad:(NSBundle *)plugin {
31 | static dispatch_once_t onceToken;
32 | NSString *currentApplicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"];
33 | if ([currentApplicationName isEqual:@"Xcode"]) {
34 | dispatch_once(&onceToken, ^{
35 | sharedPlugin = [[self alloc] initWithBundle:plugin];
36 | });
37 | }
38 | }
39 |
40 | + (instancetype)sharedPlugin {
41 | return sharedPlugin;
42 | }
43 |
44 | - (id)initWithBundle:(NSBundle *)plugin {
45 | if (self = [super init]) {
46 | _bundle = plugin;
47 | _shouldReplace = YES;
48 | [[NSNotificationCenter defaultCenter] addObserver:self
49 | selector:@selector(textStorageDidChange:)
50 | name:NSTextDidChangeNotification
51 | object:nil];
52 | [[NSNotificationCenter defaultCenter] addObserver:self
53 | selector:@selector(xcodeDidLoad)
54 | name:NSApplicationDidFinishLaunchingNotification
55 | object:nil];
56 | }
57 | return self;
58 | }
59 |
60 | - (void)dealloc {
61 | [[NSNotificationCenter defaultCenter] removeObserver:self];
62 | }
63 |
64 | - (void)xcodeDidLoad {
65 | [[NSNotificationCenter defaultCenter] removeObserver:self
66 | name:NSApplicationDidFinishLaunchingNotification
67 | object:nil];
68 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{
69 | [self addMenuItem];
70 | }];
71 | }
72 |
73 | #pragma mark - Notification Callback
74 | - (void)textStorageDidChange:(NSNotification *)notification {
75 | if (![[HKSnippetSetting defaultSetting] enabled]) {
76 | return;
77 | }
78 |
79 | if ([[notification object] isKindOfClass:[NSTextView class]]) {
80 | NSTextView *textView = (NSTextView *)[notification object];
81 | HKTextResult *currentLineResult = [textView textResultOfCurrentLine];
82 | NSString *cmdString = currentLineResult.string;
83 |
84 | // line start with "@", means no parameters
85 | if ([cmdString hasPrefix:@"@"]) {
86 | // replacement snippet exist
87 | if ([HKSnippetSetting defaultSetting].snippets[cmdString]) {
88 | [self pasteSnippet:[HKSnippetSetting defaultSetting].snippets[cmdString]
89 | byTriggerString:cmdString
90 | toTextView:textView
91 | withParameters:nil];
92 | }
93 | } else {
94 | // Replace part (start with ^) exist
95 | if ([cmdString containsString:@"^"]) {
96 | NSUInteger replaceIndex = [cmdString rangeOfString:@"^"].location;
97 | NSString *replaceTrigger = [cmdString substringFromIndex:replaceIndex];
98 | NSString *snippet = [HKSnippetSetting defaultSetting].snippets[replaceTrigger];
99 | if (snippet) {
100 | [self pasteSnippet:snippet
101 | byTriggerString:replaceTrigger
102 | toTextView:textView
103 | withParameters:nil];
104 | }
105 | }
106 |
107 | // Get parameters
108 | NSRange r = [cmdString rangeOfString:@"@" options:NSBackwardsSearch];
109 | if (r.location > 0 && r.length == 1) {
110 | NSString *parameterString = [cmdString substringToIndex:r.location];
111 | NSString *triggerString = [cmdString substringFromIndex:(r.location)];
112 | NSArray *parameters = [parameterString componentsSeparatedByString:@"|"];
113 | NSDictionary *snippets = [HKSnippetSetting defaultSetting].snippets;
114 | NSString *snippet = snippets[triggerString];
115 | if (snippet) {
116 | [self pasteSnippet:[[self class] replacedSnippet:snippet withParameters:parameters]
117 | byTriggerString:cmdString
118 | toTextView:textView
119 | withParameters:parameters];
120 | }
121 | }
122 | }
123 | }
124 | }
125 |
126 |
127 | #pragma mark - UI
128 | - (void)addMenuItem {
129 | NSMenu *mainMenu = [NSApp mainMenu];
130 | NSMenuItem *pluginsMenuItem = [mainMenu itemWithTitle:@"Plugins"];
131 | if (!pluginsMenuItem) {
132 | pluginsMenuItem = [[NSMenuItem alloc] init];
133 | pluginsMenuItem.title = @"Plugins";
134 | pluginsMenuItem.submenu = [[NSMenu alloc] initWithTitle:pluginsMenuItem.title];
135 | NSInteger windowIndex = [mainMenu indexOfItemWithTitle:@"Window"];
136 | [mainMenu insertItem:pluginsMenuItem atIndex:windowIndex];
137 | }
138 | NSMenuItem *mainMenuItem = [[NSMenuItem alloc] initWithTitle:@"HKSnippet"
139 | action:@selector(showSettingWindow)
140 | keyEquivalent:@""];
141 | [mainMenuItem setTarget:self];
142 | [pluginsMenuItem.submenu addItem:mainMenuItem];
143 | }
144 |
145 | - (void)showSettingWindow {
146 | self.settingWindow = [[HKSnippetSettingController alloc] initWithWindowNibName:@"HKSnippetSettingController"];
147 | [self.settingWindow showWindow:self.settingWindow];
148 | }
149 |
150 | #pragma mark - Private Method
151 | + (void)setPasteboardString:(NSString *)aString {
152 | NSPasteboard *thePasteboard = [NSPasteboard generalPasteboard];
153 | [thePasteboard clearContents];
154 | [thePasteboard declareTypes:@[NSStringPboardType] owner:nil];
155 | [thePasteboard setString:aString forType:NSStringPboardType];
156 | }
157 |
158 | + (NSString *)getPasteboardString {
159 | NSString *retValue = nil;
160 | NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
161 | NSArray *types = [pasteboard types];
162 | if ([types containsObject:NSStringPboardType]) {
163 | retValue = [pasteboard stringForType:NSStringPboardType];
164 | }
165 | return retValue;
166 | }
167 |
168 | - (void)resetShouldReplace {
169 | self.shouldReplace = YES;
170 | }
171 |
172 | - (void)pasteSnippet:(NSString *)snippet
173 | byTriggerString:(NSString *)triggerString
174 | toTextView:(NSTextView *)textView
175 | withParameters:(NSArray *)parameters {
176 |
177 | if (!self.shouldReplace) {
178 | [self resetShouldReplace];
179 | return;
180 | }
181 |
182 | NSUInteger length = triggerString.length;
183 | // save pasteboard string for restore
184 | NSString *oldPasteString = [[self class] getPasteboardString];
185 | [[self class] setPasteboardString:snippet];
186 |
187 | [textView setSelectedRange:NSMakeRange(textView.currentCurseLocation - length, length)];
188 |
189 | //Begin to simulate keyborad pressing
190 | HKKeyboardEventSender *kes = [[HKKeyboardEventSender alloc] init];
191 | [kes beginKeyBoradEvents];
192 |
193 | //Cmd+delete Delete current line
194 | [kes sendKeyCode:kVK_Delete withModifierCommand:YES alt:NO shift:NO control:NO];
195 |
196 | //Cmd+V, paste (which key to actually use is based on the current keyboard layout)
197 | NSInteger kKeyVCode = [kes keyVCode];
198 | [kes sendKeyCode:kKeyVCode withModifierCommand:YES alt:NO shift:NO control:NO];
199 |
200 | //The key down is just a defined finish signal by me. When we receive this key,
201 | //we know operation above is finished.
202 | [kes sendKeyCode:kVK_F19];
203 |
204 | __weak typeof(self) weakSelf = self;
205 | self.eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask
206 | handler:^ NSEvent *(NSEvent *incomingEvent) {
207 | if ([incomingEvent type] == NSKeyDown &&
208 | [incomingEvent keyCode] == kVK_F19) {
209 | //Finish signal arrived, no need to observe the event
210 | [NSEvent removeMonitor:weakSelf.eventMonitor];
211 | weakSelf.eventMonitor = nil;
212 |
213 | //Restore previois patse board content
214 | if (oldPasteString) {
215 | [[self class] setPasteboardString:oldPasteString];
216 | }
217 | if ([snippet containsString:@"<#"]) {
218 | //Set cursor before the inserted snippet. So we can use tab to begin edit.
219 | int snippetLength = (int)snippet.length;
220 | [textView setSelectedRange:NSMakeRange(textView.currentCurseLocation - snippetLength, 0)];
221 |
222 | //Send a 'tab' after insert the snippet. For our lazy programmers. :-)
223 | [kes sendKeyCode:kVK_Tab];
224 | [kes endKeyBoradEvents];
225 | }
226 |
227 | weakSelf.shouldReplace = NO;
228 | //Invalidate the finish signal, in case you set it to do some other thing.
229 | return nil;
230 | } else {
231 | return incomingEvent;
232 | }
233 | }];
234 | [self performSelector:@selector(resetShouldReplace)
235 | withObject:nil
236 | afterDelay:3.0f];
237 | }
238 |
239 | + (NSString *)replacedSnippet:(NSString *)orgSnippet
240 | withParameters:(NSArray *)parameter {
241 | NSString *snippet = [NSString stringWithString:orgSnippet];
242 | snippet = [snippet stringByReplacingOccurrencesOfString:@"<#name#>"
243 | withString:parameter[0]];
244 | for (NSString *p in parameter) {
245 | NSString *uppercaseP = p.uppercaseString;
246 |
247 | if ([uppercaseP containsString:@"FONT"]) {
248 | snippet = [snippet stringByReplacingOccurrencesOfString:@"<#font#>"
249 | withString:p];
250 | continue;
251 | }
252 | // replace color
253 | if ([uppercaseP containsString:@"COLOR"]) {
254 | snippet = [snippet stringByReplacingOccurrencesOfString:@"<#color#>"
255 | withString:p];
256 | continue;
257 | }
258 | // replace image
259 | if ([uppercaseP containsString:@"UIIMAGE"]) {
260 | snippet = [snippet stringByReplacingOccurrencesOfString:@"<#image#>"
261 | withString:p];
262 | continue;
263 | }
264 | // replace selector
265 | if ([uppercaseP containsString:@"SELECTOR"]) {
266 | snippet = [snippet stringByReplacingOccurrencesOfString:@"<#selector#>"
267 | withString:p];
268 | continue;
269 | }
270 | }
271 | return snippet;
272 | }
273 |
274 | @end
275 |
--------------------------------------------------------------------------------
/HKSnippet/default_snippets.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @ani
6 | [UIView animateWithDuration:<#(NSTimeInterval)#>
7 | animations:^{
8 | <#code#>
9 | } completion:^(BOOL finished) {
10 | <#code#>
11 | }];
12 | @button
13 | UIButton *<#name#> = [UIButton new];
14 | <#name#>.backgroundColor = [UIColor clearColor];
15 | [<#name#> setTitleColor:<#title color#> forState:UIControlStateNormal];
16 | [<#name#> setTitle:<# title #> forState:UIControlStateNormal];
17 | [<#name#> setImage:<#image#> forState:UIControlStateNormal];
18 | @cf
19 | static CGFloat const <#name#> = <#value#>;
20 | @cs
21 | static NSString * const <#name#> = @"<#value#>";
22 | @de
23 | - (void)dealloc {
24 | [[NSNotificationCenter defaultCenter] removeObserver:self];
25 | }
26 | @do
27 | do {
28 | <#statements#>
29 | } while (<#condition#>);
30 | @enum
31 | typedef enum : NSUInteger {
32 | <#MyEnumValueA#>,
33 | <#MyEnumValueB#>,
34 | <#MyEnumValueC#>,
35 | } <#MyEnum#>;
36 | @fb
37 | - (UIButton *)<#name#> {
38 | if(!_<#name#>) {
39 | _<#name#> = [UIButton new];
40 | _<#name#>.layer.cornerRadius = <#radius#>;
41 | _<#name#>.layer.masksToBounds = YES;
42 | _<#name#>.backgroundColor = [UIColor clearColor];
43 | [_<#name#> setTitleColor:<#title color#> forState:UIControlStateNormal];
44 | [_<#name#> setTitle:<# title #> forState:UIControlStateNormal];
45 | [_<#name#> setImage:<#image#> forState:UIControlStateNormal];
46 | }
47 | return _<#name#>;
48 | }
49 | @fd
50 | - (NSString *)description
51 | {
52 | return [NSString stringWithFormat:@"<#format string#>", <#arguments#>];
53 | }
54 | @ff
55 | - (<#type#> *)<#name#> {
56 | if(!_<#name#>) {
57 | <#Init Code#>
58 | }
59 | return _<#name#>;
60 | }
61 | @fi
62 | - (UIImageView *)<#name#> {
63 | if(!_<#name#>) {
64 | _<#name#> = [UIImageView new];
65 | _<#name#>.layer.cornerRadius = <#radius#>;
66 | _<#name#>.layer.masksToBounds = YES;
67 | _<#name#>.backgroundColor = [UIColor clearColor];
68 | _<#name#>.image = <#image#>;
69 | }
70 | return _<#name#>;
71 | }
72 | @fl
73 | - (UILabel *)<#name#> {
74 | if(!_<#name#>) {
75 | _<#name#> = [UILabel new];
76 | _<#name#>.backgroundColor = [UIColor clearColor];
77 | _<#name#>.textAlignment = NSTextAlignmentCenter;
78 | _<#name#>.numberOfLines = 0;
79 | _<#name#>.textColor = <#color#>;
80 | _<#name#>.font = <#font#>;
81 | _<#name#>.text = <#text#>;
82 | }
83 | return _<#name#>;
84 | }
85 | @for
86 | for (<#type#> *<#object#> in <#collection#>) {
87 | <#statements#>
88 | }
89 | @ft
90 | - (UITableView *)<#name#> {
91 | if(!_<#name#>) {
92 | _<#name#> = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
93 | _<#name#>.backgroundColor = [UIColor clearColor];
94 | _<#name#>.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
95 | _<#name#>.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
96 | _<#name#>.separatorColor = <#color#>;
97 | _<#name#>.delegate = <#table delegate#>;
98 | _<#name#>.dataSource = <#table datasource#>;
99 |
100 | [_<#name#> registerClass:[<#class name#> class] forCellReuseIdentifier:<#cellId#>];
101 | }
102 | return _<#name#>;
103 | }
104 | @fv
105 | - (UIView *)<#name#> {
106 | if(!_<#name#>) {
107 | _<#name#> = [UIView new];
108 | _<#name#>.backgroundColor = <#color#>;
109 | }
110 | return _<#name#>;
111 | }
112 | @gmk
113 | #pragma mark - Getters & Setters
114 | @imageV
115 | UIImageView *<#name#> = [UIImageView new];
116 | <#name#>.layer.cornerRadius = <#radius#>;
117 | <#name#>.layer.masksToBounds = YES;
118 | <#name#>.backgroundColor = [UIColor clearColor];
119 | <#name#>.image = <#image#>;
120 | @init
121 | - (instancetype)init {
122 | self = [super init];
123 | if (self) {
124 | <#statements#>
125 | }
126 | return self;
127 | }
128 | @it
129 | @interface <#name#> ()
130 |
131 | <#Property#>
132 |
133 | @end
134 | @kvo
135 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
136 | {
137 | if (context == <#context#>) {
138 | <#code to be executed upon observing keypath#>
139 | } else {
140 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
141 | }
142 | }
143 | @label
144 | UILabel *<#name#> = [UILabel new];
145 | <#name#>.backgroundColor = [UIColor clearColor];
146 | <#name#>.textAlignment = NSTextAlignmentCenter;
147 | <#name#>.numberOfLines = 0;
148 | <#name#>.textColor = <#color#>;
149 | <#name#>.font = <#font#>;
150 | <#name#>.text = <#text#>;
151 | @lmk
152 | #pragma mark - LifeCycle
153 | @log
154 | NSLog(@"<#format#>",<#data#>);
155 | @ls
156 | - (void)layoutSubviews {
157 | [super layoutSubviews];
158 | CGFloat w = self.frame.size.width;
159 | CGFloat h = self.frame.size.height;
160 | <#set subview frames#>
161 | }
162 | @lv
163 | - (void)loadView {
164 | [super loadView];
165 | <#set subview frames#>
166 | }
167 | @mk
168 | #pragma mark - <#section title#>
169 | @model
170 | - (NSString *)apiVersion {
171 | return @"1.0";
172 | }
173 |
174 | - (NSString *)methodName {
175 | return @"";
176 | }
177 |
178 | - (BOOL)useAuth {
179 | return YES;
180 | }
181 |
182 | - (NSInteger)pageSize {
183 | return 20;
184 | }
185 |
186 | - (NSDictionary *)dataParams {
187 | return @{};
188 | }
189 |
190 | - (NSMutableArray *)constructDataArray:(NSDictionary *)requestData {
191 | NSMutableArray *tmpArray = [NSMutableArray array];
192 | // NSArray *<#data list#> = requestData[@"data"];
193 | // for (NSDictionary *dic in <#data list#> ) {
194 | // <#item class#> *item = [[<#item class#> alloc] init];
195 | // [item tddAutoSetPropertySafety:dic];
196 | // [tmpArray addObject:item];
197 | // }
198 | return tmpArray;
199 | }
200 | @nsuser
201 | [[NSUserDefaults standardUserDefaults] setObject:<#object#> forKey:<#key#>];
202 | @ob
203 | [[NSNotificationCenter defaultCenter] addObserver:self
204 | selector:@selector(<#selector#>)
205 | name:<#Notification#>
206 | object:nil];
207 | @pa
208 | @property (assign) <#type#> <#value#>;
209 | @pc
210 | @property (copy) <#type#> *<#value#>;
211 | @pmk
212 | #pragma mark - Private Method
213 | @pna
214 | @property (nonatomic, assign) <#type#> <#value#>;
215 | @pnc
216 | @property (nonatomic, copy) <#type#> *<#value#>;
217 | @pns
218 | @property (nonatomic, strong) <#type#> *<#value#>;
219 | @pnw
220 | @property (nonatomic, weak) <#type#> *<#value#>;
221 | @pra
222 | @property (assign, readonly) <#type#> <#value#>;
223 | @prc
224 | @property (copy, readonly) <#type#> *<#value#>;
225 | @prna
226 | @property (nonatomic, assign, readonly) <#type#> <#value#>;
227 | @prnc
228 | @property (nonatomic, copy, readonly) <#type#> *<#value#>;
229 | @prns
230 | @property (nonatomic, strong, readonly) <#type#> *<#value#>;
231 | @prnw
232 | @property (nonatomic, weak, readonly) <#type#> *<#value#>;
233 | @prs
234 | @property (strong, readonly) <#type#> *<#value#>;
235 | @prw
236 | @property (weak, readonly) <#type#> *<#value#>;
237 | @ps
238 | @property (strong) <#type#> *<#value#>;
239 | @pw
240 | @property (weak) <#type#> *<#value#>;
241 | @qf
242 | - (void)<#name#> {
243 |
244 | }
245 |
246 | @singleton
247 | + (instancetype)sharedManager {
248 | static <#Class#> *_sharedInstance = nil;
249 | static dispatch_once_t onceToken;
250 | dispatch_once(&onceToken, ^{
251 | if (!_sharedInstance) {
252 | _sharedInstance = [[<#Class#> alloc] init];
253 | }
254 | });
255 | return _sharedInstance;
256 | }
257 | @ss
258 | __strong typeof(weakSelf) strongSelf = weakSelf;
259 | @table
260 | UITableView *<#name#> = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
261 | <#name#>.backgroundColor = [UIColor clearColor];
262 | <#name#>.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
263 | <#name#>.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
264 | <#name#>.separatorColor = <#color#>;
265 | <#name#>.delegate = <#table delegate#>;
266 | <#name#>.dataSource = <#table datasource#>;
267 |
268 | [<#name#> registerClass:[<#class name#> class] forCellReuseIdentifier:<#cellId#>];
269 | @tdd
270 | #pragma mark - UITableViewDataSource
271 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
272 | return <#rows#>;
273 | }
274 |
275 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
276 |
277 | UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:<#CellId#>];
278 |
279 | return cell;
280 | }
281 |
282 | #pragma mark - UITableViewDelegate
283 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
284 | return <#height#>;
285 | }
286 |
287 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
288 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
289 |
290 | }
291 |
292 | @try
293 | @try {
294 | <#Code that can potentially throw an exception#>
295 | }
296 | @catch (NSException *exception) {
297 | <#Handle an exception thrown in the @try block#>
298 | }
299 | @finally {
300 | <#Code that gets executed whether or not an exception is thrown#>
301 | }
302 | @view
303 | UIView *<#name#> = [UIView new];
304 | <#name#>.backgroundColor = <#color#>;
305 | @vl
306 | - (void)viewWillLayoutSubviews {
307 | [super viewWillLayoutSubviews];
308 | CGFloat w = self.view.frame.size.width;
309 | CGFloat h = self.view.frame.size.height;
310 | <# set subview frames #>
311 | }
312 | @while
313 | while (<#condition#>) {
314 | <#statements#>
315 | }
316 | @ws
317 | __weak typeof(self) weakSelf = self;
318 | ^a
319 | [[<#Class#> alloc] init];
320 | ^s
321 | [NSString stringWithFormat:@"%@",<#value#>];
322 |
323 |
324 |
--------------------------------------------------------------------------------
/Setting/HKSnippetEditViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
93 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/HKSnippet.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 18194CAC1B169D94007A3FB0 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18194CAB1B169D94007A3FB0 /* AppKit.framework */; };
11 | 18194CAE1B169D94007A3FB0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18194CAD1B169D94007A3FB0 /* Foundation.framework */; };
12 | 18194CB61B169D94007A3FB0 /* HKSnippet.m in Sources */ = {isa = PBXBuildFile; fileRef = 18194CB51B169D94007A3FB0 /* HKSnippet.m */; };
13 | 18194CC31B16A122007A3FB0 /* HKTextResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 18194CC21B16A122007A3FB0 /* HKTextResult.m */; };
14 | 18B907F41B16F086009033BF /* HKSnippetSettingController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18B907F21B16F086009033BF /* HKSnippetSettingController.m */; };
15 | 18B907F51B16F086009033BF /* HKSnippetSettingController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 18B907F31B16F086009033BF /* HKSnippetSettingController.xib */; };
16 | 18BA9E501B16ACB300F471AF /* HKSnippetSetting.m in Sources */ = {isa = PBXBuildFile; fileRef = 18BA9E4F1B16ACB300F471AF /* HKSnippetSetting.m */; };
17 | B40AE1641C708030004CE9B9 /* HKSnippetEditViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B40AE1621C708030004CE9B9 /* HKSnippetEditViewController.m */; };
18 | B40AE1651C708030004CE9B9 /* HKSnippetEditViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B40AE1631C708030004CE9B9 /* HKSnippetEditViewController.xib */; };
19 | B47099881C7969F30001329F /* default_snippets.plist in Resources */ = {isa = PBXBuildFile; fileRef = B47099871C7969F30001329F /* default_snippets.plist */; };
20 | B4971C731C78C1D600B80D96 /* HKKeyboardEventSender.m in Sources */ = {isa = PBXBuildFile; fileRef = B4971C721C78C1D600B80D96 /* HKKeyboardEventSender.m */; };
21 | B4CB74411C7057C60093E911 /* NSString+Snippet.m in Sources */ = {isa = PBXBuildFile; fileRef = B4CB743E1C7057C60093E911 /* NSString+Snippet.m */; };
22 | B4CB74421C7057C60093E911 /* NSTextView+Snippet.m in Sources */ = {isa = PBXBuildFile; fileRef = B4CB74401C7057C60093E911 /* NSTextView+Snippet.m */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXFileReference section */
26 | 18194CA81B169D94007A3FB0 /* HKSnippet.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HKSnippet.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; };
27 | 18194CAB1B169D94007A3FB0 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; };
28 | 18194CAD1B169D94007A3FB0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; };
29 | 18194CB11B169D94007A3FB0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
30 | 18194CB41B169D94007A3FB0 /* HKSnippet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HKSnippet.h; sourceTree = ""; };
31 | 18194CB51B169D94007A3FB0 /* HKSnippet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HKSnippet.m; sourceTree = ""; };
32 | 18194CC11B16A122007A3FB0 /* HKTextResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HKTextResult.h; sourceTree = ""; };
33 | 18194CC21B16A122007A3FB0 /* HKTextResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HKTextResult.m; sourceTree = ""; };
34 | 18B907F11B16F086009033BF /* HKSnippetSettingController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HKSnippetSettingController.h; sourceTree = ""; };
35 | 18B907F21B16F086009033BF /* HKSnippetSettingController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HKSnippetSettingController.m; sourceTree = ""; };
36 | 18B907F31B16F086009033BF /* HKSnippetSettingController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HKSnippetSettingController.xib; sourceTree = ""; };
37 | 18BA9E4E1B16ACB300F471AF /* HKSnippetSetting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HKSnippetSetting.h; sourceTree = ""; };
38 | 18BA9E4F1B16ACB300F471AF /* HKSnippetSetting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HKSnippetSetting.m; sourceTree = ""; };
39 | B40AE1611C708030004CE9B9 /* HKSnippetEditViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HKSnippetEditViewController.h; sourceTree = ""; };
40 | B40AE1621C708030004CE9B9 /* HKSnippetEditViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HKSnippetEditViewController.m; sourceTree = ""; };
41 | B40AE1631C708030004CE9B9 /* HKSnippetEditViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HKSnippetEditViewController.xib; sourceTree = ""; };
42 | B47099871C7969F30001329F /* default_snippets.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = default_snippets.plist; sourceTree = ""; };
43 | B4971C711C78C1D600B80D96 /* HKKeyboardEventSender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HKKeyboardEventSender.h; sourceTree = ""; };
44 | B4971C721C78C1D600B80D96 /* HKKeyboardEventSender.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HKKeyboardEventSender.m; sourceTree = ""; };
45 | B4CB743D1C7057C60093E911 /* NSString+Snippet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Snippet.h"; sourceTree = ""; };
46 | B4CB743E1C7057C60093E911 /* NSString+Snippet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Snippet.m"; sourceTree = ""; };
47 | B4CB743F1C7057C60093E911 /* NSTextView+Snippet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTextView+Snippet.h"; sourceTree = ""; };
48 | B4CB74401C7057C60093E911 /* NSTextView+Snippet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTextView+Snippet.m"; sourceTree = ""; };
49 | /* End PBXFileReference section */
50 |
51 | /* Begin PBXFrameworksBuildPhase section */
52 | 18194CA61B169D93007A3FB0 /* Frameworks */ = {
53 | isa = PBXFrameworksBuildPhase;
54 | buildActionMask = 2147483647;
55 | files = (
56 | 18194CAC1B169D94007A3FB0 /* AppKit.framework in Frameworks */,
57 | 18194CAE1B169D94007A3FB0 /* Foundation.framework in Frameworks */,
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXFrameworksBuildPhase section */
62 |
63 | /* Begin PBXGroup section */
64 | 18194C9F1B169D93007A3FB0 = {
65 | isa = PBXGroup;
66 | children = (
67 | 18194CAF1B169D94007A3FB0 /* HKSnippet */,
68 | 18194CAA1B169D94007A3FB0 /* Frameworks */,
69 | 18194CA91B169D94007A3FB0 /* Products */,
70 | );
71 | sourceTree = "";
72 | };
73 | 18194CA91B169D94007A3FB0 /* Products */ = {
74 | isa = PBXGroup;
75 | children = (
76 | 18194CA81B169D94007A3FB0 /* HKSnippet.xcplugin */,
77 | );
78 | name = Products;
79 | sourceTree = "";
80 | };
81 | 18194CAA1B169D94007A3FB0 /* Frameworks */ = {
82 | isa = PBXGroup;
83 | children = (
84 | 18194CAB1B169D94007A3FB0 /* AppKit.framework */,
85 | 18194CAD1B169D94007A3FB0 /* Foundation.framework */,
86 | );
87 | name = Frameworks;
88 | sourceTree = "";
89 | };
90 | 18194CAF1B169D94007A3FB0 /* HKSnippet */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 18BA9E4D1B16ACA700F471AF /* Setting */,
94 | 18194CBC1B16A0AE007A3FB0 /* Category */,
95 | 18194CB41B169D94007A3FB0 /* HKSnippet.h */,
96 | 18194CB51B169D94007A3FB0 /* HKSnippet.m */,
97 | 18194CB01B169D94007A3FB0 /* Supporting Files */,
98 | );
99 | path = HKSnippet;
100 | sourceTree = "";
101 | };
102 | 18194CB01B169D94007A3FB0 /* Supporting Files */ = {
103 | isa = PBXGroup;
104 | children = (
105 | B47099871C7969F30001329F /* default_snippets.plist */,
106 | 18194CB11B169D94007A3FB0 /* Info.plist */,
107 | );
108 | name = "Supporting Files";
109 | sourceTree = "";
110 | };
111 | 18194CBC1B16A0AE007A3FB0 /* Category */ = {
112 | isa = PBXGroup;
113 | children = (
114 | B4971C711C78C1D600B80D96 /* HKKeyboardEventSender.h */,
115 | B4971C721C78C1D600B80D96 /* HKKeyboardEventSender.m */,
116 | B4CB743D1C7057C60093E911 /* NSString+Snippet.h */,
117 | B4CB743E1C7057C60093E911 /* NSString+Snippet.m */,
118 | B4CB743F1C7057C60093E911 /* NSTextView+Snippet.h */,
119 | B4CB74401C7057C60093E911 /* NSTextView+Snippet.m */,
120 | 18194CC11B16A122007A3FB0 /* HKTextResult.h */,
121 | 18194CC21B16A122007A3FB0 /* HKTextResult.m */,
122 | );
123 | path = Category;
124 | sourceTree = SOURCE_ROOT;
125 | };
126 | 18BA9E4D1B16ACA700F471AF /* Setting */ = {
127 | isa = PBXGroup;
128 | children = (
129 | 18BA9E4E1B16ACB300F471AF /* HKSnippetSetting.h */,
130 | 18BA9E4F1B16ACB300F471AF /* HKSnippetSetting.m */,
131 | 18B907F11B16F086009033BF /* HKSnippetSettingController.h */,
132 | 18B907F21B16F086009033BF /* HKSnippetSettingController.m */,
133 | 18B907F31B16F086009033BF /* HKSnippetSettingController.xib */,
134 | B40AE1611C708030004CE9B9 /* HKSnippetEditViewController.h */,
135 | B40AE1621C708030004CE9B9 /* HKSnippetEditViewController.m */,
136 | B40AE1631C708030004CE9B9 /* HKSnippetEditViewController.xib */,
137 | );
138 | path = Setting;
139 | sourceTree = SOURCE_ROOT;
140 | };
141 | /* End PBXGroup section */
142 |
143 | /* Begin PBXNativeTarget section */
144 | 18194CA71B169D93007A3FB0 /* HKSnippet */ = {
145 | isa = PBXNativeTarget;
146 | buildConfigurationList = 18194CB91B169D94007A3FB0 /* Build configuration list for PBXNativeTarget "HKSnippet" */;
147 | buildPhases = (
148 | 18194CA41B169D93007A3FB0 /* Sources */,
149 | 18194CA51B169D93007A3FB0 /* Resources */,
150 | 18194CA61B169D93007A3FB0 /* Frameworks */,
151 | );
152 | buildRules = (
153 | );
154 | dependencies = (
155 | );
156 | name = HKSnippet;
157 | productName = HKSnippet;
158 | productReference = 18194CA81B169D94007A3FB0 /* HKSnippet.xcplugin */;
159 | productType = "com.apple.product-type.bundle";
160 | };
161 | /* End PBXNativeTarget section */
162 |
163 | /* Begin PBXProject section */
164 | 18194CA01B169D93007A3FB0 /* Project object */ = {
165 | isa = PBXProject;
166 | attributes = {
167 | CLASSPREFIX = HK;
168 | LastUpgradeCheck = 0720;
169 | ORGANIZATIONNAME = Taobao.com;
170 | TargetAttributes = {
171 | 18194CA71B169D93007A3FB0 = {
172 | CreatedOnToolsVersion = 6.3;
173 | };
174 | };
175 | };
176 | buildConfigurationList = 18194CA31B169D93007A3FB0 /* Build configuration list for PBXProject "HKSnippet" */;
177 | compatibilityVersion = "Xcode 3.2";
178 | developmentRegion = English;
179 | hasScannedForEncodings = 0;
180 | knownRegions = (
181 | en,
182 | );
183 | mainGroup = 18194C9F1B169D93007A3FB0;
184 | productRefGroup = 18194CA91B169D94007A3FB0 /* Products */;
185 | projectDirPath = "";
186 | projectRoot = "";
187 | targets = (
188 | 18194CA71B169D93007A3FB0 /* HKSnippet */,
189 | );
190 | };
191 | /* End PBXProject section */
192 |
193 | /* Begin PBXResourcesBuildPhase section */
194 | 18194CA51B169D93007A3FB0 /* Resources */ = {
195 | isa = PBXResourcesBuildPhase;
196 | buildActionMask = 2147483647;
197 | files = (
198 | B47099881C7969F30001329F /* default_snippets.plist in Resources */,
199 | 18B907F51B16F086009033BF /* HKSnippetSettingController.xib in Resources */,
200 | B40AE1651C708030004CE9B9 /* HKSnippetEditViewController.xib in Resources */,
201 | );
202 | runOnlyForDeploymentPostprocessing = 0;
203 | };
204 | /* End PBXResourcesBuildPhase section */
205 |
206 | /* Begin PBXSourcesBuildPhase section */
207 | 18194CA41B169D93007A3FB0 /* Sources */ = {
208 | isa = PBXSourcesBuildPhase;
209 | buildActionMask = 2147483647;
210 | files = (
211 | 18BA9E501B16ACB300F471AF /* HKSnippetSetting.m in Sources */,
212 | B4CB74411C7057C60093E911 /* NSString+Snippet.m in Sources */,
213 | B4971C731C78C1D600B80D96 /* HKKeyboardEventSender.m in Sources */,
214 | B4CB74421C7057C60093E911 /* NSTextView+Snippet.m in Sources */,
215 | B40AE1641C708030004CE9B9 /* HKSnippetEditViewController.m in Sources */,
216 | 18B907F41B16F086009033BF /* HKSnippetSettingController.m in Sources */,
217 | 18194CB61B169D94007A3FB0 /* HKSnippet.m in Sources */,
218 | 18194CC31B16A122007A3FB0 /* HKTextResult.m in Sources */,
219 | );
220 | runOnlyForDeploymentPostprocessing = 0;
221 | };
222 | /* End PBXSourcesBuildPhase section */
223 |
224 | /* Begin XCBuildConfiguration section */
225 | 18194CB71B169D94007A3FB0 /* Debug */ = {
226 | isa = XCBuildConfiguration;
227 | buildSettings = {
228 | ALWAYS_SEARCH_USER_PATHS = NO;
229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
230 | CLANG_CXX_LIBRARY = "libc++";
231 | CLANG_ENABLE_MODULES = YES;
232 | CLANG_ENABLE_OBJC_ARC = YES;
233 | CLANG_WARN_BOOL_CONVERSION = YES;
234 | CLANG_WARN_CONSTANT_CONVERSION = YES;
235 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
236 | CLANG_WARN_EMPTY_BODY = YES;
237 | CLANG_WARN_ENUM_CONVERSION = YES;
238 | CLANG_WARN_INT_CONVERSION = YES;
239 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
240 | CLANG_WARN_UNREACHABLE_CODE = YES;
241 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
242 | COPY_PHASE_STRIP = NO;
243 | ENABLE_STRICT_OBJC_MSGSEND = YES;
244 | ENABLE_TESTABILITY = YES;
245 | GCC_C_LANGUAGE_STANDARD = gnu99;
246 | GCC_DYNAMIC_NO_PIC = NO;
247 | GCC_NO_COMMON_BLOCKS = YES;
248 | GCC_OPTIMIZATION_LEVEL = 0;
249 | GCC_PREPROCESSOR_DEFINITIONS = (
250 | "DEBUG=1",
251 | "$(inherited)",
252 | );
253 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
254 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
255 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
256 | GCC_WARN_UNDECLARED_SELECTOR = YES;
257 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
258 | GCC_WARN_UNUSED_FUNCTION = YES;
259 | GCC_WARN_UNUSED_VARIABLE = YES;
260 | MTL_ENABLE_DEBUG_INFO = YES;
261 | ONLY_ACTIVE_ARCH = YES;
262 | STRINGS_FILE_OUTPUT_ENCODING = "UTF-8";
263 | };
264 | name = Debug;
265 | };
266 | 18194CB81B169D94007A3FB0 /* Release */ = {
267 | isa = XCBuildConfiguration;
268 | buildSettings = {
269 | ALWAYS_SEARCH_USER_PATHS = NO;
270 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
271 | CLANG_CXX_LIBRARY = "libc++";
272 | CLANG_ENABLE_MODULES = YES;
273 | CLANG_ENABLE_OBJC_ARC = YES;
274 | CLANG_WARN_BOOL_CONVERSION = YES;
275 | CLANG_WARN_CONSTANT_CONVERSION = YES;
276 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
277 | CLANG_WARN_EMPTY_BODY = YES;
278 | CLANG_WARN_ENUM_CONVERSION = YES;
279 | CLANG_WARN_INT_CONVERSION = YES;
280 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
281 | CLANG_WARN_UNREACHABLE_CODE = YES;
282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
283 | COPY_PHASE_STRIP = NO;
284 | ENABLE_NS_ASSERTIONS = NO;
285 | ENABLE_STRICT_OBJC_MSGSEND = YES;
286 | GCC_C_LANGUAGE_STANDARD = gnu99;
287 | GCC_NO_COMMON_BLOCKS = YES;
288 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
289 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
290 | GCC_WARN_UNDECLARED_SELECTOR = YES;
291 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
292 | GCC_WARN_UNUSED_FUNCTION = YES;
293 | GCC_WARN_UNUSED_VARIABLE = YES;
294 | MTL_ENABLE_DEBUG_INFO = NO;
295 | STRINGS_FILE_OUTPUT_ENCODING = "UTF-8";
296 | };
297 | name = Release;
298 | };
299 | 18194CBA1B169D94007A3FB0 /* Debug */ = {
300 | isa = XCBuildConfiguration;
301 | buildSettings = {
302 | COMBINE_HIDPI_IMAGES = YES;
303 | DEPLOYMENT_LOCATION = YES;
304 | DSTROOT = "$(HOME)";
305 | INFOPLIST_FILE = HKSnippet/Info.plist;
306 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
307 | MACOSX_DEPLOYMENT_TARGET = 10.10;
308 | PRODUCT_BUNDLE_IDENTIFIER = "com.tiny-stone.$(PRODUCT_NAME:rfc1034identifier)";
309 | PRODUCT_NAME = HKSnippet;
310 | WRAPPER_EXTENSION = xcplugin;
311 | };
312 | name = Debug;
313 | };
314 | 18194CBB1B169D94007A3FB0 /* Release */ = {
315 | isa = XCBuildConfiguration;
316 | buildSettings = {
317 | COMBINE_HIDPI_IMAGES = YES;
318 | DEPLOYMENT_LOCATION = YES;
319 | DSTROOT = "$(HOME)";
320 | INFOPLIST_FILE = HKSnippet/Info.plist;
321 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
322 | MACOSX_DEPLOYMENT_TARGET = 10.10;
323 | PRODUCT_BUNDLE_IDENTIFIER = "com.tiny-stone.$(PRODUCT_NAME:rfc1034identifier)";
324 | PRODUCT_NAME = HKSnippet;
325 | WRAPPER_EXTENSION = xcplugin;
326 | };
327 | name = Release;
328 | };
329 | /* End XCBuildConfiguration section */
330 |
331 | /* Begin XCConfigurationList section */
332 | 18194CA31B169D93007A3FB0 /* Build configuration list for PBXProject "HKSnippet" */ = {
333 | isa = XCConfigurationList;
334 | buildConfigurations = (
335 | 18194CB71B169D94007A3FB0 /* Debug */,
336 | 18194CB81B169D94007A3FB0 /* Release */,
337 | );
338 | defaultConfigurationIsVisible = 0;
339 | defaultConfigurationName = Release;
340 | };
341 | 18194CB91B169D94007A3FB0 /* Build configuration list for PBXNativeTarget "HKSnippet" */ = {
342 | isa = XCConfigurationList;
343 | buildConfigurations = (
344 | 18194CBA1B169D94007A3FB0 /* Debug */,
345 | 18194CBB1B169D94007A3FB0 /* Release */,
346 | );
347 | defaultConfigurationIsVisible = 0;
348 | defaultConfigurationName = Release;
349 | };
350 | /* End XCConfigurationList section */
351 | };
352 | rootObject = 18194CA01B169D93007A3FB0 /* Project object */;
353 | }
354 |
--------------------------------------------------------------------------------
/Setting/HKSnippetSettingController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
111 |
124 |
137 |
150 |
163 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
--------------------------------------------------------------------------------