The R Project SVN R-packages

Rev

Rev 1499 | Rev 5707 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
714 iacus 1
/*
2
 *  R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
3
 *  
4
 *  R.app Copyright notes:
1254 iacus 5
 *                     Copyright (C) 2004-5  The R Foundation
714 iacus 6
 *                     written by Stefano M. Iacus and Simon Urbanek
7
 *
8
 *                  
9
 *  R Copyright notes:
10
 *                     Copyright (C) 1995-1996   Robert Gentleman and Ross Ihaka
11
 *                     Copyright (C) 1998-2001   The R Development Core Team
12
 *                     Copyright (C) 2002-2004   The R Foundation
13
 *
14
 *  This program is free software; you can redistribute it and/or modify
15
 *  it under the terms of the GNU General Public License as published by
16
 *  the Free Software Foundation; either version 2 of the License, or
17
 *  (at your option) any later version.
18
 *
19
 *  This program is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  A copy of the GNU General Public License is available via WWW at
25
 *  http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
26
 *  writing to the Free Software Foundation, Inc., 59 Temple Place,
27
 *  Suite 330, Boston, MA  02111-1307  USA.
28
 */
568 iacus 29
 
30
#import "CodeCompletion.h"
816 urbaneks 31
#import "../REngine/REngine.h"
1499 urbaneks 32
#import "RGUI.h"
568 iacus 33
 
34
@implementation CodeCompletion
35
 
36
+ (NSString*) complete: (NSString*) part {
1499 urbaneks 37
	if (preventReentrance && insideR>0) {
38
		SLog(@"CodeCompletion.complete: returning nil completion to prevent R re-entrance [***]");
39
		return nil;
40
	}
568 iacus 41
    REngine *re = [REngine mainEngine];
1562 urbaneks 42
	if (![re beginProtected]) {
43
		SLog(@"CodeCompletion.complete: returning nil completion because protected REngine entry failed [***]");
44
		return nil;
45
	}
568 iacus 46
    // first get the length of the search path so we can go environment by environment
47
    RSEXP *x = [re evaluateString:@"length(search())"];
48
    int pos=1, maxpos;
1562 urbaneks 49
    if (x==nil || ((maxpos = [x integer])==0)) { [re endProtected]; return nil; }
568 iacus 50
 
51
    // ok, we got the search path length; search in each environment and if something matches, get it, otherwise go to the next one
52
    while (pos<=maxpos) {
53
        // use ls to get the names of the objects in the specific environment
54
        NSString *ls=[NSString stringWithFormat:@"ls(pos=%d, all.names=TRUE, pattern=\"^%@.*\")", pos, part];
55
        RSEXP *x = [re evaluateString:ls];
56
        //NSLog(@"attepmting to find %@ via %@", part, ls);
1562 urbaneks 57
        if (x==nil) {
58
			[re endProtected];
568 iacus 59
            return nil;
1562 urbaneks 60
		}
568 iacus 61
        NSArray *a = [x array];
62
        if (a == nil) {
63
            [x release];
1562 urbaneks 64
			[re endProtected];
568 iacus 65
            return nil;
66
        }
67
 
68
        { // the following code works also if pattern is not specified; with pattern present we could make it even easier, but currently we use it just to narrow the search (e.g. "." could still be matched by something else ...)
69
            int i=0, firstMatch=-1, matches=0;
70
            NSString *common=nil;
71
            while (i<[a count]) {
72
                NSString *sx = (NSString*) [a objectAtIndex:i];
73
                if ([sx hasPrefix: part]) {
74
                    if (matches==0) {
75
                        firstMatch=i;
76
                        common=[[NSString alloc] initWithString: sx];
77
                    } else {
78
                        NSString *cpref=[[NSString alloc] initWithString:[common commonPrefixWithString:sx options:0]];
79
                        [common release];
80
                        common=cpref;
81
                    }
82
                    matches++;
83
                }
84
                i++;
85
            }
86
            if (common!=nil) { // attempt to get class of the object - it will fail if that's just a partial object, but who cares..
87
                x = [re evaluateString:[NSString stringWithFormat:@"try(class(%@),silent=TRUE)",common]];
1562 urbaneks 88
				[re endProtected];
568 iacus 89
                if (x!=nil && [x string]!=nil && [[x string] isEqualToString:@"function"])
90
                    return [[common autorelease] stringByAppendingString:@"("];
91
                else
92
                    return [common autorelease];
93
            }
94
        }
95
        pos++;
96
    }
1562 urbaneks 97
	[re endProtected];
568 iacus 98
    return nil;
99
}
100
 
