-
Notifications
You must be signed in to change notification settings - Fork 351
Expand file tree
/
Copy pathESJsonFormat.m
More file actions
executable file
·227 lines (195 loc) · 10.4 KB
/
ESJsonFormat.m
File metadata and controls
executable file
·227 lines (195 loc) · 10.4 KB
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//
// ESJsonFormat.m
// ESJsonFormat
//
// Created by 尹桥印 on 15/6/28.
// Copyright (c) 2015年 EnjoySR. All rights reserved.
//
#import "ESJsonFormat.h"
#import "ESJsonFormatManager.h"
#import "ESFormatInfo.h"
#import "ESInputJsonController.h"
#import "ESSettingController.h"
#import "ESPbxprojInfo.h"
#import "ESJsonFormatSetting.h"
#import "ESClassInfo.h"
@interface ESJsonFormat()<ESInputJsonControllerDelegate>
@property (nonatomic, strong) ESInputJsonController *inputCtrl;
@property (nonatomic, strong) ESSettingController *settingCtrl;
@property (nonatomic, strong) id eventMonitor;
@property (nonatomic, strong, readwrite) NSBundle *bundle;
@property (nonatomic, copy) NSString *currentFilePath;
@property (nonatomic, copy) NSString *currentProjectPath;
@property (nonatomic) NSTextView *currentTextView;
@property (nonatomic, assign) BOOL notiTag;
@end
@implementation ESJsonFormat
+ (instancetype)sharedPlugin{
return sharedPlugin;
}
+ (instancetype)instance{
return instance;
}
- (id)initWithBundle:(NSBundle *)plugin
{
if (self = [super init]) {
// reference to plugin's bundle, for resource access
self.bundle = plugin;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didApplicationFinishLaunchingNotification:)
name:NSApplicationDidFinishLaunchingNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(outputResult:) name:ESFormatResultNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationLog:) name:NSTextViewDidChangeSelectionNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationLog:) name:@"IDEEditorDocumentDidChangeNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationLog:) name:@"PBXProjectDidOpenNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationLog:) name:@"SourceEditorSelectedSourceRangeChangedNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationLog:) name:@"IDEWorkspaceDocumentWillWriteStateDataNotification" object:nil];
}
instance = self;
return self;
}
- (void)notificationLog:(NSNotification *)notify
{
if (!self.notiTag) return;
if ([notify.name isEqualToString:NSTextViewDidChangeSelectionNotification]) {
if ([notify.object isKindOfClass:NSClassFromString(@"DVTSourceTextView")]) {
NSTextView *text = (NSTextView *)notify.object;
self.currentTextView = text;
}
}else if ([notify.name isEqualToString:@"IDEEditorDocumentDidChangeNotification"]){
//Track the current open paths
NSObject *array = notify.userInfo[@"IDEEditorDocumentChangeLocationsKey"];
NSURL *url = [[array valueForKey:@"documentURL"] firstObject];
if (![url isKindOfClass:[NSNull class]]) {
NSString *path = [url absoluteString];
self.currentFilePath = path;
if ([self.currentFilePath hasSuffix:@"swift"]) {
self.swift = YES;
}else{
self.swift = NO;
}
}
}else if ([notify.name isEqualToString:@"PBXProjectDidOpenNotification"]){
self.currentProjectPath = [notify.object valueForKey:@"path"];
[[ESPbxprojInfo shareInstance] setParamsWithPath:[self.currentProjectPath stringByAppendingPathComponent:@"project.pbxproj"]];
}else if ([notify.name isEqualToString:@"SourceEditorSelectedSourceRangeChangedNotification"]) {
// 适配 Xcode 9,在Xcode 9 中代码编辑区域的 View 类型如下,继承于 NSView,但使用方式与 NSTextView 类似
if ([notify.object isKindOfClass:NSClassFromString(@"IDEPegasusSourceEditor.SourceCodeEditorView")]) {
self.currentTextView = notify.object;
}
}else if ([notify.name isEqualToString:@"IDEWorkspaceDocumentWillWriteStateDataNotification"]) {
NSArray *recentEditorDocumentURLs = [notify.object valueForKey:@"_recentEditorDocumentURLs"];
NSString *path = [recentEditorDocumentURLs.firstObject absoluteString];
if ([path hasPrefix:@"file"]) {
self.currentFilePath = path;
}
}
}
-(void)outputResult:(NSNotification*)noti{
ESClassInfo *classInfo = noti.object;
if ([ESJsonFormatSetting defaultSetting].outputToFiles) {
//选择保存路径
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setTitle:@"ESJsonFormat"];
[panel setCanChooseDirectories:YES];
[panel setCanCreateDirectories:YES];
[panel setCanChooseFiles:NO];
if ([panel runModal] == NSModalResponseOK) {
NSString *folderPath = [[[panel URLs] objectAtIndex:0] relativePath];
[classInfo createFileWithFolderPath:folderPath];
[[NSWorkspace sharedWorkspace] openFile:folderPath];
}
}else{
if (!self.currentTextView) return;
if (!self.isSwift) {
//先添加主类的属性
[self.currentTextView insertText:classInfo.propertyContent];
//再添加把其他类的的字符串拼接到最后面
[self.currentTextView insertText:classInfo.classInsertTextViewContentForH replacementRange:NSMakeRange(self.currentTextView.string.length, 0)];
//@class
NSString *atClassContent = classInfo.atClassContent;
if (atClassContent.length>0) {
NSRange atInsertRange = [self.currentTextView.string rangeOfString:@"\n@interface"];
if (atInsertRange.location != NSNotFound) {
[self.currentTextView insertText:[NSString stringWithFormat:@"\n%@",atClassContent] replacementRange:NSMakeRange(atInsertRange.location, 0)];
}
}
//再添加.m文件的内容
NSString *urlStr = [NSString stringWithFormat:@"%@m",[self.currentFilePath substringWithRange:NSMakeRange(0, self.currentFilePath.length-1)]] ;
NSURL *writeUrl = [NSURL URLWithString:urlStr];
//The original content
NSString *originalContent = [NSString stringWithContentsOfURL:writeUrl encoding:NSUTF8StringEncoding error:nil];
//大写ID时生成对应的映射方法
if (ESJsonFormatSetting.defaultSetting.uppercaseKeyWordForId &&
(classInfo.classDic[@"id"] || classInfo.classDic[@"ID"]))
{
NSString *methodStr = @"\n+ (NSDictionary *)replacedKeyFromPropertyName\n{\n return @{@\"ID\" : @\"id\"};\n}\n";
NSRange lastEndRange = [originalContent rangeOfString:@"@end"];
if (lastEndRange.location != NSNotFound) {
originalContent = [originalContent stringByReplacingCharactersInRange:NSMakeRange(lastEndRange.location, 0) withString:methodStr];
}
}
//输出RootClass的impOjbClassInArray方法
if ([ESJsonFormatSetting defaultSetting].impOjbClassInArray) {
NSString *methodStr = [ESJsonFormatManager methodContentOfObjectClassInArrayWithClassInfo:classInfo];
if (methodStr.length) {
NSRange lastEndRange = [originalContent rangeOfString:@"@end"];
if (lastEndRange.location != NSNotFound) {
originalContent = [originalContent stringByReplacingCharactersInRange:NSMakeRange(lastEndRange.location, 0) withString:methodStr];
}
}
}
originalContent = [originalContent stringByReplacingCharactersInRange:NSMakeRange(originalContent.length, 0) withString:classInfo.classInsertTextViewContentForM];
[originalContent writeToURL:writeUrl atomically:YES encoding:NSUTF8StringEncoding error:nil];
}else{
//Swift
[self.currentTextView insertText:classInfo.propertyContent];
//再添加把其他类的的字符串拼接到最后面
[self.currentTextView insertText:classInfo.classInsertTextViewContentForH replacementRange:NSMakeRange(self.currentTextView.string.length, 0)];
}
}
}
- (void)didApplicationFinishLaunchingNotification:(NSNotification*)noti{
self.notiTag = YES;
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:nil];
NSMenuItem *menuItem = [[NSApp mainMenu] itemWithTitle:@"Window"];
if (menuItem) {
NSMenu *menu = [[NSMenu alloc] init];
//Input JSON window
NSMenuItem *inputJsonWindow = [[NSMenuItem alloc] initWithTitle:@"Input JSON window" action:@selector(showInputJsonWindow:) keyEquivalent:@"J"];
[inputJsonWindow setKeyEquivalentModifierMask:NSAlphaShiftKeyMask | NSControlKeyMask];
inputJsonWindow.target = self;
[menu addItem:inputJsonWindow];
//Setting
NSMenuItem *settingWindow = [[NSMenuItem alloc] initWithTitle:@"Setting" action:@selector(showSettingWindow:) keyEquivalent:@""];
settingWindow.target = self;
[menu addItem:settingWindow];
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"ESJsonFormat" action:nil keyEquivalent:@""];
item.submenu = menu;
[[menuItem submenu] addItem:item];
}
}
- (void)showInputJsonWindow:(NSMenuItem *)item{
if (!(self.currentTextView && self.currentFilePath)) {
NSError *error = [NSError errorWithDomain:@"Current state is not edit!" code:0 userInfo:nil];
NSAlert *alert = [NSAlert alertWithError:error];
[alert runModal];
return;
}
self.notiTag = NO;
self.inputCtrl = [[ESInputJsonController alloc] initWithWindowNibName:@"ESInputJsonController"];
self.inputCtrl.delegate = self;
[self.inputCtrl showWindow:self.inputCtrl];
}
- (void)showSettingWindow:(NSMenuItem *)item{
self.settingCtrl = [[ESSettingController alloc] initWithWindowNibName:@"ESSettingController"];
[self.settingCtrl showWindow:self.settingCtrl];
}
-(void)windowWillClose{
self.notiTag = YES;
}
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end