The R Project SVN R-packages

Rev

Rev 1562 | Rev 5707 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1562 Rev 5705
Line 27... Line 27...
27
 *  Suite 330, Boston, MA  02111-1307  USA.
27
 *  Suite 330, Boston, MA  02111-1307  USA.
28
 */
28
 */
29
 
29
 
30
#import "CodeCompletion.h"
30
#import "CodeCompletion.h"
31
#import "../REngine/REngine.h"
31
#import "../REngine/REngine.h"
-
 
32
#import "../RegexKitLite.h"
-
 
33
#import "FileCompletion.h"
32
#import "RGUI.h"
34
#import "RGUI.h"
-
 
35
#import "../RController.h"
-
 
36
 
33
 
37
 
34
@implementation CodeCompletion
38
@implementation CodeCompletion
35
 
39
 
36
+ (NSString*) complete: (NSString*) part {
40
+ (NSString*) complete: (NSString*) part {
37
	if (preventReentrance && insideR>0) {
41
	if (preventReentrance && insideR>0) {
Line 183... Line 187...
183
	[re endProtected];
187
	[re endProtected];
184
	[ca release];
188
	[ca release];
185
    return nil;
189
    return nil;
186
}
190
}
187
 
191
 
-
 
192
+ (NSArray*) retrieveSuggestionsForScopeRange:(NSRange)scopeRange inTextView:(NSTextView*)textView
-
 
193
{
-
 
194
 
-
 
195
	if (preventReentrance && insideR>0) {
-
 
196
		SLog(@"CodeCompletion.retrieveSuggestionForScope: returning nil completion to prevent R re-entrance [***]");
-
 
197
		return nil;
-
 
198
	}
-
 
199
 
-
 
200
	REngine *re = [REngine mainEngine];
-
 
201
	if (![re beginProtected]) {
-
 
202
		SLog(@"CodeCompletion.retrieveSuggestionForScope: returning nil completion because protected REngine entry failed [***]");
-
 
203
		return nil;
-
 
204
	}
-
 
205
 
-
 
206
	NSString *linebuffer = [[[textView textStorage] string] substringWithRange:scopeRange];
-
 
207
 
-
 
208
	SLog(@" - passed string for completion:\n%@", [linebuffer description]);
-
 
209
	if(!linebuffer || ![linebuffer length]) {
-
 
210
		[re endProtected];
-
 
211
		return nil;
-
 
212
	}
-
 
213
 
-
 
214
	// convert scope string to single line
-
 
215
	linebuffer = [linebuffer stringByReplacingOccurrencesOfRegex:@"[\n\r\t]+" withString:@" "];
-
 
216
 
-
 
217
	// first we need to find out whether we're in a text part or code part
-
 
218
	unichar c;
-
 
219
	int tl = [linebuffer length], tp=0, quotes=0, dquotes=0, lastQuote=-1;
-
 
220
	while (tp < tl) {
-
 
221
		c = CFStringGetCharacterAtIndex((CFStringRef)linebuffer, tp);
-
 
222
		if (c=='\\') 
-
 
223
			tp++; // skip the next char after a backslash (we don't have to worry about \023 and friends)
-
 
224
		else {
-
 
225
			if (dquotes==0 && c=='\'') {
-
 
226
				quotes^=1;
-
 
227
				if (quotes) lastQuote=tp;
-
 
228
			}
-
 
229
			if (quotes==0 && c=='"') {
-
 
230
				dquotes^=1;
-
 
231
				if (dquotes) lastQuote=tp;
-
 
232
			}
-
 
233
		}
-
 
234
		tp++;
-
 
235
	}
-
 
236
 
-
 
237
	// if we're inside any quotes, bail via file completion
-
 
238
	if (quotes+dquotes>0) {
-
 
239
		SLog(@" - cursor is inside quotes - call file completion");
-
 
240
		[re endProtected];
-
 
241
		return [FileCompletion completeAll:[linebuffer substringFromIndex:lastQuote+1] cutPrefix:0];
-
 
242
	}
-
 
243
 
-
 
244
	// use internal rcompgen to retrieve completion suggestions;
-
 
245
	// can be modified by the user via rc.setting s() and rc.options() resp.
-
 
246
 
-
 
247
	// escape ' since we pass it via @" '...' "
-
 
248
	linebuffer = [linebuffer stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
-
 
249
	SLog(@" - rcompgen completion will be invoked with:\n%@", linebuffer);
-
 
250
	RSEXP *xx = [re evaluateString:[NSString stringWithFormat:@"rcompgen.completion('%@')", linebuffer]];
-
 
251
	[re endProtected];
-
 
252
	if(xx) {
-
 
253
 
-
 
254
		NSArray *ca = [xx array];
-
 
255
 
-
 
256
		// if only one suggestion was found set function hint in status bar
-
 
257
		if (ca && [ca count]==1) {
-
 
258
 
-
 
259
			NSString *foundItem = [ca objectAtIndex:0];
-
 
260
 
-
 
261
			// ignore all spaces, equal signs, and opened paranthesis at the end
-
 
262
			BOOL showIt = YES;
-
 
263
			int i = [foundItem length]-1;
-
 
264
			unichar c;
-
 
265
			while(i>0) {
-
 
266
				c = CFStringGetCharacterAtIndex((CFStringRef)foundItem, i);
-
 
267
				if(c == ' ' || c == '(') {
-
 
268
					i--;
-
 
269
				}
-
 
270
				else if (c == '=') {
-
 
271
					// if suggestion ends with a = do not show the hint, since
-
 
272
					// it's a parameter
-
 
273
					showIt = NO;
-
 
274
					break;
-
 
275
				}
-
 
276
				else
-
 
277
					break;
-
 
278
			}
-
 
279
			i++;
-
 
280
			foundItem = [foundItem substringToIndex:i];
-
 
281
			SLog(@" - show function hint '%@' with display %d", foundItem, showIt);
-
 
282
			if(showIt && [[(NSTextView*)[[NSApp keyWindow] firstResponder] delegate] respondsToSelector:@selector(hintForFunction:)])
-
 
283
				// (RController*) is only a dummy to avoid compiler warnings
-
 
284
				[(RController*)[(NSTextView*)[[NSApp keyWindow] firstResponder] delegate] hintForFunction:foundItem];
-
 
285
		}
-
 
286
 
-
 
287
		SLog(@" - found %d suggestions", [ca count]);
-
 
288
		[xx release];
-
 
289
		return (ca && [ca count]) ? ca : nil;
-
 
290
 
-
 
291
	}
-
 
292
 
-
 
293
	return nil;
-
 
294
 
-
 
295
}
-
 
296
 
188
@end
297
@end