973 urbaneks 101
+ (NSArray*) completeAll: (NSString*) part cutPrefix: (int) prefix {
1499 urbaneks 102
	if (preventReentrance && insideR>0) {
103
		SLog(@"CodeCompletion.completeAll: returning nil completion to prevent R re-entrance [***]");
104
		return nil;
105
	}
1562 urbaneks 106
 
973 urbaneks 107
    REngine *re = [REngine mainEngine];
1562 urbaneks 108
	if (![re beginProtected]) {
109
		SLog(@"CodeCompletion.completeAll: returning nil completion because protected REngine entry failed [***]");
110
		return nil;
111
	}
112
 
973 urbaneks 113
    // first get the length of the search path so we can go environment by environment
114
    RSEXP *x = [re evaluateString:@"length(search())"];
115
    int pos=1, maxpos, matches=0;
116
	NSMutableArray *ca = nil;
117
	NSString *common=nil;
118
 
1562 urbaneks 119
    if (x==nil || ((maxpos = [x integer])==0)) { [re endProtected]; return nil; }
973 urbaneks 120
 
121
	ca = [[NSMutableArray alloc] initWithCapacity: 8];
122
 
123
    // ok, we got the search path length; search in each environment and if something matches, get it, otherwise go to the next one
124
    while (pos<=maxpos) {
125
        // use ls to get the names of the objects in the specific environment
126
        NSString *ls=[NSString stringWithFormat:@"ls(pos=%d, all.names=TRUE, pattern=\"^%@.*\")", pos, part];
127
        RSEXP *x = [re evaluateString:ls];
128
        //NSLog(@"attepmting to find %@ via %@", part, ls);
1562 urbaneks 129
        if (x==nil) {
130
			[re endProtected];
973 urbaneks 131
            return nil;
1562 urbaneks 132
		}
133
 
973 urbaneks 134
        NSArray *a = [x array];
135
 
136
        if (a == nil) {
137
            [x release];
1562 urbaneks 138
			[re endProtected];
973 urbaneks 139
            return nil;
140
        }
141
 
142
        { // the following code works also if pattern is not specified; with pattern present we could make it even easier, but currently we use it just to narrow the search (e.g. "." could still be matched by something else ...)
143
            int i=0, firstMatch=-1;
144
            while (i<[a count]) {
145
                NSString *sx = (NSString*) [a objectAtIndex:i];
146
                if ([sx hasPrefix: part]) {
147
                    if (matches==0) {
148
                        firstMatch=i;
149
                        common=[[NSString alloc] initWithString: sx];
150
                    } else {
151
                        NSString *cpref=[[NSString alloc] initWithString:[common commonPrefixWithString:sx options:0]];
152
                        [common release];
153
                        common=cpref;
154
                    }
1359 urbaneks 155
					if (prefix<[sx length]) {
156
						[ca addObject: [sx substringFromIndex:prefix]];
157
						matches++;
158
					}
973 urbaneks 159
                }
160
                i++;
161
            }
162
        }
163
        pos++;
164
    }
165
	if (common) { 
166
		if (matches==1) {
167
			// attempt to get class of the object - it will fail if that's just a partial object, but who cares..
168
			x = [re evaluateString:[NSString stringWithFormat:@"try(class(%@),silent=TRUE)",common]];
169
			[ca release];
170
			if (x!=nil && [x string]!=nil && [[x string] isEqualToString:@"function"]) {
1562 urbaneks 171
				[re endProtected];
973 urbaneks 172
				return [NSArray arrayWithObject: [[[common autorelease] stringByAppendingString:@"("] substringFromIndex:prefix]];
173
			} else {
1562 urbaneks 174
				[re endProtected];
973 urbaneks 175
				return [NSArray arrayWithObject: [[common autorelease] substringFromIndex:prefix]];
176
			}
177
		} else {
178
			[common release];
1562 urbaneks 179
			[re endProtected];
973 urbaneks 180
			return ca;
181
		}
182
	}
1562 urbaneks 183
	[re endProtected];
973 urbaneks 184
	[ca release];
185
    return nil;
186
}
187
 
568 iacus 188
@end