1 11 12 package org.eclipse.jface.text; 13 14 import java.util.regex.Matcher ; 15 import java.util.regex.Pattern ; 16 import java.util.regex.PatternSyntaxException ; 17 18 import org.eclipse.core.runtime.Assert; 19 20 21 30 public class FindReplaceDocumentAdapter implements CharSequence { 31 32 35 private static class FindReplaceOperationCode { 36 } 37 38 private static final FindReplaceOperationCode FIND_FIRST= new FindReplaceOperationCode(); 40 private static final FindReplaceOperationCode FIND_NEXT= new FindReplaceOperationCode(); 41 private static final FindReplaceOperationCode REPLACE= new FindReplaceOperationCode(); 42 private static final FindReplaceOperationCode REPLACE_FIND_NEXT= new FindReplaceOperationCode(); 43 44 47 private IDocument fDocument; 48 49 52 private FindReplaceOperationCode fFindReplaceState= null; 53 54 57 private Matcher fFindReplaceMatcher; 58 59 62 private int fFindReplaceMatchOffset; 63 64 69 public FindReplaceDocumentAdapter(IDocument document) { 70 Assert.isNotNull(document); 71 fDocument= document; 72 } 73 74 89 public IRegion find(int startOffset, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord, boolean regExSearch) throws BadLocationException { 90 Assert.isTrue(!(regExSearch && wholeWord)); 91 92 if (startOffset == -1 && forwardSearch) 94 startOffset= 0; 95 if (startOffset == -1 && !forwardSearch) 96 startOffset= length() - 1; 97 98 return findReplace(FIND_FIRST, startOffset, findString, null, forwardSearch, caseSensitive, wholeWord, regExSearch); 99 } 100 101 124 private IRegion findReplace(final FindReplaceOperationCode operationCode, int startOffset, String findString, String replaceText, boolean forwardSearch, boolean caseSensitive, boolean wholeWord, boolean regExSearch) throws BadLocationException { 125 126 Assert.isTrue(!(regExSearch && wholeWord)); 128 129 if ((operationCode == REPLACE || operationCode == REPLACE_FIND_NEXT) && (fFindReplaceState != FIND_FIRST && fFindReplaceState != FIND_NEXT)) 131 throw new IllegalStateException ("illegal findReplace state: cannot replace without preceding find"); 133 if (operationCode == FIND_FIRST) { 134 136 if (findString == null || findString.length() == 0) 137 return null; 138 139 if (startOffset < 0 || startOffset >= length()) 141 throw new BadLocationException(); 142 143 int patternFlags= 0; 144 145 if (regExSearch) 146 patternFlags |= Pattern.MULTILINE; 147 148 if (!caseSensitive) 149 patternFlags |= Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; 150 151 if (wholeWord) 152 findString= "\\b" + findString + "\\b"; 154 if (!regExSearch && !wholeWord) 155 findString= asRegPattern(findString); 156 157 fFindReplaceMatchOffset= startOffset; 158 if (fFindReplaceMatcher != null && fFindReplaceMatcher.pattern().pattern().equals(findString) && fFindReplaceMatcher.pattern().flags() == patternFlags) { 159 163 } else { 165 Pattern pattern= Pattern.compile(findString, patternFlags); 166 fFindReplaceMatcher= pattern.matcher(this); 167 } 168 } 169 170 fFindReplaceState= operationCode; 172 173 if (operationCode == REPLACE || operationCode == REPLACE_FIND_NEXT) { 174 if (regExSearch) { 175 Pattern pattern= fFindReplaceMatcher.pattern(); 176 Matcher replaceTextMatcher= pattern.matcher(fFindReplaceMatcher.group()); 177 try { 178 replaceText= replaceTextMatcher.replaceFirst(replaceText); 179 } catch (IndexOutOfBoundsException ex) { 180 throw new PatternSyntaxException (ex.getLocalizedMessage(), replaceText, -1); 181 } 182 } 183 184 int offset= fFindReplaceMatcher.start(); 185 fDocument.replace(offset, fFindReplaceMatcher.group().length(), replaceText); 186 187 if (operationCode == REPLACE) { 188 return new Region(offset, replaceText.length()); 189 } 190 } 191 192 if (operationCode != REPLACE) { 193 if (forwardSearch) { 194 195 boolean found= false; 196 if (operationCode == FIND_FIRST) 197 found= fFindReplaceMatcher.find(startOffset); 198 else 199 found= fFindReplaceMatcher.find(); 200 201 if (operationCode == REPLACE_FIND_NEXT) 202 fFindReplaceState= FIND_NEXT; 203 204 if (found && fFindReplaceMatcher.group().length() > 0) 205 return new Region(fFindReplaceMatcher.start(), fFindReplaceMatcher.group().length()); 206 return null; 207 } 208 209 boolean found= fFindReplaceMatcher.find(0); 211 int index= -1; 212 int length= -1; 213 while (found && fFindReplaceMatcher.start() + fFindReplaceMatcher.group().length() <= fFindReplaceMatchOffset + 1) { 214 index= fFindReplaceMatcher.start(); 215 length= fFindReplaceMatcher.group().length(); 216 found= fFindReplaceMatcher.find(index + 1); 217 } 218 fFindReplaceMatchOffset= index; 219 if (index > -1) { 220 fFindReplaceMatcher.find(index); 222 return new Region(index, length); 223 } 224 return null; 225 } 226 227 return null; 228 } 229 230 237 private String asRegPattern(String string) { 238 StringBuffer out= new StringBuffer (string.length()); 239 boolean quoting= false; 240 241 for (int i= 0, length= string.length(); i < length; i++) { 242 char ch= string.charAt(i); 243 if (ch == '\\') { 244 if (quoting) { 245 out.append("\\E"); quoting= false; 247 } 248 out.append("\\\\"); continue; 250 } 251 if (!quoting) { 252 out.append("\\Q"); quoting= true; 254 } 255 out.append(ch); 256 } 257 if (quoting) 258 out.append("\\E"); 260 return out.toString(); 261 } 262 263 277 public IRegion replace(String text, boolean regExReplace) throws BadLocationException { 278 return findReplace(REPLACE, -1, null, text, false, false, false, regExReplace); 279 } 280 281 283 286 public int length() { 287 return fDocument.getLength(); 288 } 289 290 293 public char charAt(int index) { 294 try { 295 return fDocument.getChar(index); 296 } catch (BadLocationException e) { 297 throw new IndexOutOfBoundsException (); 298 } 299 } 300 301 304 public CharSequence subSequence(int start, int end) { 305 try { 306 return fDocument.get(start, end - start); 307 } catch (BadLocationException e) { 308 throw new IndexOutOfBoundsException (); 309 } 310 } 311 312 315 public String toString() { 316 return fDocument.get(); 317 } 318 } 319
| Popular Tags
|