Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Classes/RubyConsoleWindowController.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 146 - (show annotations) (download)
Sun Dec 17 04:05:28 2017 UTC (6 years, 5 months ago) by toshinagata1964
File size: 9303 byte(s)
Xcode project is updated so that ppc/i386 universal binary can be built (as before)
1 //
2 // RubyConsoleWindowController.m
3 // Alchemusica
4 //
5 // Created by Toshi Nagata on 09/03/01.
6 // Copyright 2009-2016 Toshi Nagata. All rights reserved.
7 //
8 /*
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation version 2 of the License.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 */
18
19 #import "RubyConsoleWindowController.h"
20 #import "MyAppController.h"
21 #include "MDRubyExtern.h"
22 #include "MDHeaders.h"
23
24 @implementation RubyConsoleWindowController
25
26 #pragma mark ====== Ruby Console ======
27
28 static RubyConsoleWindowController *shared;
29
30 + (RubyConsoleWindowController *)sharedRubyConsoleWindowController
31 {
32 if (shared == nil)
33 shared = [[RubyConsoleWindowController alloc] initWithWindowNibName: @"RubyConsoleWindow"];
34 return shared;
35 }
36
37 - (void)windowDidLoad
38 {
39 NSFont *font;
40 [super windowDidLoad];
41 font = [NSFont userFixedPitchFontOfSize:11.0f];
42 [consoleView setFont:font];
43 [consoleView setEnabledTextCheckingTypes:0]; // Disable "smart=***"
44 }
45
46 - (void)flushMessage
47 {
48 [consoleView display];
49 }
50
51 - (void)setConsoleColor: (int)colorID
52 {
53 NSColor *col;
54 switch (colorID) {
55 case 1: col = [NSColor blueColor]; break;
56 case 2: col = [NSColor greenColor]; break;
57 case 4: col = [NSColor redColor]; break;
58 default: col = nil; break;
59 }
60 [defaultColor release];
61 defaultColor = col;
62 if (col != nil)
63 [col retain];
64 }
65
66 - (int)appendMessage: (NSString *)string withColor: (NSColor *)color
67 {
68 NSRange range;
69 int len;
70 range.location = [[consoleView textStorage] length];
71 range.length = 0;
72 [consoleView replaceCharactersInRange: range withString: string];
73 range.length = len = (int)[string length];
74 if (color == nil)
75 color = defaultColor;
76 [consoleView setTextColor: color range: range];
77 range.location += range.length;
78 range.length = 0;
79 [consoleView scrollRangeToVisible: range];
80 return (int)[string length];
81 }
82
83 - (int)appendMessage: (NSString *)string
84 {
85 return [self appendMessage: string withColor: nil];
86 }
87
88 - (void)showRubyPrompt
89 {
90 NSString *str = [[consoleView textStorage] string];
91 int len = (int)[str length];
92 if (len > 0 && [str characterAtIndex: len - 1] != '\n')
93 [self appendMessage: @"\n% "];
94 else
95 [self appendMessage: @"% "];
96 [self flushMessage];
97 }
98
99 - (void)onEnterPressed: (id)sender
100 {
101 // printf("OnEnterPressed invoked\n");
102
103 // if (::wxGetKeyState(WXK_ALT)) {
104 // textCtrl->WriteText(wxT("\n> "));
105 // return;
106 // }
107 NSString *str = [[consoleView textStorage] string];
108 NSMutableString *script = [NSMutableString string];
109 NSRange range, selectedLineRange;
110 int start, end;
111 int strLen = (int)[str length];
112
113 // Get the block of script to be executed
114 range = [str lineRangeForRange: [[[consoleView selectedRanges] objectAtIndex: 0] rangeValue]];
115 // Look forwards
116 end = (int)(range.location + range.length);
117 while (end < strLen && [str characterAtIndex: end] == '>') {
118 NSRange range1 = [str lineRangeForRange: NSMakeRange(end + 1, 0)];
119 end = (int)(range1.location + range1.length);
120 }
121 // Look backwards
122 start = (int)range.location;
123 while (start > 0 && start < strLen && [str characterAtIndex: start] != '%') {
124 NSRange range2 = [str lineRangeForRange: NSMakeRange(start - 1, 0)];
125 start = (int)range2.location;
126 }
127 if (start < strLen && [str characterAtIndex: start] == '%')
128 start++;
129 if (start < strLen && [str characterAtIndex: start] == ' ')
130 start++;
131
132 // Get script (prompt characters are still in)
133 selectedLineRange = NSMakeRange(start, end - start);
134 script = [NSMutableString stringWithString: [str substringWithRange: selectedLineRange]];
135 // Remove prompt characters
136 [script replaceOccurrencesOfString: @"\n>" withString: @"\n" options: 0 range: NSMakeRange(0, [script length])];
137 [script replaceOccurrencesOfString: @"\n%" withString: @"\n" options: 0 range: NSMakeRange(0, [script length])];
138
139 if ([script length] == 0) {
140 // Input is empty
141 [self showRubyPrompt];
142 return;
143 }
144
145 // Append newline to avoid choking Ruby lexical analyzer
146 if ([script characterAtIndex: [script length] - 1] != '\n')
147 [script appendString: @"\n"];
148
149 if (end < strLen) {
150 // Enter is pressed in the block not at the end
151 // -> Insert the text at the end
152 [self showRubyPrompt];
153 [self appendMessage: script withColor: [NSColor blueColor]];
154 } else {
155 [consoleView setTextColor: [NSColor blueColor] range: selectedLineRange];
156 [self appendMessage: @"\n"];
157 }
158
159 // Invoke ruby interpreter
160 int status;
161 char *cscript = strdup([script UTF8String]);
162 RubyValue val = Ruby_evalRubyScriptOnDocument(cscript, [(MyAppController *)[NSApp delegate] documentAtIndex: 0], &status);
163 cscript[strlen(cscript) - 1] = 0; /* Remove the last newline */
164 AssignArray(&commandHistory, &nCommandHistory, sizeof(char *), nCommandHistory, &cscript);
165 if (nCommandHistory >= MAX_HISTORY_LINES)
166 DeleteArray(&commandHistory, &nCommandHistory, sizeof(char *), 0, 1, NULL);
167 defaultColor = [[NSColor redColor] retain];
168 if (status != 0)
169 Ruby_showError(status);
170 else {
171 char *valueString;
172 [self appendMessage: @"-->"];
173 status = Ruby_showValue(val, &valueString);
174 if (status != 0) {
175 Ruby_showError(status);
176 } else {
177 AssignArray(&valueHistory, &nValueHistory, sizeof(char *), nValueHistory, &valueString);
178 if (nValueHistory >= MAX_HISTORY_LINES)
179 DeleteArray(&valueHistory, &nValueHistory, sizeof(char *), 0, 1, NULL);
180 }
181 }
182 [defaultColor release];
183 defaultColor = nil;
184 [self showRubyPrompt];
185 [consoleView setSelectedRange: NSMakeRange([[consoleView string] length], 0)];
186 commandHistoryIndex = valueHistoryIndex = -1;
187 }
188
189 - (BOOL)showHistory:(int)updown
190 {
191 BOOL up = (updown < 0);
192 BOOL option = ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) != 0;
193 NSTextStorage *storage = [consoleView textStorage];
194 char *p;
195 if (commandHistoryIndex == -1 && valueHistoryIndex == -1) {
196 if (!up)
197 return NO;
198 historyPos = (int)[storage length];
199 }
200 if (option) {
201 if (up) {
202 if (valueHistoryIndex == -1) {
203 if (nValueHistory == 0)
204 return NO;
205 valueHistoryIndex = nValueHistory;
206 }
207 if (valueHistoryIndex <= 0)
208 return YES; /* Key is processed but do nothing */
209 valueHistoryIndex--;
210 p = valueHistory[valueHistoryIndex];
211 } else {
212 if (valueHistoryIndex == -1)
213 return YES; /* Do nothing */
214 if (valueHistoryIndex == nValueHistory - 1) {
215 valueHistoryIndex = -1;
216 p = "";
217 } else {
218 valueHistoryIndex++;
219 p = valueHistory[valueHistoryIndex];
220 }
221 }
222 } else {
223 if (up) {
224 if (commandHistoryIndex == -1) {
225 if (nCommandHistory == 0)
226 return NO;
227 commandHistoryIndex = nCommandHistory;
228 }
229 if (commandHistoryIndex <= 0)
230 return YES; /* Do nothing */
231 commandHistoryIndex--;
232 p = commandHistory[commandHistoryIndex];
233 } else {
234 if (commandHistoryIndex == -1)
235 return YES; /* Do nothing */
236 if (commandHistoryIndex == nCommandHistory - 1) {
237 commandHistoryIndex = -1;
238 p = "";
239 } else {
240 commandHistoryIndex++;
241 p = commandHistory[commandHistoryIndex];
242 }
243 }
244 }
245 if (p == NULL)
246 p = "";
247 [storage deleteCharactersInRange:NSMakeRange(historyPos, [storage length] - historyPos)];
248 while (isspace(*p))
249 p++;
250 [self setConsoleColor:(option ? 4 : 1)];
251 [self appendMessage:[NSString stringWithUTF8String:p]];
252 [self setConsoleColor:0];
253 return YES;
254 }
255
256 - (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)aSelector
257 {
258 if (aSelector == @selector(insertNewline:)) {
259 [self onEnterPressed: self];
260 return YES;
261 } else if (aSelector == @selector(moveUp:) || aSelector == @selector(moveDown:)) {
262 NSArray *a = [aTextView selectedRanges];
263 NSRange r;
264 if ([a count] == 1 && (r = [[a objectAtIndex:0] rangeValue]).length == 0 && r.location == [[aTextView textStorage] length])
265 return [self showHistory:(aSelector == @selector(moveDown:) ? 1 : -1)];
266 else return NO;
267 }
268 return NO;
269 }
270
271 @end
272
273 #pragma mark ====== Plain-C Interface ======
274
275 int
276 MyAppCallback_showScriptMessage(const char *fmt, ...)
277 {
278 RubyConsoleWindowController *cont = [RubyConsoleWindowController sharedRubyConsoleWindowController];
279 if (fmt != NULL) {
280 char *p;
281 va_list ap;
282 int retval;
283 va_start(ap, fmt);
284 if (strchr(fmt, '%') == NULL) {
285 /* No format characters */
286 return [cont appendMessage: [NSString stringWithUTF8String: fmt]];
287 } else if (strcmp(fmt, "%s") == 0) {
288 /* Direct output of one string */
289 p = va_arg(ap, char *);
290 return [cont appendMessage: [NSString stringWithUTF8String: p]];
291 }
292 vasprintf(&p, fmt, ap);
293 if (p != NULL) {
294 retval = [cont appendMessage: [NSString stringWithUTF8String: p]];
295 free(p);
296 return retval;
297 } else return 0;
298 } else {
299 [cont flushMessage];
300 return 0;
301 }
302 }
303
304 void
305 MyAppCallback_setConsoleColor(int color)
306 {
307 RubyConsoleWindowController *cont = [RubyConsoleWindowController sharedRubyConsoleWindowController];
308 [cont setConsoleColor: color];
309 }
310
311 void
312 MyAppCallback_showRubyPrompt(void)
313 {
314 RubyConsoleWindowController *cont = [RubyConsoleWindowController sharedRubyConsoleWindowController];
315 [cont setConsoleColor: 0];
316 [cont showRubyPrompt];
317 }
318

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26