📄 buffer.java
字号:
} //}}} //{{{ indentLines() method /** * Indents all specified lines. * @param lines The line numbers * @since jEdit 3.2pre1 */ public void indentLines(int[] lines) { try { beginCompoundEdit(); for(int i = 0; i < lines.length; i++) indentLine(lines[i],true); } finally { endCompoundEdit(); } } //}}} //{{{ indentLine() method /** * @deprecated Use {@link #indentLine(int,boolean)} instead. */ public boolean indentLine(int lineIndex, boolean canIncreaseIndent, boolean canDecreaseIndent) { return indentLine(lineIndex,canDecreaseIndent); } //}}} //{{{ indentLine() method /** * Indents the specified line. * @param line The line number to indent * @param canDecreaseIndent If true, the indent can be decreased as a * result of this. Set this to false for Tab key. * @return true If indentation took place, false otherwise. * @since jEdit 4.2pre2 */ public boolean indentLine(int lineIndex, boolean canDecreaseIndent) { int[] whitespaceChars = new int[1]; int currentIndent = getCurrentIndentForLine(lineIndex, whitespaceChars); int idealIndent = getIdealIndentForLine(lineIndex); if(idealIndent == -1 || idealIndent == currentIndent || (!canDecreaseIndent && idealIndent < currentIndent)) return false; // Do it try { beginCompoundEdit(); int start = getLineStartOffset(lineIndex); remove(start,whitespaceChars[0]); insert(start,MiscUtilities.createWhiteSpace( idealIndent,(getBooleanProperty("noTabs") ? 0 : getTabSize()))); } finally { endCompoundEdit(); } return true; } //}}} //{{{ getCurrentIndentForLine() method /** * Returns the line's current leading indent. * @param lineIndex The line number * @param whitespaceChars If this is non-null, the number of whitespace * characters is stored at the 0 index * @since jEdit 4.2pre2 */ public int getCurrentIndentForLine(int lineIndex, int[] whitespaceChars) { getLineText(lineIndex,seg); int tabSize = getTabSize(); int currentIndent = 0;loop: for(int i = 0; i < seg.count; i++) { char c = seg.array[seg.offset + i]; switch(c) { case ' ': currentIndent++; if(whitespaceChars != null) whitespaceChars[0]++; break; case '\t': currentIndent += (tabSize - (currentIndent % tabSize)); if(whitespaceChars != null) whitespaceChars[0]++; break; default: break loop; } } return currentIndent; } //}}} //{{{ getIdealIndentForLine() method /** * Returns the ideal leading indent for the specified line. * This will apply the various auto-indent rules. * @param lineIndex The line number */ public int getIdealIndentForLine(int lineIndex) { final String EXPLICIT_START = "{{{"; final String EXPLICIT_END = "}}}"; if(lineIndex == 0) return -1; //{{{ Get properties String openBrackets = getStringProperty("indentOpenBrackets"); if(openBrackets == null) openBrackets = ""; String closeBrackets = getStringProperty("indentCloseBrackets"); if(closeBrackets == null) closeBrackets = ""; RE indentNextLineRE; try { indentNextLineRE = getRegexpProperty("indentNextLine", RE.REG_ICASE,RESearchMatcher.RE_SYNTAX_JEDIT); } catch(REException re) { indentNextLineRE = null; Log.log(Log.ERROR,this,"Invalid indentNextLine regexp"); Log.log(Log.ERROR,this,re); } RE indentNextLinesRE; try { indentNextLinesRE = getRegexpProperty("indentNextLines", RE.REG_ICASE,RESearchMatcher.RE_SYNTAX_JEDIT); } catch(REException re) { indentNextLinesRE = null; Log.log(Log.ERROR,this,"Invalid indentNextLines regexp"); Log.log(Log.ERROR,this,re); } boolean doubleBracketIndent = getBooleanProperty("doubleBracketIndent"); boolean lineUpClosingBracket = getBooleanProperty("lineUpClosingBracket"); int tabSize = getTabSize(); int indentSize = getIndentSize(); //}}} //{{{ Get indent attributes of previous line int prevLineIndex = getPriorNonEmptyLine(lineIndex); if(prevLineIndex == -1) return -1; String prevLine = getLineText(prevLineIndex); /* * On the previous line, * if(bob) { --> +1 * if(bob) { } --> 0 * } else if(bob) { --> +1 */ boolean prevLineStart = true; // False after initial indent int indent = 0; // Indent width (tab expanded) int prevLineBrackets = 0; // Additional bracket indent int prevLineCloseBracketIndex = -1; // For finding whether we're in // this kind of construct: // if (cond1) // while (cond2) // if (cond3){ // // } // So we know to indent the next line under the 1st if. int prevLineUnclosedParenIndex = -1; // Index of the last unclosed parenthesis int prevLineParenWeight = 0; // (openParens - closeParens) Stack openParens = new Stack(); for(int i = 0; i < prevLine.length(); i++) { char c = prevLine.charAt(i); switch(c) { case ' ': if(prevLineStart) indent++; break; case '\t': if(prevLineStart) { indent += (tabSize - (indent % tabSize)); } break; default: prevLineStart = false; if(closeBrackets.indexOf(c) != -1) { if(prevLine.regionMatches(false, i,EXPLICIT_END,0,3)) i += 2; else { prevLineBrackets--; if(prevLineBrackets < 0) { if(lineUpClosingBracket) prevLineBrackets = 0; prevLineCloseBracketIndex = i; } } } else if(openBrackets.indexOf(c) != -1) { if(prevLine.regionMatches(false, i,EXPLICIT_START,0,3)) i += 2; else prevLineBrackets++; } else if (c == '(') { openParens.push(new Integer(i)); prevLineParenWeight++; } else if (c == ')') { if(openParens.size() > 0) openParens.pop(); prevLineParenWeight--; } break; } } if(openParens.size() > 0) { prevLineUnclosedParenIndex = ((Integer) openParens.pop()).intValue(); } //}}} if(Debug.INDENT_DEBUG) { Log.log(Log.DEBUG,this,"Determined previous line"); Log.log(Log.DEBUG,this,"indent=" + indent + ",prevLineBrackets=" + prevLineBrackets + ",prevLineCloseBracketIndex=" + prevLineCloseBracketIndex); } //{{{ Get indent attributes for current line String line = getLineText(lineIndex); /* * On the current line, * } --> -1 * } else if(bob) { --> -1 * if(bob) { } --> 0 */ int lineBrackets = 0; // Additional bracket indent int closeBracketIndex = -1; // For lining up closing // and opening brackets for(int i = 0; i < line.length(); i++) { char c = line.charAt(i); if(closeBrackets.indexOf(c) != -1) { if(line.regionMatches(false, i,EXPLICIT_END,0,3)) i += 2; else { closeBracketIndex = i; lineBrackets--; } } else if(openBrackets.indexOf(c) != -1) { if(line.regionMatches(false, i,EXPLICIT_START,0,3)) i += 2; else if(lineBrackets >= 0) lineBrackets++; } } //}}} if(Debug.INDENT_DEBUG) { Log.log(Log.DEBUG,this,"Determined current line"); Log.log(Log.DEBUG,this,"lineBrackets=" + lineBrackets + ",closeBracketIndex=" + closeBracketIndex); } //{{{ Deep indenting if(getBooleanProperty("deepIndent")) { if(prevLineParenWeight > 0) { indent = prevLineUnclosedParenIndex+1; for (int i = 0; i < prevLine.length(); i++) { if (prevLine.charAt(i) == '\t') indent += tabSize-1; } return indent; } else if(prevLineParenWeight < 0) { int openParenOffset = TextUtilities.findMatchingBracket(this,prevLineIndex,prevLine.lastIndexOf(")")); if(openParenOffset >= 0) { int startLine = getLineOfOffset(openParenOffset); int startLineParenWeight = getLineParenWeight(startLine); if(startLineParenWeight == 1) indent = getCurrentIndentForLine(startLine,null); else indent = getOpenParenIndent(startLine,lineIndex); } } // no parenthesis on previous line (prevLineParenWeight == 0) so the normal indenting rules are used } //}}} //{{{ Handle brackets if(prevLineBrackets > 0) indent += (indentSize * prevLineBrackets); if(lineUpClosingBracket) { if(lineBrackets < 0) { int openBracketIndex = TextUtilities.findMatchingBracket( this,lineIndex,closeBracketIndex); if(openBracketIndex != -1) { int openLineIndex = getLineOfOffset(openBracketIndex); String openLine = getLineText(openLineIndex); Log.log(Log.DEBUG,this,"parenWeight of "+openLine+" is "+getLineParenWeight(openLineIndex)); if (getLineParenWeight(openLineIndex) < 0) { openBracketIndex = TextUtilities.findMatchingBracket(this,openLineIndex,openLine.indexOf(")")); Log.log(Log.DEBUG,this,"openBracketIndex: "+openBracketIndex); } openLine = getLineText(getLineOfOffset(openBracketIndex)); Log.log(Log.DEBUG,this,"openLine: "+openLine); indent = MiscUtilities.getLeadingWhiteSpaceWidth( openLine,tabSize); Log.log(Log.DEBUG,this,"indent: "+indent); } else return -1; } } else { if(prevLineBrackets < 0) { int offset = TextUtilities.findMatchingBracket( this,prevLineIndex,prevLineCloseBracketIndex); if(offset != -1) { String closeLine = getLineText(getLineOfOffset(offset)); indent = MiscUtilities.getLeadingWhiteSpaceWidth( closeLine,tabSize); } else return -1; } }//}}} //{{{ Handle regexps if(lineBrackets >= 0) { // If the previous line matches indentNextLine or indentNextLines, // add a level of indent if((lineBrackets == 0 || doubleBracketIndent) && indentNextLinesRE != null && indentNextLinesRE.isMatch(prevLine)) { if(Debug.INDENT_DEBUG) { Log.log(Log.DEBUG,this,"Matches indentNextLines"); } indent += indentSize; } else if(indentNextLineRE != null) { if((lineBrackets == 0 || doubleBracketIndent) && indentNextLineRE.isMatch(prevLine)) indent += indentSize; // we don't want // if(foo) // { // <--- decreased indent else if(prevLineBrackets == 0) { // While prior lines match indentNextLine, remove a level of indent // this correctly handles constructs like: // if(foo) // if(bar) // if(baz) // <--- put indent here int prevPrevLineIndex; /* if(prevLineCloseBracketIndex != -1) { int offset = TextUtilities.findMatchingBracket( this,prevLineIndex,prevLineCloseBracketIndex); if(offset == -1) return -1; prevPrevLineIndex = getLineOfOffset(offset); } else */ prevPrevLineIndex = getPriorNonEmptyLine(prevLineIndex); while(prevPrevLineIndex != -1) { if(indentNextLineRE.isMatch(getLineText(prevPrevLineIndex))) indent = getCurrentIndentForLine(prevPrevLineIndex,null); else break; if(Debug.INDENT_DEBUG) { Log.log(Log.DEBUG,this, prevPrevLineIndex + " matches " + "indentNextLine"); } prevPrevLineIndex = getPriorNonEmptyLine(prevPrevLineIndex); } } } } //}}} return indent; } //}}} //{{{ getLineParenWeight() method /** * Returns the number of open parenthesis minus the number of close parenthesis. * @param line The line number * @since jEdit 4.2pre9 */ private int getLineParenWeight(int line) { String lineText = getLineText(line); int parenWeight = 0; for(int i = 0; i < lineText.length(); i++) { char c = lineText.charAt(i); switch(c) { case '(': parenWeight++; break; case ')': parenWeight--; break; default: } } return parenWeight; } //}}} //{{{ getOpenParenIndent() method /** * Returns the appropriate indent based on open parenthesis on previous lines. * * @param startLine The line where parens were last balanced * @param targetLine The line we're finding the indent for */ private int getOpenParenIndent(int startLine, int targetLine) { Stack openParens = new Stack(); String lineText; for(int lineIndex = startLine; lineIndex < targetLine; lineIndex++) { lineText = getLineText(lineIndex); for(int i = 0; i < lineText.length(); i++) { char c = lineText.charAt(i); switch(c) { case '(': openParens.push(new Integer(i)); break; case ')': if(openParens.size() > 0) openParens.pop(); break; default: } } } int indent = getCurrentIndentForLine(startLine,null); if(openParens.size() > 0) indent += ((Integer) openParens.pop()).intValue(); return indent; } //}}} //{{{ getVirtualWidth() method /** * Returns the virtual column number (taking tabs into account) of the * specified position. * * @param line The line number * @param column The column number * @since jEdit 4.1pre1 */ public int getVirtualWidth(int line, int column) { try { readLock(); int start = getLineStartOffset(line); getText(start,column,seg); return MiscUtilities.getVirtualWidth(seg,getTabSize()); } finally { readUnlock(); } } //}}} //{{{ getOffsetOfVirtualColumn() method /** * Returns the offset of a virtual column number (taking tabs * into account) relative to the start of the line in question. * * @param line The line number * @param column The virtual column number * @param totalVirtualWidth If this array is non-null, the total * virtual width will be stored in its first location if this method * returns -1. * * @return -1 if the column is out of bounds * * @since jEdit 4.1pre1 */ public int getOffsetOfVirtualColumn(int line, int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -