/** * Find the next occurrence of empty line(s) * Will match all valid lines except single ^$ * * @param editor * @param forward true if moving forward * @return -1 if not found, else offset of match in widget coords */ protected int findNext(ITextEditor editor, boolean forward) { IFindReplaceTarget frt = getTarget(editor); Point selection = frt.getSelection(); // don't move past eob int offset = Math.min(MarkUtils.getCharCount(editor), Math.max(0,MarkUtils.getCaretOffset(editor) + (forward ? 1 : -2))); int result = ((IFindReplaceTargetExtension3)frt).findAndSelect(offset, PARAGRAPH_START, forward, false, false, true); if (result != -1) { if ((forward && offset > result) || (!forward && offset < result)) { // reset if we've wrapped around in the search MarkUtils.setWidgetSelection(editor, selection.x, selection.x + selection.y); result = -1; } } return result; }
/** * Case-based replacement - after the initial find has already happened * * @param replacer - the replacement string (may be regexp) * @param index - offset of find * @param all - all if true, else initial * @return - the replacement region * * @throws BadLocationException */ private IRegion caseReplace(String replacer, int index, boolean all) throws BadLocationException { IRegion result = null; IDocumentUndoManager undoer = DocumentUndoManagerRegistry.getDocumentUndoManager(getDocument()); try { if (!isReplaceAll() && undoer != null) { undoer.beginCompoundChange(); } IFindReplaceTarget target = getTarget(); // first replace with (possible regexp) string ((IFindReplaceTargetExtension3)target).replaceSelection(replacer, isRegexp()); // adjust case of actual replacement string replacer = target.getSelectionText(); String caseReplacer = replacer; if (all) { caseReplacer = caseReplacer.toUpperCase(); } else { caseReplacer = caseReplacer.trim(); caseReplacer = Character.toUpperCase(caseReplacer.charAt(0)) + caseReplacer.substring(1,caseReplacer.length()).toString(); // now update the replacement string with the re-cased part caseReplacer = replacer.replaceFirst(replacer.trim(), caseReplacer); } int ind = target.findAndSelect(index, replacer, true, false, false); if (ind > -1) { target.replaceSelection(caseReplacer); } } finally { if (!isReplaceAll() && undoer != null) { undoer.endCompoundChange(); } } return result; }
/** * Find the next occurrence of empty line consisting of ^$ * Since findNext will find multiple sequential ^$'s, we only need find one * * @param editor * @param forward * @return offset of match in widget coords */ protected int findNextEmpty(ITextEditor editor, boolean forward) { IFindReplaceTarget frt = getTarget(editor); Point selection = frt.getSelection(); int count = MarkUtils.getCharCount(editor); int coffset = MarkUtils.getCaretOffset(editor); // don't move past EOB int offset = Math.min(count,coffset + (forward ? 1 : -1)); //(forward ? selection.x + selection.y+1 : selection.x-2); int next = 0; int prev = -1; do { next = ((IFindReplaceTargetExtension3)frt).findAndSelect(offset, REGEX_BOL_HACK, forward, false, false, true); if (next == -1 || prev == next){ // we've run out of buffer offset = (forward ? count : 0); MarkUtils.setWidgetSelection(editor, offset, offset); return offset; } else if (forward && offset > next) { // protect against overrun MarkUtils.setWidgetSelection(editor, count, count); return count; } else if (!forward && offset < next) { // protect against overrun MarkUtils.setWidgetSelection(editor, 0, 0); return 0; } else { selection = frt.getSelection(); // Eclipse internals (frda) return different regions depending on whether the file has a // single or double line delimiter e.g. \r\n or \n. In the former it returns a 0 length // region, and in the latter a length of 1 if (selection.y == 0 || (!forward && selection.x == 0)) { // found it, or reached the top return selection.x; } if (selection.y == 1) { // check for single line delimiter char c = frt.getSelectionText().charAt(0); if (c == '\n' || c == '\r'){ return selection.x; } } // the widget count could change if a folded region expands automatically count = MarkUtils.getCharCount(editor); // don't move past EOB offset = Math.min(count,(forward ? selection.x + selection.y+1 : selection.x-1)); prev = next; } } while (next != -1); return next; }
/** * Perform one replacement * * @return the replacement index */ private boolean replaceIt() { boolean result = false; boolean forward = true; if (!checkPaused()) { findCount++; try { result = true; int index = getSearchOffset(); IFindReplaceTarget target = getTarget(); int fpos = findTarget(target,getSearchStr(), index, forward); if (fpos > -1) { boolean initial = false; boolean all = false; String replacer = replaceStr; if (!isCaseSensitive() && replacer.length() > 0) { // Preserve case using the emacs definition // - Preserving case means that if the string matched is all caps, or capitalized, // then its replacement is upper cased or capitalized.) String replacee = target.getSelectionText().trim(); if (replacee != null && replacee.length() > 0) { initial = Character.isUpperCase(replacee.charAt(0)); all = initial; if (initial) { for (int i = 1; i < replacee.length(); i++) { if (!Character.isUpperCase(replacee.charAt(i))) { all = false; break; } } } } } int adjust = 0; if (all || initial) { caseReplace(replacer,index,all); } else { if (isRegexLD()) { adjust = replacer.length(); // prevents repetitious find of same EOL // now we need the offset in model coords ITextSelection sel = (ITextSelection)getEditor().getSelectionProvider().getSelection(); // use document 'insert' instead of broken target replace getDocument().replace(sel.getOffset(),0,replacer); // search uses cursor position - s/r is always forward MarkUtils.setCursorOffset(getEditor(), sel.getOffset()+adjust); } else { ((IFindReplaceTargetExtension3)target).replaceSelection(replacer, isRegexp()); } } Point p = target.getSelection(); int rIndex = p.x + p.y + adjust; setSearchOffset(rIndex); } } catch (Exception e) { setResultString(e.getLocalizedMessage(), true); finish(); beep(); } } return result; }
/** * Replaces the selection with <code>replaceString</code>. If <code>regExReplace</code> is <code>true</code>, * <code>replaceString</code> is a regex replace pattern which will get expanded if the underlying target supports * it. Returns the region of the inserted text; note that the returned selection covers the expanded pattern in case * of regex replace. * * @param replaceString * the replace string (or a regex pattern) * @param regExReplace * <code>true</code> if <code>replaceString</code> is a pattern * @return the selection after replacing, i.e. the inserted text * @since 3.0 */ /* default */Point replaceSelection(String replaceString, boolean regExReplace) { if (fTarget instanceof IFindReplaceTargetExtension3) ((IFindReplaceTargetExtension3) fTarget).replaceSelection(replaceString, regExReplace); else fTarget.replaceSelection(replaceString); return fTarget.getSelection(); }
/** * Searches for a string starting at the given offset and using the specified search directives. If a string has * been found it is selected and its start offset is returned. * * @param offset * the offset at which searching starts * @param findString * the string which should be found * @param forwardSearch * the direction of the search * @param caseSensitive * <code>true</code> performs a case sensitive search, <code>false</code> an insensitive search * @param wholeWord * if <code>true</code> only occurrences are reported in which the findString stands as a word by itself * @param regExSearch * if <code>true</code> findString represents a regular expression * @return the position of the specified string, or -1 if the string has not been found * @since 3.0 */ /* default */int findAndSelect(int offset, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord, boolean regExSearch) { if (fTarget instanceof IFindReplaceTargetExtension3) return ((IFindReplaceTargetExtension3) fTarget).findAndSelect(offset, findString, forwardSearch, caseSensitive, wholeWord, regExSearch); return fTarget.findAndSelect(offset, findString, forwardSearch, caseSensitive, wholeWord); }