/
JSTAppDelegate.m
275 lines (186 loc) · 7.65 KB
/
JSTAppDelegate.m
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
//
// JSTAppDelegate.m
// jstalk
//
// Created by August Mueller on 1/14/09.
// Copyright 2009 Flying Meat Inc. All rights reserved.
//
#import "JSTAppDelegate.h"
#import "JSTalk.h"
@interface JSTAppDelegate (PrivateStuff)
- (void)restoreWorkspace;
- (void)saveWorkspace;
- (void)loadExternalEditorPrefs;
- (void)updatePrefsFontField;
@end
void JSTUncaughtExceptionHandler(NSException *exception) {
NSLog(@"Uncaught exception: %@", exception);
}
@implementation JSTAppDelegate
+ (void)initialize {
NSMutableDictionary *defaultValues = [NSMutableDictionary dictionary];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaultValues setObject:[NSNumber numberWithBool:YES] forKey:@"rememberWorkspace"];
[defaultValues setObject:[NSNumber numberWithBool:YES] forKey:@"clearConsoleOnRun"];
[defaultValues setObject:[NSNumber numberWithBool:YES] forKey:@"codeCompletionEnabled"];
[defaultValues setObject:@"com.apple.xcode" forKey:@"externalEditor"];
[defaults registerDefaults: defaultValues];
[[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:defaultValues];
}
- (void)awakeFromNib {
if ([JSTPrefs boolForKey:@"rememberWorkspace"]) {
[self restoreWorkspace];
}
[JSTalk setShouldLoadJSTPlugins:YES];
[JSTalk listen];
NSSetUncaughtExceptionHandler(JSTUncaughtExceptionHandler);
// register this object to handle the services stuff.
[NSApp setServicesProvider:self];
// have all the services menus get updated.
//NSUpdateDynamicServices();
[JSTalk loadPlugins]; // some guys will setup custom UI in the app.
}
- (IBAction)showPrefs:(id)sender {
[self loadExternalEditorPrefs];
[self updatePrefsFontField];
if (![prefsWindow isVisible]) {
[prefsWindow center];
}
[prefsWindow makeKeyAndOrderFront:self];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
[self saveWorkspace];
}
- (void)restoreWorkspace {
NSArray *ar = [[NSUserDefaults standardUserDefaults] objectForKey:@"workspaceOpenDocuments"];
for (NSString *path in ar) {
if ([path hasSuffix:@".jstplugin"]) {
debug(@"Skipping %@", path);
continue;
}
[[NSDocumentController sharedDocumentController] openDocumentWithContentsOfURL:[NSURL fileURLWithPath:path] display:YES error:nil];
}
}
- (void)saveWorkspace {
NSMutableArray *openDocs = [NSMutableArray array];
for (NSDocument *doc in [[NSDocumentController sharedDocumentController] documents]) {
if ([doc fileURL]) {
// saving the file alias would be better.
[openDocs addObject:[[doc fileURL] path]];
}
}
[[NSUserDefaults standardUserDefaults] setObject:openDocs forKey:@"workspaceOpenDocuments"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)loadExternalEditorPrefs {
NSString *editorId = [[NSUserDefaults standardUserDefaults] objectForKey:@"externalEditor"];
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSString *appPath = [ws absolutePathForAppBundleWithIdentifier:editorId];
NSString *appName = nil;
if (appPath) {
NSBundle *appBundle = [NSBundle bundleWithPath:appPath];
NSString *bundleName = [appBundle objectForInfoDictionaryKey:@"CFBundleName"];
if (bundleName) {
appName = bundleName;
}
}
if (!appName) {
appName = @"Unknown";
}
[externalEditorField setStringValue:appName];
}
- (void)openPanelDidEndForExternalEditor:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
if (returnCode) {
NSString *path = [[sheet URL] path];
NSBundle *appBundle = [NSBundle bundleWithPath:path];
NSString *bundleId = [appBundle bundleIdentifier];
if (!bundleId) {
NSBeep();
NSLog(@"Could not load the bundle info for %@", bundleId);
return;
}
[[NSUserDefaults standardUserDefaults] setObject:bundleId forKey:@"externalEditor"];
[self loadExternalEditorPrefs];
}
}
- (void)chooseExternalEditor:(id)sender {
NSOpenPanel *p = [NSOpenPanel openPanel];
[p setCanChooseFiles:YES];
[p setCanChooseDirectories:NO];
[p setAllowsMultipleSelection:NO];
[p beginSheetForDirectory:@"/Applications"
file:nil
types:[NSArray arrayWithObjects:@"app", @"APPL", nil]
modalForWindow:prefsWindow
modalDelegate:self
didEndSelector:@selector(openPanelDidEndForExternalEditor:returnCode:contextInfo:)
contextInfo:nil];
}
- (void)prefsChoosefont:(id)sender {
[[NSFontManager sharedFontManager] setTarget:self];
[[NSFontManager sharedFontManager] orderFrontFontPanel:self];
}
- (void)changeFont:(id)sender {
NSFont *f = [[sender fontPanel:NO] panelConvertFont:[self defaultEditorFont]];
[self setDefaultEditorFont:f];
[self updatePrefsFontField];
[[NSNotificationCenter defaultCenter] postNotificationName:@"JSTFontChangeNotification" object:self];
}
- (void)updatePrefsFontField {
NSFont *f = [self defaultEditorFont];
[prefsFontField setStringValue:[NSString stringWithFormat:@"%@ %dfp", [f fontName],(int)[f pointSize]]];
}
- (void)setDefaultEditorFont:(NSFont*)f {
NSData *fontAsData = [NSArchiver archivedDataWithRootObject:f];
[[NSUserDefaults standardUserDefaults] setObject:fontAsData forKey: @"defaultFont"];
}
- (NSFont*)defaultEditorFont {
NSFont *defaultFont = nil;
NSData *d = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultFont"];
if (d) {
defaultFont = [NSUnarchiver unarchiveObjectWithData:d];
}
if (!defaultFont) {
defaultFont = [NSFont fontWithName:@"Monaco" size:10];
}
if (!defaultFont) {
defaultFont = [NSFont systemFontOfSize:12];
}
return defaultFont;
}
- (void)JSTalk:(JSTalk*)jstalk hadError:(NSString*)error onLineNumber:(NSInteger)lineNumber atSourceURL:(id)url {
_serviceError = [error retain];
}
- (void)runAsJSTalkScript:(NSPasteboard *)pb userData:(NSDictionary *)userData error:(NSString **)error {
_serviceError = nil;
// Test for strings on the pasteboard.
NSArray *classes = [NSArray arrayWithObject:[NSString class]];
NSDictionary *options = [NSDictionary dictionary];
if (![pb canReadObjectForClasses:classes options:options]) {
*error = NSLocalizedString(@"Error: couldn't read the text.", @"pboard couldn't give string.");
return;
}
NSString *result = nil;
NSString *script = [pb stringForType:NSPasteboardTypeString];
@try {
JSTalk *jstalk = [[JSTalk alloc] init];
[jstalk setErrorController:self];
[[[NSThread currentThread] threadDictionary] setObject:jstalk forKey:@"org.jstalk.currentJSTalkContext"];
result = [[jstalk executeString:script] description];
[[[NSThread currentThread] threadDictionary] removeObjectForKey:@"org.jstalk.currentJSTalkContext"];
[jstalk release];
}
@catch (NSException *e) {
*error = [e reason];
return;
}
if (_serviceError) {
result = _serviceError;
}
[pb clearContents];
if (result) {
[pb writeObjects:[NSArray arrayWithObject:result]];
}
[_serviceError autorelease];
}
@end