1 11 package org.eclipse.ui.internal.texteditor; 12 13 import java.util.ArrayList ; 14 import java.util.Collections ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.regex.Matcher ; 19 import java.util.regex.Pattern ; 20 21 import org.eclipse.jface.text.BadLocationException; 22 import org.eclipse.jface.text.FindReplaceDocumentAdapter; 23 import org.eclipse.jface.text.IDocument; 24 import org.eclipse.jface.text.IRegion; 25 26 39 public final class HippieCompletionEngine { 40 41 44 private static final String COMPLETION_WORD_REGEX= "[\\p{L}[\\p{Mn}[\\p{Pc}[\\p{Nd}[\\p{Nl}[\\p{Sc}]]]]]]+"; 53 private static final Pattern COMPLETION_WORD_PATTERN= Pattern.compile(COMPLETION_WORD_REGEX); 54 55 60 private static final String NON_EMPTY_COMPLETION_BOUNDARY= "[\\s\\p{Z}[\\p{P}&&[\\P{Pc}]][\\p{S}&&[\\P{Sc}]]]+"; 62 67 private static final String COMPLETION_BOUNDARY= "(^|" + NON_EMPTY_COMPLETION_BOUNDARY + ")"; 72 76 private static final boolean CASE_SENSITIVE= true; 77 78 81 public HippieCompletionEngine() { 82 } 83 84 87 94 private String asRegPattern(CharSequence string) { 95 StringBuffer out= new StringBuffer (string.length()); 96 boolean quoting= false; 97 98 for (int i= 0, length= string.length(); i < length; i++) { 99 char ch= string.charAt(i); 100 if (ch == '\\') { 101 if (quoting) { 102 out.append("\\E"); quoting= false; 104 } 105 out.append("\\\\"); continue; 107 } 108 if (!quoting) { 109 out.append("\\Q"); quoting= true; 111 } 112 out.append(ch); 113 } 114 if (quoting) 115 out.append("\\E"); 117 return out.toString(); 118 } 119 120 138 public List getCompletionsForward(IDocument document, CharSequence prefix, 139 int firstPosition, boolean currentWordLast) throws BadLocationException { 140 ArrayList res= new ArrayList (); 141 String currentWordCompletion= null; 143 if (firstPosition == document.getLength()) { 144 return res; 145 } 146 147 FindReplaceDocumentAdapter searcher= new FindReplaceDocumentAdapter(document); 148 149 String searchPattern; 151 152 if (firstPosition > 0) { 157 firstPosition--; 158 searchPattern= NON_EMPTY_COMPLETION_BOUNDARY + asRegPattern(prefix); 160 } else { 161 searchPattern= COMPLETION_BOUNDARY + asRegPattern(prefix); 162 } 163 164 IRegion reg= searcher.find(firstPosition, searchPattern, true, CASE_SENSITIVE, false, true); 165 while (reg != null) { 166 int wordSearchPos= reg.getOffset() + reg.getLength() - prefix.length(); 168 IRegion word= searcher.find(wordSearchPos, COMPLETION_WORD_REGEX, true, true, false, true); 170 if (word.getLength() > prefix.length() ) { String wholeWord= document.get(word.getOffset(), word.getLength()); 172 String completion= wholeWord.substring(prefix.length()); 173 if (currentWordLast && reg.getOffset() == firstPosition) { currentWordCompletion= completion; } else { 176 res.add(completion); 177 } 178 } 179 int nextPos= word.getOffset() + word.getLength(); 180 if (nextPos >= document.getLength() ) { 181 break; 182 } 183 reg= searcher.find(nextPos, searchPattern, true, CASE_SENSITIVE, false, true); 184 } 185 186 if (currentWordCompletion != null) { 188 res.add(currentWordCompletion); 189 } 190 191 return res; 192 } 193 194 207 public List getCompletionsBackwards(IDocument document, CharSequence prefix, int firstPosition) throws BadLocationException { 208 ArrayList res= new ArrayList (); 209 210 if (firstPosition == 0) { 213 return res; 214 } 215 216 FindReplaceDocumentAdapter searcher= new FindReplaceDocumentAdapter(document); 217 218 String searchPattern= COMPLETION_BOUNDARY + asRegPattern(prefix); 220 221 IRegion reg= searcher.find(0, searchPattern, true, CASE_SENSITIVE, false, true); 222 while (reg != null) { 223 int wordSearchPos= reg.getOffset() + reg.getLength() - prefix.length(); 225 IRegion word= searcher.find(wordSearchPos, COMPLETION_WORD_REGEX, true, true, false, true); 227 if (word.getOffset() + word.getLength() > firstPosition) { 228 break; 229 } 230 if (word.getLength() > prefix.length() ) { String found= document.get(word.getOffset(), word.getLength()); 232 res.add(found.substring(prefix.length())); 233 } 234 int nextPos= word.getOffset() + word.getLength(); 235 if (nextPos >= firstPosition ) { break; 237 } 238 reg= searcher.find(nextPos, searchPattern, true, CASE_SENSITIVE, false, true); 239 } 240 Collections.reverse(res); 241 242 return res; 243 } 244 245 254 public String getPrefixString(IDocument doc, int pos) throws BadLocationException { 255 Matcher m= COMPLETION_WORD_PATTERN.matcher(""); int prevNonAlpha= pos; 257 while (prevNonAlpha > 0) { 258 m.reset(doc.get(prevNonAlpha-1, pos - prevNonAlpha + 1)); 259 if (!m.matches()) { 260 break; 261 } 262 prevNonAlpha--; 263 } 264 if (prevNonAlpha != pos) { 265 return doc.get(prevNonAlpha, pos - prevNonAlpha); 266 } 267 return null; 268 } 269 270 277 public List makeUnique(List suggestions) { 278 HashSet seenAlready= new HashSet (); 279 ArrayList uniqueSuggestions= new ArrayList (); 280 281 for (Iterator i= suggestions.iterator(); i.hasNext();) { 282 String suggestion= (String ) i.next(); 283 if (!seenAlready.contains(suggestion)) { 284 seenAlready.add(suggestion); 285 uniqueSuggestions.add(suggestion); 286 } 287 } 288 return uniqueSuggestions; 289 } 290 } 291 | Popular Tags |