📄 searchandreplace.java
字号:
{ buffer.beginCompoundEdit(); retVal = _replace(view,buffer,matcher, 0,buffer.getLength(), smartCaseReplace); } finally { buffer.endCompoundEdit(); } if(retVal != 0) { fileCount++; occurCount += retVal; jEdit.commitTemporary(buffer); } } } catch(Exception e) { Log.log(Log.ERROR,SearchAndReplace.class,e); Object[] args = { e.toString() }; GUIUtilities.error(comp, beanshell ? "searcherror-bsh" : "searcherror",args); } finally { view.hideWaitCursor(); } /* Don't do this when playing a macro, cos it's annoying */ if(!BeanShell.isScriptRunning()) { Object[] args = { new Integer(occurCount), new Integer(fileCount) }; view.getStatus().setMessageAndClear(jEdit.getProperty( "view.status.replace-all",args)); if(occurCount == 0) view.getToolkit().beep(); } return (fileCount != 0); } //}}} //}}} //{{{ load() method /** * Loads search and replace state from the properties. */ public static void load() { search = jEdit.getProperty("search.find.value"); replace = jEdit.getProperty("search.replace.value"); ignoreCase = jEdit.getBooleanProperty("search.ignoreCase.toggle"); regexp = jEdit.getBooleanProperty("search.regexp.toggle"); beanshell = jEdit.getBooleanProperty("search.beanshell.toggle"); wrap = jEdit.getBooleanProperty("search.wrap.toggle"); fileset = new CurrentBufferSet(); // Tags plugin likes to call this method at times other than // startup; so we need to fire a SearchSettingsChanged to // notify the search bar and so on. matcher = null; EditBus.send(new SearchSettingsChanged(null)); } //}}} //{{{ save() method /** * Saves search and replace state to the properties. */ public static void save() { jEdit.setProperty("search.find.value",search); jEdit.setProperty("search.replace.value",replace); jEdit.setBooleanProperty("search.ignoreCase.toggle",ignoreCase); jEdit.setBooleanProperty("search.regexp.toggle",regexp); jEdit.setBooleanProperty("search.beanshell.toggle",beanshell); jEdit.setBooleanProperty("search.wrap.toggle",wrap); } //}}} //{{{ Private members //{{{ Instance variables private static String search; private static String replace; private static BshMethod replaceMethod; private static NameSpace replaceNS = new NameSpace( BeanShell.getNameSpace(), BeanShell.getNameSpace().getClassManager(), "search and replace"); private static boolean regexp; private static boolean ignoreCase; private static boolean reverse; private static boolean beanshell; private static boolean wrap; private static SearchMatcher matcher; private static SearchFileSet fileset; //}}} //{{{ initReplace() method /** * Set up BeanShell replace if necessary. */ private static void initReplace() throws Exception { if(beanshell && replace.length() != 0) { replaceMethod = BeanShell.cacheBlock("replace", "return (" + replace + ");",true); } else replaceMethod = null; } //}}} //{{{ record() method private static void record(View view, String action, boolean replaceAction, boolean recordFileSet) { Macros.Recorder recorder = view.getMacroRecorder(); if(recorder != null) { recorder.record("SearchAndReplace.setSearchString(\"" + MiscUtilities.charsToEscapes(search) + "\");"); if(replaceAction) { recorder.record("SearchAndReplace.setReplaceString(\"" + MiscUtilities.charsToEscapes(replace) + "\");"); recorder.record("SearchAndReplace.setBeanShellReplace(" + beanshell + ");"); } else { // only record this if doing a find next recorder.record("SearchAndReplace.setAutoWrapAround(" + wrap + ");"); recorder.record("SearchAndReplace.setReverseSearch(" + reverse + ");"); } recorder.record("SearchAndReplace.setIgnoreCase(" + ignoreCase + ");"); recorder.record("SearchAndReplace.setRegexp(" + regexp + ");"); if(recordFileSet) { recorder.record("SearchAndReplace.setSearchFileSet(" + fileset.getCode() + ");"); } recorder.record("SearchAndReplace." + action + ";"); } } //}}} //{{{ replaceInSelection() method private static int replaceInSelection(View view, JEditTextArea textArea, Buffer buffer, SearchMatcher matcher, boolean smartCaseReplace, Selection s) throws Exception { /* if an occurence occurs at the beginning of the selection, the selection start will get moved. this sucks, so we hack to avoid it. */ int start = s.getStart(); int returnValue; if(s instanceof Selection.Range) { returnValue = _replace(view,buffer,matcher, s.getStart(),s.getEnd(), smartCaseReplace); textArea.removeFromSelection(s); textArea.addToSelection(new Selection.Range( start,s.getEnd())); } else if(s instanceof Selection.Rect) { Selection.Rect rect = (Selection.Rect)s; int startCol = rect.getStartColumn( buffer); int endCol = rect.getEndColumn( buffer); returnValue = 0; for(int j = s.getStartLine(); j <= s.getEndLine(); j++) { returnValue += _replace(view,buffer, matcher, getColumnOnOtherLine(buffer,j,startCol), getColumnOnOtherLine(buffer,j,endCol), smartCaseReplace); } textArea.addToSelection(new Selection.Rect( start,s.getEnd())); } else throw new RuntimeException("Unsupported: " + s); return returnValue; } //}}} //{{{ _replace() method /** * Replaces all occurances of the search string with the replacement * string. * @param view The view * @param buffer The buffer * @param start The start offset * @param end The end offset * @param matcher The search matcher to use * @param smartCaseReplace See user's guide * @return The number of occurrences replaced */ private static int _replace(View view, Buffer buffer, SearchMatcher matcher, int start, int end, boolean smartCaseReplace) throws Exception { int occurCount = 0; boolean endOfLine = (buffer.getLineEndOffset( buffer.getLineOfOffset(end)) - 1 == end); Segment text = new Segment(); int offset = start;loop: for(int counter = 0; ; counter++) { buffer.getText(offset,end - offset,text); boolean startOfLine = (buffer.getLineStartOffset( buffer.getLineOfOffset(offset)) == offset); SearchMatcher.Match occur = matcher.nextMatch( new CharIndexedSegment(text,false), startOfLine,endOfLine,counter == 0, false); if(occur == null) break loop; String found = new String(text.array, text.offset + occur.start, occur.end - occur.start); int length = replaceOne(buffer,occur,offset,found, smartCaseReplace); if(length == -1) offset += occur.end; else { offset += occur.start + length; end += (length - found.length()); occurCount++; } } return occurCount; } //}}} //{{{ replaceOne() method /** * Replace one occurrence of the search string with the * replacement string. */ private static int replaceOne(Buffer buffer, SearchMatcher.Match occur, int offset, String found, boolean smartCaseReplace) throws Exception { String subst = replaceOne(occur,found); if(smartCaseReplace && ignoreCase) { int strCase = TextUtilities.getStringCase(found); if(strCase == TextUtilities.LOWER_CASE) subst = subst.toLowerCase(); else if(strCase == TextUtilities.UPPER_CASE) subst = subst.toUpperCase(); else if(strCase == TextUtilities.TITLE_CASE) subst = TextUtilities.toTitleCase(subst); } if(subst != null) { int start = offset + occur.start; int end = offset + occur.end; buffer.remove(start,end - start); buffer.insert(start,subst); return subst.length(); } else return -1; } //}}} //{{{ replaceOne() method private static String replaceOne(SearchMatcher.Match occur, String found) throws Exception { if(regexp) { if(replaceMethod != null) return regexpBeanShellReplace(occur,found); else return regexpReplace(occur,found); } else { if(replaceMethod != null) return literalBeanShellReplace(occur,found); else return replace; } } //}}} //{{{ regexpBeanShellReplace() method private static String regexpBeanShellReplace(SearchMatcher.Match occur, String found) throws Exception { for(int i = 0; i < occur.substitutions.length; i++) { replaceNS.setVariable("_" + i, occur.substitutions[i]); } Object obj = BeanShell.runCachedBlock( replaceMethod,null,replaceNS); if(obj == null) return ""; else return obj.toString(); } //}}} //{{{ regexpReplace() method private static String regexpReplace(SearchMatcher.Match occur, String found) throws Exception { StringBuffer buf = new StringBuffer(); for(int i = 0; i < replace.length(); i++) { char ch = replace.charAt(i); switch(ch) { case '$': if(i == replace.length() - 1) { buf.append(ch); break; } ch = replace.charAt(++i); if(ch == '$') buf.append('$'); else if(ch == '0') buf.append(found); else if(Character.isDigit(ch)) { int n = ch - '0'; if(n < occur .substitutions .length) { buf.append( occur .substitutions [n] ); } } break; case '\\': if(i == replace.length() - 1) { buf.append('\\'); break; } ch = replace.charAt(++i); switch(ch) { case 'n': buf.append('\n'); break; case 't': buf.append('\t'); break; default: buf.append(ch); break; } break; default: buf.append(ch); break; } } return buf.toString(); } //}}} //{{{ literalBeanShellReplace() method private static String literalBeanShellReplace(SearchMatcher.Match occur, String found) throws Exception { replaceNS.setVariable("_0",found); Object obj = BeanShell.runCachedBlock( replaceMethod, null,replaceNS); if(obj == null) return ""; else return obj.toString(); } //}}} //{{{ getColumnOnOtherLine() method /** * Should be somewhere else... */ private static int getColumnOnOtherLine(Buffer buffer, int line, int col) { int returnValue = buffer.getOffsetOfVirtualColumn( line,col,null); if(returnValue == -1) return buffer.getLineEndOffset(line) - 1; else return buffer.getLineStartOffset(line) + returnValue; } //}}} //}}}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -