[Pydev-cvs] org.python.pydev/src/org/python/pydev/editor/autoedit AbstractIndentPrefs.java, 1.6, 1.
Brought to you by:
fabioz
From: Fabio Z. <fa...@us...> - 2008-09-28 12:49:22
|
Update of /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/autoedit In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4313/src/org/python/pydev/editor/autoedit Modified Files: AbstractIndentPrefs.java DefaultIndentPrefs.java PyAutoIndentStrategy.java IIndentPrefs.java Log Message: Synching to latest changes: Pydev <ul> <li><strong>Editor</strong>: Cursor settings no longer overridden</li> <li><strong>Code-completion</strong>: If __all__ is defined with runtime elements (and not only in a single assign statement), it's ignored for code-completion purposes</li> <li><strong>Debugger</strong>: Pythonpath the same in debug and regular modes (sys.path[0] is the same directory as the file run)</li> <li><strong>Debugger</strong>: Persist choices done in the debugger when files from the debugger are not found</li> <li><strong>Interpreter config</strong>: "email" automatically added to the "forced builtins"</li> <li><strong>Parser</strong>: Correctly recognizing absolute import with 3 or more levels</li> <li><strong>Syntax check</strong>: Option to do only on active editor</li> </ul> Also: tabs changed for spaces Index: PyAutoIndentStrategy.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/autoedit/PyAutoIndentStrategy.java,v retrieving revision 1.72 retrieving revision 1.73 diff -C2 -d -r1.72 -r1.73 *** PyAutoIndentStrategy.java 21 Aug 2008 18:25:18 -0000 1.72 --- PyAutoIndentStrategy.java 28 Sep 2008 12:45:49 -0000 1.73 *************** *** 60,64 **** private Tuple<String,Boolean> autoIndentNewline(IDocument document, int length, String text, int offset) throws BadLocationException { ! if (offset > 0) { PySelection selection = new PySelection(document, offset); --- 60,64 ---- private Tuple<String,Boolean> autoIndentNewline(IDocument document, int length, String text, int offset) throws BadLocationException { ! if (offset > 0) { PySelection selection = new PySelection(document, offset); *************** *** 84,106 **** //we have to check if smartIndent is -1 because otherwise we are inside some bracket if(smartIndent == -1 && DocUtils.isClosingPeer(lastChar)){ ! //ok, not inside brackets PythonPairMatcher matcher = new PythonPairMatcher(DocUtils.BRACKETS); int bracketOffset = selection.getLineOffset()+curr; IRegion region = matcher.match(document, bracketOffset+1); if(region != null){ ! if(!PySelection.endsInSameLine(document, region)){ ! //we might not have a match if there is an error in the program... ! //e.g. a single ')' without its counterpart. ! int openingBracketLine = document.getLineOfOffset(region.getOffset()); ! String openingBracketLineStr = PySelection.getLine(document, openingBracketLine); ! int first = PySelection.getFirstCharPosition(openingBracketLineStr); ! String initial = getCharsBeforeNewLine(text); ! text = initial + openingBracketLineStr.substring(0, first); ! return new Tuple<String, Boolean>(text, isInsidePar); ! } } } else if (smartIndent == -1 && lastChar == ':') { //we have to check if smartIndent is -1 because otherwise we are in a dict ! //ok, not inside brackets text = indentBasedOnStartingScope(text, selection, false); return new Tuple<String, Boolean>(text, isInsidePar); --- 84,106 ---- //we have to check if smartIndent is -1 because otherwise we are inside some bracket if(smartIndent == -1 && DocUtils.isClosingPeer(lastChar)){ ! //ok, not inside brackets PythonPairMatcher matcher = new PythonPairMatcher(DocUtils.BRACKETS); int bracketOffset = selection.getLineOffset()+curr; IRegion region = matcher.match(document, bracketOffset+1); if(region != null){ ! if(!PySelection.endsInSameLine(document, region)){ ! //we might not have a match if there is an error in the program... ! //e.g. a single ')' without its counterpart. ! int openingBracketLine = document.getLineOfOffset(region.getOffset()); ! String openingBracketLineStr = PySelection.getLine(document, openingBracketLine); ! int first = PySelection.getFirstCharPosition(openingBracketLineStr); ! String initial = getCharsBeforeNewLine(text); ! text = initial + openingBracketLineStr.substring(0, first); ! return new Tuple<String, Boolean>(text, isInsidePar); ! } } } else if (smartIndent == -1 && lastChar == ':') { //we have to check if smartIndent is -1 because otherwise we are in a dict ! //ok, not inside brackets text = indentBasedOnStartingScope(text, selection, false); return new Tuple<String, Boolean>(text, isInsidePar); *************** *** 139,256 **** * @return the text for the indent */ ! private String indentBasedOnStartingScope(String text, PySelection selection, boolean checkForLowestBeforeNewScope) { ! Tuple3<String,String, String> previousIfLine = selection.getPreviousLineThatStartsScope(); ! if(previousIfLine != null){ ! String initial = getCharsBeforeNewLine(text); ! ! if(previousIfLine.o2 == null){ //no dedent was found ! String indent = PySelection.getIndentationFromLine(previousIfLine.o1); ! if(checkForLowestBeforeNewScope && previousIfLine.o3 != null){ ! indent = PySelection.getIndentationFromLine(previousIfLine.o3); text = initial + indent; }else{ ! text = initial + indent + prefs.getIndentationString(); } ! ! }else{ //some dedent was found ! String indent = PySelection.getIndentationFromLine(previousIfLine.o2); ! String indentationString = prefs.getIndentationString(); ! ! final int i = indent.length() - indentationString.length(); ! if (i > 0 && indent.length() > i){ ! text = (initial+indent).substring(0, i+1); ! }else{ ! text = initial; // this can happen if we found a dedent that is 1 level deep ! } ! } ! ! } ! return text; ! } ! /** ! * Returns the first offset greater than <code>offset</code> and smaller than ! * <code>end</code> whose character is not a space or tab character. If no such ! * offset is found, <code>end</code> is returned. ! * ! * @param document the document to search in ! * @param offset the offset at which searching start ! * @param end the offset at which searching stops ! * @return the offset in the specified range whose character is not a space or tab ! * @exception BadLocationException if position is an invalid range in the given document ! */ ! private int findEndOfWhiteSpace(IDocument document, int offset, int end) throws BadLocationException { ! while (offset < end) { ! char c= document.getChar(offset); ! if (c != ' ' && c != '\t') { ! return offset; ! } ! offset++; ! } ! return end; ! } ! private void autoIndentSameAsPrevious(IDocument d, DocumentCommand c) { ! String txt = autoIndentSameAsPrevious(d, c.offset, c.text, true); ! if(txt != null){ ! c.text = txt; ! } ! } ! /** ! * Copies the indentation of the previous line. ! * ! * @param d the document to work on ! * @param text the string that should added to the start of the returned string ! * @param considerEmptyLines whether we should consider empty lines in this function ! * @param c the command to deal with ! * ! * @return a string with text+ the indentation found in the previous line (or previous non-empty line). ! */ ! private String autoIndentSameAsPrevious(IDocument d, int offset, String text, boolean considerEmptyLines) { ! if (offset == -1 || d.getLength() == 0) ! return null; ! try { ! // find start of line ! IRegion info= d.getLineInformationOfOffset(offset); ! String line = d.get(info.getOffset(), info.getLength()); ! ! if(!considerEmptyLines){ ! int currLine = d.getLineOfOffset(offset); ! while(PySelection.containsOnlyWhitespaces(line)){ ! currLine--; ! if(currLine <= 0){ ! break; ! } ! info= d.getLineInformation(currLine); ! line = d.get(info.getOffset(), info.getLength()); ! } ! } ! ! int start= info.getOffset(); ! // find white spaces ! int end= findEndOfWhiteSpace(d, start, offset); ! FastStringBuffer buf= new FastStringBuffer(text, end-start+1); ! if (end > start) { ! // append to input ! buf.append(d.get(start, end - start)); ! } ! return buf.toString(); ! } catch (BadLocationException excp) { ! // stop work ! return null; ! } ! } /** --- 139,256 ---- * @return the text for the indent */ ! private String indentBasedOnStartingScope(String text, PySelection selection, boolean checkForLowestBeforeNewScope) { ! Tuple3<String,String, String> previousIfLine = selection.getPreviousLineThatStartsScope(); ! if(previousIfLine != null){ ! String initial = getCharsBeforeNewLine(text); ! ! if(previousIfLine.o2 == null){ //no dedent was found ! String indent = PySelection.getIndentationFromLine(previousIfLine.o1); ! if(checkForLowestBeforeNewScope && previousIfLine.o3 != null){ ! indent = PySelection.getIndentationFromLine(previousIfLine.o3); text = initial + indent; }else{ ! text = initial + indent + prefs.getIndentationString(); } ! ! }else{ //some dedent was found ! String indent = PySelection.getIndentationFromLine(previousIfLine.o2); ! String indentationString = prefs.getIndentationString(); ! ! final int i = indent.length() - indentationString.length(); ! if (i > 0 && indent.length() > i){ ! text = (initial+indent).substring(0, i+1); ! }else{ ! text = initial; // this can happen if we found a dedent that is 1 level deep ! } ! } ! ! } ! return text; ! } ! /** ! * Returns the first offset greater than <code>offset</code> and smaller than ! * <code>end</code> whose character is not a space or tab character. If no such ! * offset is found, <code>end</code> is returned. ! * ! * @param document the document to search in ! * @param offset the offset at which searching start ! * @param end the offset at which searching stops ! * @return the offset in the specified range whose character is not a space or tab ! * @exception BadLocationException if position is an invalid range in the given document ! */ ! private int findEndOfWhiteSpace(IDocument document, int offset, int end) throws BadLocationException { ! while (offset < end) { ! char c= document.getChar(offset); ! if (c != ' ' && c != '\t') { ! return offset; ! } ! offset++; ! } ! return end; ! } ! private void autoIndentSameAsPrevious(IDocument d, DocumentCommand c) { ! String txt = autoIndentSameAsPrevious(d, c.offset, c.text, true); ! if(txt != null){ ! c.text = txt; ! } ! } ! /** ! * Copies the indentation of the previous line. ! * ! * @param d the document to work on ! * @param text the string that should added to the start of the returned string ! * @param considerEmptyLines whether we should consider empty lines in this function ! * @param c the command to deal with ! * ! * @return a string with text+ the indentation found in the previous line (or previous non-empty line). ! */ ! private String autoIndentSameAsPrevious(IDocument d, int offset, String text, boolean considerEmptyLines) { ! if (offset == -1 || d.getLength() == 0) ! return null; ! try { ! // find start of line ! IRegion info= d.getLineInformationOfOffset(offset); ! String line = d.get(info.getOffset(), info.getLength()); ! ! if(!considerEmptyLines){ ! int currLine = d.getLineOfOffset(offset); ! while(PySelection.containsOnlyWhitespaces(line)){ ! currLine--; ! if(currLine <= 0){ ! break; ! } ! info= d.getLineInformation(currLine); ! line = d.get(info.getOffset(), info.getLength()); ! } ! } ! ! int start= info.getOffset(); ! // find white spaces ! int end= findEndOfWhiteSpace(d, start, offset); ! FastStringBuffer buf= new FastStringBuffer(text, end-start+1); ! if (end > start) { ! // append to input ! buf.append(d.get(start, end - start)); ! } ! return buf.toString(); ! } catch (BadLocationException excp) { ! // stop work ! return null; ! } ! } /** *************** *** 287,301 **** public void customizeDocumentCommand(IDocument document, DocumentCommand command) { // super idents newlines the same amount as the previous line ! final boolean isNewLine = isNewLineText(document, command.length, command.text); ! String contentType = ParsingUtils.getContentType(document, command.offset); ! if(!contentType.equals(ParsingUtils.PY_DEFAULT)){ //the indentation is only valid for things in the code (comments should not be indented). //(that is, if it is not a new line... in this case, it may have to be indented) if(!isNewLine){ ! //we have to take care about tabs anyway ! getIndentPrefs().convertToStd(document, command); return; }else{ --- 287,301 ---- public void customizeDocumentCommand(IDocument document, DocumentCommand command) { // super idents newlines the same amount as the previous line ! final boolean isNewLine = isNewLineText(document, command.length, command.text); ! String contentType = ParsingUtils.getContentType(document, command.offset); ! if(!contentType.equals(ParsingUtils.PY_DEFAULT)){ //the indentation is only valid for things in the code (comments should not be indented). //(that is, if it is not a new line... in this case, it may have to be indented) if(!isNewLine){ ! //we have to take care about tabs anyway ! getIndentPrefs().convertToStd(document, command); return; }else{ *************** *** 310,349 **** try { ! if (isNewLine) { ! customizeNewLine(document, command); ! }else if(command.text.equals("\t")){ ! PySelection ps = new PySelection(document, command.offset); ! //it is a tab ! String lineContentsToCursor = ps.getLineContentsToCursor(); ! int currSize = lineContentsToCursor.length(); ! int cursorLine = ps.getCursorLine(); ! if(cursorLine > 0){ ! //this is to know which would be expected if it was a new line in the previous line ! //(so that we know the 'expected' output ! IRegion prevLineInfo = document.getLineInformation(cursorLine-1); ! int prevLineEndOffset = prevLineInfo.getOffset()+prevLineInfo.getLength(); ! String prevExpectedIndent = autoIndentSameAsPrevious(document, prevLineEndOffset, "\n", false); String txt = prevExpectedIndent; ! Tuple<String, Boolean> prevLineTup = autoIndentNewline(document, 0, txt, prevLineEndOffset); txt = prevLineTup.o1; ! txt = txt.substring(1);//remove the newline prevExpectedIndent = prevExpectedIndent.substring(1); ! if (txt.length() > 0){ ! //now, we should not apply that indent if we are already at the 'max' indent in this line ! //(or better: we should go to that max if it would pass it) ! int sizeExpected = txt.length(); ! int sizeApplied = currSize + sizeExpected; ! if(currSize >= sizeExpected){ ! //ok, we already passed what we expected from the indentation, so, let's indent ! //to the next 'expected' position... ! ! boolean applied = false; ! //handle within parenthesis if(prevLineTup.o2){ ! int len = sizeApplied-sizeExpected; if(prevExpectedIndent.length() > len){ command.text = prevExpectedIndent.substring(len); --- 310,349 ---- try { ! if (isNewLine) { ! customizeNewLine(document, command); ! }else if(command.text.equals("\t")){ ! PySelection ps = new PySelection(document, command.offset); ! //it is a tab ! String lineContentsToCursor = ps.getLineContentsToCursor(); ! int currSize = lineContentsToCursor.length(); ! int cursorLine = ps.getCursorLine(); ! if(cursorLine > 0){ ! //this is to know which would be expected if it was a new line in the previous line ! //(so that we know the 'expected' output ! IRegion prevLineInfo = document.getLineInformation(cursorLine-1); ! int prevLineEndOffset = prevLineInfo.getOffset()+prevLineInfo.getLength(); ! String prevExpectedIndent = autoIndentSameAsPrevious(document, prevLineEndOffset, "\n", false); String txt = prevExpectedIndent; ! Tuple<String, Boolean> prevLineTup = autoIndentNewline(document, 0, txt, prevLineEndOffset); txt = prevLineTup.o1; ! txt = txt.substring(1);//remove the newline prevExpectedIndent = prevExpectedIndent.substring(1); ! if (txt.length() > 0){ ! //now, we should not apply that indent if we are already at the 'max' indent in this line ! //(or better: we should go to that max if it would pass it) ! int sizeExpected = txt.length(); ! int sizeApplied = currSize + sizeExpected; ! if(currSize >= sizeExpected){ ! //ok, we already passed what we expected from the indentation, so, let's indent ! //to the next 'expected' position... ! ! boolean applied = false; ! //handle within parenthesis if(prevLineTup.o2){ ! int len = sizeApplied-sizeExpected; if(prevExpectedIndent.length() > len){ command.text = prevExpectedIndent.substring(len); *************** *** 353,375 **** if(!applied){ ! applyDefaultForTab(command, currSize); } ! }else if(sizeExpected == sizeApplied){ if(command.length == 0){ ! ps.deleteSpacesAfter(command.offset); } ! command.text = txt; ! }else if(sizeApplied > sizeExpected){ ! ps.deleteSpacesAfter(command.offset); ! command.text = txt.substring(0, sizeExpected - currSize); ! } ! }else{ ! applyDefaultForTab(command, currSize); ! } ! ! }else{ //cursorLine == 0 ! applyDefaultForTab(command, currSize); ! } } --- 353,375 ---- if(!applied){ ! applyDefaultForTab(command, currSize); } ! }else if(sizeExpected == sizeApplied){ if(command.length == 0){ ! ps.deleteSpacesAfter(command.offset); } ! command.text = txt; ! }else if(sizeApplied > sizeExpected){ ! ps.deleteSpacesAfter(command.offset); ! command.text = txt.substring(0, sizeExpected - currSize); ! } ! }else{ ! applyDefaultForTab(command, currSize); ! } ! ! }else{ //cursorLine == 0 ! applyDefaultForTab(command, currSize); ! } } *************** *** 377,399 **** ! if (prefs.getAutoParentesis() && (command.text.equals("[") || command.text.equals("{")) ) { ! PySelection ps = new PySelection(document, command.offset); ! char c = command.text.charAt(0); ! if (shouldClose(ps, c)) { ! command.shiftsCaret = false; command.text = c+""+DocUtils.getPeer(c); command.caretOffset = command.offset+1; ! } ! ! }else if (command.text.equals("(")) { ! /* ! * Now, let's also check if we are in an 'elif ' that must be dedented in the doc ! */ ! autoDedentElif(document, command); ! customizeParenthesis(document, command); } ! else if (command.text.equals(":")) { /* --- 377,399 ---- ! if (prefs.getAutoParentesis() && (command.text.equals("[") || command.text.equals("{")) ) { ! PySelection ps = new PySelection(document, command.offset); ! char c = command.text.charAt(0); ! if (shouldClose(ps, c)) { ! command.shiftsCaret = false; command.text = c+""+DocUtils.getPeer(c); command.caretOffset = command.offset+1; ! } ! ! }else if (command.text.equals("(")) { ! /* ! * Now, let's also check if we are in an 'elif ' that must be dedented in the doc ! */ ! autoDedentElif(document, command); ! customizeParenthesis(document, command); } ! else if (command.text.equals(":")) { /* *************** *** 422,449 **** */ else if (command.text.equals(" ")) { ! if( prefs.getAutoWriteImport()){ ! PySelection ps = new PySelection(document, command.offset); ! String completeLine = ps.getLineWithoutCommentsOrLiterals(); ! String lineToCursor = ps.getLineContentsToCursor().trim(); ! String lineContentsFromCursor = ps.getLineContentsFromCursor(); ! ! if( completeLine.indexOf(" import ") == -1 && ! StringUtils.leftTrim(completeLine).startsWith("from ")&& ! !completeLine.startsWith("import ")&& ! !completeLine.endsWith(" import") && ! !lineContentsFromCursor.startsWith("import")){ ! ! String importsTipperStr = ImportsSelection.getImportsTipperStr(lineToCursor, false).importsTipperStr; ! if(importsTipperStr.length() > 0){ ! command.text = " import "; ! } ! } ! } ! ! ! /* ! * Now, let's also check if we are in an 'elif ' that must be dedented in the doc ! */ ! autoDedentElif(document, command); } --- 422,449 ---- */ else if (command.text.equals(" ")) { ! if( prefs.getAutoWriteImport()){ ! PySelection ps = new PySelection(document, command.offset); ! String completeLine = ps.getLineWithoutCommentsOrLiterals(); ! String lineToCursor = ps.getLineContentsToCursor().trim(); ! String lineContentsFromCursor = ps.getLineContentsFromCursor(); ! ! if( completeLine.indexOf(" import ") == -1 && ! StringUtils.leftTrim(completeLine).startsWith("from ")&& ! !completeLine.startsWith("import ")&& ! !completeLine.endsWith(" import") && ! !lineContentsFromCursor.startsWith("import")){ ! ! String importsTipperStr = ImportsSelection.getImportsTipperStr(lineToCursor, false).importsTipperStr; ! if(importsTipperStr.length() > 0){ ! command.text = " import "; ! } ! } ! } ! ! ! /* ! * Now, let's also check if we are in an 'elif ' that must be dedented in the doc ! */ ! autoDedentElif(document, command); } *************** *** 487,491 **** public void customizeParenthesis(IDocument document, DocumentCommand command) throws BadLocationException { if(prefs.getAutoParentesis()){ ! PySelection ps = new PySelection(document, command.offset); String line = ps.getLine(); --- 487,491 ---- public void customizeParenthesis(IDocument document, DocumentCommand command) throws BadLocationException { if(prefs.getAutoParentesis()){ ! PySelection ps = new PySelection(document, command.offset); String line = ps.getLine(); *************** *** 557,570 **** PySelection selection = new PySelection(document, command.offset); if(selection.getCursorLineContents().trim().length() > 0){ ! command.text = autoIndentNewline(document, command.length, command.text, command.offset).o1; ! if(PySelection.containsOnlyWhitespaces(selection.getLineContentsToCursor())){ ! command.caretOffset = command.offset + selection.countSpacesAfter(command.offset); ! } } }else{ ! PySelection selection = new PySelection(document, command.offset); ! if(selection.getLineContentsToCursor().trim().endsWith(":")){ ! command.text += prefs.getIndentationString(); ! } } } --- 557,570 ---- PySelection selection = new PySelection(document, command.offset); if(selection.getCursorLineContents().trim().length() > 0){ ! command.text = autoIndentNewline(document, command.length, command.text, command.offset).o1; ! if(PySelection.containsOnlyWhitespaces(selection.getLineContentsToCursor())){ ! command.caretOffset = command.offset + selection.countSpacesAfter(command.offset); ! } } }else{ ! PySelection selection = new PySelection(document, command.offset); ! if(selection.getLineContentsToCursor().trim().endsWith(":")){ ! command.text += prefs.getIndentationString(); ! } } } *************** *** 575,590 **** * @param lineContentsToCursorLen the current cursor position at the current line */ ! private void applyDefaultForTab(DocumentCommand command, int lineContentsToCursorLen) { ! IIndentPrefs prefs = getIndentPrefs(); ! if(prefs.getUseSpaces()){ ! int tabWidth = getIndentPrefs().getTabWidth(); ! ! int mod = (lineContentsToCursorLen+tabWidth) % tabWidth; ! command.text = DocUtils.createSpaceString(tabWidth-mod); ! }else{ ! //do nothing (a tab is already a tab) ! } ! ! } /** --- 575,590 ---- * @param lineContentsToCursorLen the current cursor position at the current line */ ! private void applyDefaultForTab(DocumentCommand command, int lineContentsToCursorLen) { ! IIndentPrefs prefs = getIndentPrefs(); ! if(prefs.getUseSpaces()){ ! int tabWidth = getIndentPrefs().getTabWidth(); ! ! int mod = (lineContentsToCursorLen+tabWidth) % tabWidth; ! command.text = DocUtils.createSpaceString(tabWidth-mod); ! }else{ ! //do nothing (a tab is already a tab) ! } ! ! } /** *************** *** 637,641 **** */ public Tuple<String, Integer> autoDedentElif(IDocument document, DocumentCommand command) throws BadLocationException { ! return autoDedentAfterColon(document, command, "elif", PySelection.TOKENS_BEFORE_ELSE); } --- 637,641 ---- */ public Tuple<String, Integer> autoDedentElif(IDocument document, DocumentCommand command) throws BadLocationException { ! return autoDedentAfterColon(document, command, "elif", PySelection.TOKENS_BEFORE_ELSE); } *************** *** 768,783 **** try{ ! char peer = DocUtils.getPeer(c); ! ! FastStringBuffer doc = new FastStringBuffer(document.get(), 2); ! //it is not enough just counting the chars, we have to ignore those that are within comments or literals. ! ParsingUtils.removeCommentsWhitespacesAndLiterals(doc); ! int chars = PyAction.countChars(c, doc); ! int peers = PyAction.countChars(peer, doc); ! ! boolean skipChar = chars == peers; ! return skipChar; }catch(NoPeerAvailableException e){ ! return false; } } --- 768,783 ---- try{ ! char peer = DocUtils.getPeer(c); ! ! FastStringBuffer doc = new FastStringBuffer(document.get(), 2); ! //it is not enough just counting the chars, we have to ignore those that are within comments or literals. ! ParsingUtils.removeCommentsWhitespacesAndLiterals(doc); ! int chars = PyAction.countChars(c, doc); ! int peers = PyAction.countChars(peer, doc); ! ! boolean skipChar = chars == peers; ! return skipChar; }catch(NoPeerAvailableException e){ ! return false; } } *************** *** 812,832 **** /** ! * Return smart indent amount for new line. This should be done for ! * multiline structures like function parameters, tuples, lists and ! * dictionaries. ! * ! * Example: ! * ! * a=foo(1, # ! * ! * We would return the indentation needed to place the caret at the # ! * position. ! * ! * @param document The document ! * @param offset The document offset of the last character on the previous line * @param ps ! * @return indent, or -1 if smart indent could not be determined (fall back to default) * and a boolean indicating if we're inside a parenthesis ! */ public static Tuple<Integer,Boolean> determineSmartIndent(int offset, PySelection ps, IIndentPrefs prefs) throws BadLocationException { --- 812,832 ---- /** ! * Return smart indent amount for new line. This should be done for ! * multiline structures like function parameters, tuples, lists and ! * dictionaries. ! * ! * Example: ! * ! * a=foo(1, # ! * ! * We would return the indentation needed to place the caret at the # ! * position. ! * ! * @param document The document ! * @param offset The document offset of the last character on the previous line * @param ps ! * @return indent, or -1 if smart indent could not be determined (fall back to default) * and a boolean indicating if we're inside a parenthesis ! */ public static Tuple<Integer,Boolean> determineSmartIndent(int offset, PySelection ps, IIndentPrefs prefs) throws BadLocationException { *************** *** 848,887 **** String contents = ""; if(prefs.getIndentToParLevel()){ ! ! ! //now, there's a little catch here, if we are in a line with an opening peer, ! //we have to choose whether to indent to the opening peer or a little further ! //e.g.: if the line is ! //method( self <<- a new line here should indent to the start of the self and not ! //to the opening peer. ! if(openingPeerOffset < offset){ ! String fromParToCursor = document.get(openingPeerOffset, offset-openingPeerOffset); ! if(fromParToCursor.length() > 0 && fromParToCursor.charAt(0) == '('){ ! fromParToCursor = fromParToCursor.substring(1); ! if(!PySelection.containsOnlyWhitespaces(fromParToCursor)){ ! final int firstCharPosition = PySelection.getFirstCharPosition(fromParToCursor); ! openingPeerOffset += firstCharPosition; ! } ! } ! } ! ! ! int openingPeerLineOffset = lineInformationOfOffset.getOffset(); ! len = openingPeerOffset - openingPeerLineOffset; ! contents = document.get(openingPeerLineOffset, len); }else{ ! //ok, we have to get the ! int line = document.getLineOfOffset(openingPeerOffset); ! final String indent = prefs.getIndentationString(); ! contents = PySelection.getLine(document, line); ! contents = PySelection.getIndentationFromLine(contents); ! contents += indent.substring(0, indent.length()-1); //we have to make it -1 (that's what the smartindent expects) ! len = contents.length(); } //add more spaces for each tab for(int i = 0; i<contents.length(); i++){ ! if(contents.charAt(i) == '\t'){ ! len += prefs.getTabWidth() - 1; ! } } return new Tuple<Integer,Boolean>(len, true); --- 848,887 ---- String contents = ""; if(prefs.getIndentToParLevel()){ ! ! ! //now, there's a little catch here, if we are in a line with an opening peer, ! //we have to choose whether to indent to the opening peer or a little further ! //e.g.: if the line is ! //method( self <<- a new line here should indent to the start of the self and not ! //to the opening peer. ! if(openingPeerOffset < offset){ ! String fromParToCursor = document.get(openingPeerOffset, offset-openingPeerOffset); ! if(fromParToCursor.length() > 0 && fromParToCursor.charAt(0) == '('){ ! fromParToCursor = fromParToCursor.substring(1); ! if(!PySelection.containsOnlyWhitespaces(fromParToCursor)){ ! final int firstCharPosition = PySelection.getFirstCharPosition(fromParToCursor); ! openingPeerOffset += firstCharPosition; ! } ! } ! } ! ! ! int openingPeerLineOffset = lineInformationOfOffset.getOffset(); ! len = openingPeerOffset - openingPeerLineOffset; ! contents = document.get(openingPeerLineOffset, len); }else{ ! //ok, we have to get the ! int line = document.getLineOfOffset(openingPeerOffset); ! final String indent = prefs.getIndentationString(); ! contents = PySelection.getLine(document, line); ! contents = PySelection.getIndentationFromLine(contents); ! contents += indent.substring(0, indent.length()-1); //we have to make it -1 (that's what the smartindent expects) ! len = contents.length(); } //add more spaces for each tab for(int i = 0; i<contents.length(); i++){ ! if(contents.charAt(i) == '\t'){ ! len += prefs.getTabWidth() - 1; ! } } return new Tuple<Integer,Boolean>(len, true); Index: AbstractIndentPrefs.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/autoedit/AbstractIndentPrefs.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** AbstractIndentPrefs.java 28 Jul 2008 15:53:31 -0000 1.6 --- AbstractIndentPrefs.java 28 Sep 2008 12:45:48 -0000 1.7 *************** *** 43,48 **** * Converts spaces to tabs or vice-versa depending on the user preferences */ ! public void convertToStd(IDocument document, DocumentCommand command){ ! try { if (getUseSpaces()) { command.text = convertTabsToSpaces(document, command.length, command.text, command.offset, getIndentationString()); --- 43,48 ---- * Converts spaces to tabs or vice-versa depending on the user preferences */ ! public void convertToStd(IDocument document, DocumentCommand command){ ! try { if (getUseSpaces()) { command.text = convertTabsToSpaces(document, command.length, command.text, command.offset, getIndentationString()); *************** *** 56,168 **** } ! } - - - //------------------------------------------------------------- UTILS ! /** ! * Replaces tabs if needed by ident string or just a space depending of the ! * tab location ! * ! */ ! private String convertTabsToSpaces( ! IDocument document, int length, String text, int offset, ! String indentString) throws BadLocationException ! { ! // only interresting if it contains a tab (also if it is a tab only) ! if (text.indexOf("\t") != -1) { ! // get some text infos ! ! if (text.equals("\t")) { ! //only a single tab? ! deleteWhitespaceAfter(document, offset); ! text = indentString; ! ! } else { ! // contains a char (pasted text) ! byte[] byteLine = text.getBytes(); ! FastStringBuffer newText = new FastStringBuffer(); ! for (int count = 0; count < byteLine.length; count++) { ! if (byteLine[count] == '\t'){ ! newText.append(indentString); ! ! } else { // if it is not a tab add the char ! newText.append((char) byteLine[count]); ! } ! } ! text = newText.toString(); ! } ! } ! return text; ! } ! ! /** ! * Converts spaces to strings. Useful when pasting ! */ ! private String convertSpacesToTabs(IDocument document, int length, ! String text, int offset, String indentString) ! throws BadLocationException ! { ! String spaceStr = DocUtils.createSpaceString(getTabWidth()); ! while(text.startsWith(spaceStr)){ ! text = text.replaceAll(spaceStr, "\t"); ! } return text; ! } ! /** ! * When hitting TAB, delete the whitespace after the cursor in the line ! */ ! private void deleteWhitespaceAfter(IDocument document, int offset) ! throws BadLocationException { ! if (offset < document.getLength() && !endsWithNewline(document, document.get(offset, 1))) { ! ! int lineLength = document.getLineInformationOfOffset(offset).getLength(); ! int lineStart = document.getLineInformationOfOffset(offset).getOffset(); ! String textAfter = document.get(offset, (lineStart + lineLength) - offset); ! ! if (textAfter.length() > 0 ! && isWhitespace(textAfter)) { ! document.replace(offset, textAfter.length(), DocUtils.EMPTY_STRING); ! } ! } ! } ! /** ! * Checks if the string is solely composed of spaces ! * ! * @param s the string analyzed ! * @return true if it's only composed of spaces and false otherwise. ! */ ! private boolean isWhitespace(String s) { ! int len = s.length(); ! ! //it's done backwards because the chance of finding a non-whitespace char is higher at the end of the string ! //than at the beggining ! for (int i = len - 1; i > -1 ; i--){ ! if (!Character.isWhitespace(s.charAt(i))){ ! return false; ! } ! } ! return true; ! } ! ! /** ! * True if text ends with a newline delimiter ! */ ! public static boolean endsWithNewline(IDocument document, String text) { ! String[] newlines = document.getLegalLineDelimiters(); ! boolean ends = false; ! for (int i = 0; i < newlines.length; i++) { ! String delimiter = newlines[i]; ! if (text.indexOf(delimiter) != -1) ! ends = true; ! } ! return ends; ! } } --- 56,168 ---- } ! } ! ! //------------------------------------------------------------- UTILS ! ! /** ! * Replaces tabs if needed by ident string or just a space depending of the ! * tab location ! * ! */ ! private String convertTabsToSpaces( ! IDocument document, int length, String text, int offset, ! String indentString) throws BadLocationException ! { ! // only interresting if it contains a tab (also if it is a tab only) ! if (text.indexOf("\t") != -1) { ! // get some text infos ! ! if (text.equals("\t")) { ! //only a single tab? ! deleteWhitespaceAfter(document, offset); ! text = indentString; ! ! } else { ! // contains a char (pasted text) ! byte[] byteLine = text.getBytes(); ! FastStringBuffer newText = new FastStringBuffer(); ! for (int count = 0; count < byteLine.length; count++) { ! if (byteLine[count] == '\t'){ ! newText.append(indentString); ! ! } else { // if it is not a tab add the char ! newText.append((char) byteLine[count]); ! } ! } ! text = newText.toString(); ! } ! } return text; ! } ! ! /** ! * Converts spaces to strings. Useful when pasting ! */ ! private String convertSpacesToTabs(IDocument document, int length, ! String text, int offset, String indentString) ! throws BadLocationException ! { ! String spaceStr = DocUtils.createSpaceString(getTabWidth()); ! while(text.startsWith(spaceStr)){ ! text = text.replaceAll(spaceStr, "\t"); ! } ! return text; ! } ! /** ! * When hitting TAB, delete the whitespace after the cursor in the line ! */ ! private void deleteWhitespaceAfter(IDocument document, int offset) ! throws BadLocationException { ! if (offset < document.getLength() && !endsWithNewline(document, document.get(offset, 1))) { ! ! int lineLength = document.getLineInformationOfOffset(offset).getLength(); ! int lineStart = document.getLineInformationOfOffset(offset).getOffset(); ! String textAfter = document.get(offset, (lineStart + lineLength) - offset); ! ! if (textAfter.length() > 0 ! && isWhitespace(textAfter)) { ! document.replace(offset, textAfter.length(), DocUtils.EMPTY_STRING); ! } ! } ! } ! /** ! * Checks if the string is solely composed of spaces ! * ! * @param s the string analyzed ! * @return true if it's only composed of spaces and false otherwise. ! */ ! private boolean isWhitespace(String s) { ! int len = s.length(); ! ! //it's done backwards because the chance of finding a non-whitespace char is higher at the end of the string ! //than at the beggining ! for (int i = len - 1; i > -1 ; i--){ ! if (!Character.isWhitespace(s.charAt(i))){ ! return false; ! } ! } ! return true; ! } ! ! /** ! * True if text ends with a newline delimiter ! */ ! public static boolean endsWithNewline(IDocument document, String text) { ! String[] newlines = document.getLegalLineDelimiters(); ! boolean ends = false; ! for (int i = 0; i < newlines.length; i++) { ! String delimiter = newlines[i]; ! if (text.indexOf(delimiter) != -1) ! ends = true; ! } ! return ends; ! } } Index: IIndentPrefs.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/autoedit/IIndentPrefs.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** IIndentPrefs.java 19 May 2006 13:47:15 -0000 1.9 --- IIndentPrefs.java 28 Sep 2008 12:45:49 -0000 1.10 *************** *** 41,82 **** * @return the indentation string based on the current settings. */ ! public String getIndentationString(); ! /** ! * Given the current settings, convert the current string to tabs or spaces. ! */ ! public void convertToStd(IDocument document, DocumentCommand command); ! ! /** ! * @return whether we should auto-close parentesis ! */ ! public boolean getAutoParentesis(); ! ! /** ! * Get whether or not to do colon detection. ! * @return true iff colon detection is turned on ! */ ! public boolean getAutoColon(); ! ! /** ! * Get whether or not to auto-skip braces insertion ! * @return iff auto-skip braces is ENABLED ! */ ! public boolean getAutoBraces(); ! ! /** ! * Get whether we should auto-write 'import' if we are in a from xxx import fff ! */ ! public boolean getAutoWriteImport(); ! ! /** ! * Get whether we should smart-indent after a '(' ! */ ! public boolean getSmartIndentPar(); ! ! /** ! * Get whether we should add 'self' automatically when declaring method ! */ ! public boolean getAutoAddSelf(); /** --- 41,82 ---- * @return the indentation string based on the current settings. */ ! public String getIndentationString(); ! /** ! * Given the current settings, convert the current string to tabs or spaces. ! */ ! public void convertToStd(IDocument document, DocumentCommand command); ! ! /** ! * @return whether we should auto-close parentesis ! */ ! public boolean getAutoParentesis(); ! ! /** ! * Get whether or not to do colon detection. ! * @return true iff colon detection is turned on ! */ ! public boolean getAutoColon(); ! ! /** ! * Get whether or not to auto-skip braces insertion ! * @return iff auto-skip braces is ENABLED ! */ ! public boolean getAutoBraces(); ! ! /** ! * Get whether we should auto-write 'import' if we are in a from xxx import fff ! */ ! public boolean getAutoWriteImport(); ! ! /** ! * Get whether we should smart-indent after a '(' ! */ ! public boolean getSmartIndentPar(); ! ! /** ! * Get whether we should add 'self' automatically when declaring method ! */ ! public boolean getAutoAddSelf(); /** *************** *** 93,96 **** * Should be called to regenerate the indent string that's in the cache. */ ! public void regenerateIndentString(); } --- 93,96 ---- * Should be called to regenerate the indent string that's in the cache. */ ! public void regenerateIndentString(); } Index: DefaultIndentPrefs.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev/src/org/python/pydev/editor/autoedit/DefaultIndentPrefs.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** DefaultIndentPrefs.java 28 Jul 2008 15:53:31 -0000 1.13 --- DefaultIndentPrefs.java 28 Sep 2008 12:45:49 -0000 1.14 *************** *** 14,18 **** */ public class DefaultIndentPrefs extends AbstractIndentPrefs { ! /** * Cache for indentation string --- 14,18 ---- */ public class DefaultIndentPrefs extends AbstractIndentPrefs { ! /** * Cache for indentation string *************** *** 24,32 **** private int tabWidth; ! private static PyPreferencesCache cache; ! /** ! * Singleton instance for the preferences ! */ private static IIndentPrefs indentPrefs; --- 24,32 ---- private int tabWidth; ! private static PyPreferencesCache cache; ! /** ! * Singleton instance for the preferences ! */ private static IIndentPrefs indentPrefs; *************** *** 40,66 **** return indentPrefs; } ! /** * @return a cache for the preferences. */ ! private PyPreferencesCache getCache(){ ! if(cache == null){ ! cache = new PyPreferencesCache(PydevPlugin.getDefault().getPreferenceStore()); ! } ! return cache; ! } ! ! /** ! * Not singleton (each pyedit may force to use tabs or not). ! */ ! DefaultIndentPrefs(){ ! PyPreferencesCache c = getCache(); ! useSpaces = c.getBoolean(PydevPrefs.SUBSTITUTE_TABS); ! tabWidth = c.getInt(PydevPrefs.TAB_WIDTH, 4); ! } public boolean getUseSpaces() { PyPreferencesCache c = getCache(); ! if(useSpaces != c.getBoolean(PydevPrefs.SUBSTITUTE_TABS)){ useSpaces = c.getBoolean(PydevPrefs.SUBSTITUTE_TABS); regenerateIndentString(); --- 40,66 ---- return indentPrefs; } ! /** * @return a cache for the preferences. */ ! private PyPreferencesCache getCache(){ ! if(cache == null){ ! cache = new PyPreferencesCache(PydevPlugin.getDefault().getPreferenceStore()); ! } ! return cache; ! } ! ! /** ! * Not singleton (each pyedit may force to use tabs or not). ! */ ! DefaultIndentPrefs(){ ! PyPreferencesCache c = getCache(); ! useSpaces = c.getBoolean(PydevPrefs.SUBSTITUTE_TABS); ! tabWidth = c.getInt(PydevPrefs.TAB_WIDTH, 4); ! } public boolean getUseSpaces() { PyPreferencesCache c = getCache(); ! if(useSpaces != c.getBoolean(PydevPrefs.SUBSTITUTE_TABS)){ useSpaces = c.getBoolean(PydevPrefs.SUBSTITUTE_TABS); regenerateIndentString(); *************** *** 91,97 **** public void regenerateIndentString(){ ! PyPreferencesCache c = getCache(); c.clear(PydevPrefs.TAB_WIDTH); ! c.clear(PydevPrefs.SUBSTITUTE_TABS); indentString = super.getIndentationString(); } --- 91,97 ---- public void regenerateIndentString(){ ! PyPreferencesCache c = getCache(); c.clear(PydevPrefs.TAB_WIDTH); ! c.clear(PydevPrefs.SUBSTITUTE_TABS); indentString = super.getIndentationString(); } *************** *** 118,122 **** public boolean getIndentToParLevel() { ! return getCache().getBoolean(PydevPrefs.AUTO_INDENT_TO_PAR_LEVEL); } --- 118,122 ---- public boolean getIndentToParLevel() { ! return getCache().getBoolean(PydevPrefs.AUTO_INDENT_TO_PAR_LEVEL); } *************** *** 134,143 **** public boolean getSmartIndentPar() { ! return getCache().getBoolean(PydevPrefs.SMART_INDENT_PAR); } ! public boolean getAutoAddSelf() { ! return getCache().getBoolean(PydevPrefs.AUTO_ADD_SELF); ! } public boolean getAutoDedentElse() { --- 134,143 ---- public boolean getSmartIndentPar() { ! return getCache().getBoolean(PydevPrefs.SMART_INDENT_PAR); } ! public boolean getAutoAddSelf() { ! return getCache().getBoolean(PydevPrefs.AUTO_ADD_SELF); ! } public boolean getAutoDedentElse() { |