Hi all,
This patch adds auto indentation to the Shell and Editor classes in Py. It
needs some polishing; there is a lot of duplicated code across the Shell and
Editor functions and too many dugging print statements, but I would like to
receive some comments on what I have done so far.
Thanks,
Ben Armston
Index: editor.py
···
===================================================================
RCS file: /pack/cvsroots/wxwidgets/wxWidgets/wxPython/wx/py/editor.py,v
retrieving revision 1.7
diff -u -r1.7 editor.py
--- editor.py 2004/06/14 20:17:31 1.7
+++ editor.py 2005/08/30 20:32:33
@@ -5,6 +5,7 @@
__revision__ = "$Revision: 1.7 $"[11:-2]
import wx
+import re
from buffer import Buffer
import crust
@@ -585,7 +586,28 @@
# Assign handlers for keyboard events.
wx.EVT_CHAR(self.window, self.OnChar)
wx.EVT_KEY_DOWN(self.window, self.OnKeyDown)
+ self.window.Bind(wx.stc.EVT_STC_CHARADDED, self.OnCharAdded, id=self.id)
+ # XXX Later tabwidth and tabChar should be set on a file by file
+ # XXX basis. For existing files, the indentation type should be
+ # XXX determined automatically when the file is opened. If it is
+ # XXX mixed the user should be presented with the option of fixing
+ # XXX it. For new files the user configurable default should be
+ # XXX chosen.
+ self.tabwidth = 4
+ self.tabChar = ' ' * self.tabwidth
+ self.reContainsKeyword = re.compile(r'(\breturn\b)|(\bbreak\b)|'
+ r'(\bpass\b)|(\bcontinue\b)|(\braise\b)')
+ self.reContinuationIndent = re.compile(r'^\s*\S*\s*')
+ eol = self.window.GetEOLMode()
+ if eol == wx.stc.STC_EOL_CR:
+ self.eolMarker = '\r'
+ elif eol == wx.stc.STC_EOL_CRLF:
+ self.eolMarker = '\r\n'
+ else:
+ self.eolMarker = '\n'
+ del eol
+
def _setBuffer(self, buffer, text):
"""Set the editor to a buffer. Private callback called by buffer."""
self.buffer = buffer
@@ -695,6 +717,268 @@
dispatcher.send(signal='FontDefault')
else:
event.Skip()
+
+ def OnCharAdded(self, event):
+ """Character added to stc event handler."""
+
+ key = chr(event.GetKey())
+ if key == '\r':
+ if self.window.GetEOLMode() == wx.stc.STC_EOL_CR:
+ self.__autoIndent()
+ event.Skip()
+ elif key == '\n':
+ self.__autoIndent()
+ event.Skip()
+
+ def __autoIndent(self):
+ """Automatically indent or dedent the line."""
+
+ # The algorithm for indenting lines is as follows:
+ #
+ # Check whether the brackets of the line just left are paired:
+ # * Unmatched open brackets
+ # - Find last open bracket
+ # - Indent new line to one space after last open bracket
+ # * Unmatched closed brackets
+ # - Find first unmatched closed bracket
+ # - Find matching opening bracket
+ # - Concatenate intervening lines
+ # - Start indenting this new line from the begining
+ # * No unmatched brackets
+ # - If line above one just left is a \-continuation line
+ # + remove `\'
+ # + concatenate lines
+ # + restart indenting from begining
+ # - elif line just left is \-continuation line
+ # + indent to start of second word
+ # - elif line ends with `:'
+ # + increase indent level
+ # - elif line contains dedenting keyword (e.g. `return')
+ # + if character prior to keyword is `:'
+ # * pass
+ # + else
+ # * decrease indentation level
+
+ print '----------'
+ prevLineNum = self.window.GetCurrentLine() - 1
+ prevLine = self.window.GetLine(prevLineNum)
+ umb = self.__handleUnmatchedBrackets(prevLine, prevLineNum)
+ if umb[0] == 'opening':
+ print 'AUTO INDENT 1: umb =', umb
+ self.window.AddText(self.tabChar * umb[1] + ' ' * umb[2])
+ else:
+ print 'AUTO INDENT 2: umb =', umb
+ line, startLineNum, endLineNum =
self.__handleBackslashIndent(umb[1], umb[2], umb[3])
+ self.__indentLine(line, startLineNum, endLineNum)
+
+ def __handleUnmatchedBrackets(self, line, startLineNum, endLineNum=-1):
+ """
+ Return information required to indent implied continuation lines.
+
+ Return type depends on type of unmatched bracket found.
+
+ * If are unmatched opening bracket, return ('opening', numtabs, offset)
+ where numtabs and offset point to position one after unmatched
+ bracket.
+ * If there are no unmatched brackets, return
+ ('none', concatenatedLineText, startLineNum, endLineNum), where
+ concatenatedLineText is the resulting concatenated line, startLineNum
+ and endLineNum are the line numbers of the start and end of this line
+ respectively.
+
+ If there are unmatched closing brackets, concatenate line with
+ previous lines until there are unmatched opening brackets or no
+ unmatched brackets and return accordingly.
+ """
+ if endLineNum == -1:
+ endLineNum = startLineNum
+ umbType, umbPos = self.__findUnmatchedBrackets(line, startLineNum)
+ if umbType == 'opening':
+ print 'HNDL UNMATCHED BRACKS 1: umbType =', umbType
+ numtabs = (umbPos + 1) / self.tabwidth
+ offset = (umbPos + 1) % self.tabwidth
+ returnStmnt = 'opening', numtabs, offset
+ elif umbType == 'closing':
+ linePos = self.window.PositionFromLine(startLineNum)
+ print 'HNDL UNMATCHED BRACKS 2: umb (line, pos, char) =', linePos,
umbPos, chr(self.window.GetCharAt(linePos + umbPos))
+ mbPos = self.window.BraceMatch(linePos + umbPos)
+ print 'HNDL UNMATCHED BRACKS 3: mb (pos, char) =', mbPos,
chr(self.window.GetCharAt(mbPos))
+ if mbPos > -1:
+ mbLineNum = self.window.LineFromPosition(mbPos)
+ lines = ''
+ for i in range(mbLineNum, startLineNum):
+ l = self.window.GetLine(i)
+ lines += l
+ lines = lines + line
+ returnStmnt = self.__handleUnmatchedBrackets(lines, mbLineNum,
+ endLineNum)
+ else:
+ # No matching opening bracket found!!!
+ # For now, pretend that the line contains matching brackets.
+ # XXX Fix this -- what should it do?
+ returnStmnt = 'none', line, startLineNum, endLineNum
+ elif umbType == 'none':
+ returnStmnt = 'none', line, startLineNum, endLineNum
+ return returnStmnt
+
+
+ def __findUnmatchedBrackets(self, line, startLineNum):
+ """Search 'line' for type and position of unmatched brackets. Return
(type, position).
+
+ type
+ One of 'opening', 'closing' or 'none'.
+ position
+ For opening brackets, position in string of the last unmatched bracket.
+ For closing brackets, position in string of the first unmatched
bracket.
+ If there are no unmatched brackets, -1.
+ """
+ print 'FND UNMTCHD BRCKTS 1: line =', line
+ lineStartPos = self.window.PositionFromLine(startLineNum)
+ brackets = {'(': [], ')': [], '{': [], '}': [], '[': [], ']': []}
+ for b in brackets.keys():
+ bpos = -1
+ for i in range(line.count(b)):
+ bpos = line.find(b, bpos + 1)
+ if bpos > -1:
+ print 'FND UNMTCHD BRCKTS 2: found bracket',
chr(self.window.GetCharAt(lineStartPos + bpos))
+ if bpos > -1 and self.window.GetStyleAt(lineStartPos + bpos) == \
+ wx.stc.STC_P_OPERATOR:
+ brackets[b].append(bpos)
+ print brackets
+ lastOpenBracket = []
+ firstCloseBracket = []
+ openBrackets = ['(', '{', '[']
+ closeBrackets = [')', '}', ']']
+ for i in range(3):
+ ob = openBrackets[i]
+ cb = closeBrackets[i]
+ numOpenBrackets = len(brackets[ob])
+ numClosedBrackets = len(brackets[cb])
+ if numOpenBrackets > numClosedBrackets:
+ lastOpenBracket.append(brackets[ob][-1-numClosedBrackets])
+ elif numOpenBrackets < numClosedBrackets:
+ firstCloseBracket.append(brackets[cb][-1-numOpenBrackets])
+ if lastOpenBracket:
+ lastOpenBracket.sort()
+ print 'FND UNMTCHD BRCKTS 3: lastOpenBracket', lastOpenBracket
+ return 'opening', lastOpenBracket[-1]
+ if firstCloseBracket:
+ firstCloseBracket.sort()
+ print 'FND UNMTCHD BRCKTS 4: firstCloseBracket', firstCloseBracket
+ return 'closing', firstCloseBracket[0]
+ print 'FND UNMTCHD BRCKTS 5: brackets match'
+ return 'none', -1
+
+
+ def __handleBackslashIndent(self, line, startLineNum, endLineNum):
+ """
+ Return line concatenated with previous \-continuation lines.
+ """
+ # Check if line prior to the one we have just left is a continuation line.
+ prevPrevLine = self.window.GetLine(startLineNum - 1)
+ print 'HNDL BCKSLSH INDNT 1: line=', line
+ print 'HNDL BCKSLSH INDNT 2: prevPrevLine =', prevPrevLine
+ try:
+ lastChar = prevPrevLine[-len(self.eolMarker) - 1]
+ print 'HNDL BCKSLSH INDNT 3: lastCharPrevLine =', lastChar
+ except IndexError:
+ return line, startLineNum, endLineNum
+ else:
+ lastCharPos = self.window.PositionFromLine(startLineNum) -
len(self.eolMarker) - 1
+ print 'HNDL BCKSLSH INDNT 4: lastCharPos =', lastCharPos
+ print 'HNDL BCKSLSH INDNT 5: lastChar = ' +
chr(self.window.GetCharAt(lastCharPos))
+ if lastChar == '\\' and self.window.GetStyleAt(lastCharPos) == \
+ wx.stc.STC_P_DEFAULT:
+ line = prevPrevLine + line
+ return self.__handleBackslashIndent(line, startLineNum - 1,
+ endLineNum)
+ else:
+ return line, startLineNum, endLineNum
+
+
+ def __indentLine(self, line, startLineNum, endLineNum):
+ """Indents the new line.
+ """
+ print 'INDNT LINE 1: line =', line
+ indentLength = self.window.GetLineIndentation(startLineNum)
+ numtabs = indentLength / self.tabwidth
+ offset = indentLength % self.tabwidth
+ print 'INDNT LINE 1.5: numtabs =', numtabs
+ # Check whether the line we have just left is a continuation line.
+ try:
+ lastChar = line[-len(self.eolMarker) - 1]
+ print 'INDNT LINE 2: lastChar =', lastChar
+ except IndexError:
+ pass
+ else:
+ lastCharPos = self.window.GetLineEndPosition(endLineNum) - 1
+ print 'INDNT LINE 3: lastCharPos =', lastCharPos
+ print 'INDNT LINE 4: lastChar =',
chr(self.window.GetCharAt(lastCharPos))
+ print 'INDNT LINE 5: lastCharStyle =',
self.window.GetStyleAt(lastCharPos)
+ if lastChar == '\\' and self.window.GetStyleAt(lastCharPos) == \
+ wx.stc.STC_P_DEFAULT:
+ # XXX The following works well for lines such as
+ # if age == 27 and ... \
+ # but it doesn't work so well for lines such as
+ # var = var1 + var2 + ... + \
+ indent = self.reContinuationIndent.match(line).end()
+ numtabs = indent / self.tabwidth
+ offset = indent % self.tabwidth
+ indent = self.tabChar * numtabs + ' ' * offset
+ self.window.AddText(indent)
+ print 'INDNT LINE 5.4: added', numtabs, 'tabs + offset of', offset
+ return
+
+ # The line we have just left is not a continuation line.
+ # Check to see if it ended with a `:'.
+ lineJustLeft = line.splitlines()[-1]
+ commentPos = -1
+ for i in range(lineJustLeft.count('#')):
+ commentPos = lineJustLeft.find('#', commentPos+1)
+ print "INDT LINE 5.5: '#' found at ", commentPos
+ style =
self.window.GetStyleAt(self.window.PositionFromLine(endLineNum) +
+ commentPos)
+ print "INDT LINE 5.6: style =", style
+ if style == wx.stc.STC_P_COMMENTLINE or style ==
wx.stc.STC_P_COMMENTBLOCK:
+ lineJustLeft = lineJustLeft[:commentPos]
+ break
+ try:
+ lastChar = lineJustLeft.rstrip()[-1]
+ print 'INDNT LINE 6: lastChar.rstrip() =', lastChar
+ except IndexError:
+ pass
+ else:
+ if lastChar == ':':
+ numtabs += 1
+ self.window.AddText(self.tabChar * numtabs)
+ print 'INDNT LINE 6.5: added', numtabs, 'tabs'
+ return
+
+ # The line we have just left doesn't end with `:'.
+ # Check to see if it contains a dedenting keyword, e.g. `return'
+ mo = self.reContainsKeyword.search(line)
+ if mo and
self.window.GetStyleAt(self.window.PositionFromLine(startLineNum) +
+ mo.start()) == wx.stc.STC_P_WORD:
+ print 'INDNT LINE 7: keyword =', mo.group()
+ # Check whether line is similar to 'if x == 0: pass'.
+ justBeforeKeyword = line[:mo.start()].rstrip()
+ try:
+ lastChar = justBeforeKeyword[-1]
+ except IndexError:
+ self.window.AddText(self.tabChar * (numtabs - 1))
+ return
+ else:
+ if lastChar != ':':
+ numtabs -= 1
+ self.window.AddText(self.tabChar * numtabs)
+ print 'INDNT LINE 7.5: added', numtabs, 'tabs'
+ return
+
+ # There is nothing special about the line we have just left. Indent
+ # the new line the same as the previous line.
+ self.window.AddText(self.tabChar * numtabs + ' ' * offset)
+ print 'INDNT LINE 8: added', numtabs, 'tabs + offset of', offset
+
def autoCompleteShow(self, command):
"""Display auto-completion popup list."""
Index: editwindow.py
RCS file: /pack/cvsroots/wxwidgets/wxWidgets/wxPython/wx/py/editwindow.py,v
retrieving revision 1.10
diff -u -r1.10 editwindow.py
--- editwindow.py 2004/03/26 19:26:34 1.10
+++ editwindow.py 2005/08/30 20:32:33
@@ -104,6 +104,8 @@
self.SetViewWhiteSpace(False)
self.SetTabWidth(4)
self.SetUseTabs(False)
+ self.SetBackSpaceUnIndents(True)
+ self.SetTabIndents(True)
# Do we want to automatically pop up command completion options?
self.autoComplete = True
self.autoCompleteIncludeMagic = True
Index: shell.py
RCS file: /pack/cvsroots/wxwidgets/wxWidgets/wxPython/wx/py/shell.py,v
retrieving revision 1.9
diff -u -r1.9 shell.py
--- shell.py 2004/10/15 20:31:23 1.9
+++ shell.py 2005/08/30 20:32:35
@@ -15,6 +15,7 @@
import os
import sys
import time
+import re
from buffer import Buffer
import dispatcher
@@ -236,7 +237,21 @@
# environment. They can override anything they want.
self.execStartupScript(self.interp.startupScript)
wx.CallAfter(self.ScrollToLine, 0)
-
+ # Used for autoindenting
+ self.tabwidth = 4
+ self.tabChar = ' ' * self.tabwidth
+ self.reContainsKeyword = re.compile(r'(\breturn\b)|(\bbreak\b)|'
+ r'(\bpass\b)|(\bcontinue\b)|(\braise\b)')
+ self.reContinuationIndent = re.compile(r'^\s*\S*\s*')
+ eol = self.GetEOLMode()
+ if eol == wx.stc.STC_EOL_CR:
+ self.eolMarker = '\r'
+ elif eol == wx.stc.STC_EOL_CRLF:
+ self.eolMarker = '\r\n'
+ else:
+ self.eolMarker = '\n'
+ del eol
+
def destroy(self):
del self.interp
@@ -732,11 +747,262 @@
self.promptPosEnd = self.GetCurrentPos()
# Keep the undo feature from undoing previous responses.
self.EmptyUndoBuffer()
- # XXX Add some autoindent magic here if more.
if self.more:
- self.write(' '*4) # Temporary hack indentation.
+ self.__autoIndent()
self.EnsureCaretVisible()
self.ScrollToColumn(0)
+
+ def __autoIndent(self):
+ """Automatically indent or dedent the line."""
+
+ # The algorithm for indenting lines is as follows:
+ #
+ # Check whether the brackets of the line just left are paired:
+ # * Unmatched open brackets
+ # - Find last open bracket
+ # - Indent new line to one space after last open bracket
+ # * Unmatched closed brackets
+ # - Find first unmatched closed bracket
+ # - Find matching opening bracket
+ # - Concatenate intervening lines
+ # - Start indenting this new line from the begining
+ # * No unmatched brackets
+ # - If line above one just left is a \-continuation line
+ # + remove `\'
+ # + concatenate lines
+ # + restart indenting from begining
+ # - elif line just left is \-continuation line
+ # + indent to start of second word
+ # - elif line ends with `:'
+ # + increase indent level
+ # - elif line contains dedenting keyword (e.g. `return')
+ # + if character prior to keyword is `:'
+ # * pass
+ # + else
+ # * decrease indentation level
+
+ print '----------'
+ prevLineNum = self.GetCurrentLine() - 1
+ prevLine = self.lstripPrompt(self.GetLine(prevLineNum))
+ umb = self.__handleUnmatchedBrackets(prevLine, prevLineNum)
+ if umb[0] == 'opening':
+ print 'AUTO INDENT 1: umb =', umb
+ self.AddText(self.tabChar * umb[1] + ' ' * umb[2])
+ else:
+ print 'AUTO INDENT 2: umb =', umb
+ line, startLineNum, endLineNum =
self.__handleBackslashIndent(umb[1], umb[2], umb[3])
+ self.__indentLine(line, startLineNum, endLineNum)
+
+ def __handleUnmatchedBrackets(self, line, startLineNum, endLineNum=-1):
+ """
+ Return information required to indent implied continuation lines.
+
+ Return type depends on type of unmatched bracket found.
+
+ * If are unmatched opening bracket, return ('opening', numtabs, offset)
+ where numtabs and offset point to position one after unmatched
+ bracket.
+ * If there are no unmatched brackets, return
+ ('none', concatenatedLineText, startLineNum, endLineNum), where
+ concatenatedLineText is the resulting concatenated line, startLineNum
+ and endLineNum are the line numbers of the start and end of this line
+ respectively.
+
+ If there are unmatched closing brackets, concatenate line with
+ previous lines until there are unmatched opening brackets or no
+ unmatched brackets and return accordingly.
+ """
+ if endLineNum == -1:
+ endLineNum = startLineNum
+ umbType, umbPos = self.__findUnmatchedBrackets(line, startLineNum,
endLineNum)
+ if umbType == 'opening':
+ print 'HNDL UNMATCHED BRACKS 1: umbType =', umbType
+ numtabs = (umbPos + 1) / self.tabwidth
+ offset = (umbPos + 1) % self.tabwidth
+ returnStmnt = 'opening', numtabs, offset
+ elif umbType == 'closing':
+ linePos = self.PositionFromLine(startLineNum)
+ print 'HNDL UNMATCHED BRACKS 2: umb (line, pos, char) =', linePos,
umbPos, chr(self.GetCharAt(linePos + umbPos))
+ mbPos = self.BraceMatch(linePos + umbPos)
+ print 'HNDL UNMATCHED BRACKS 3: mb (pos, char) =', mbPos,
chr(self.GetCharAt(mbPos))
+ if mbPos > -1:
+ mbLineNum = self.LineFromPosition(mbPos)
+ lines = ''
+ for i in range(mbLineNum, startLineNum):
+ l = self.lstripPrompt(self.GetLine(i))
+ lines += l
+ lines = lines + line
+ returnStmnt = self.__handleUnmatchedBrackets(lines, mbLineNum,
+ endLineNum)
+ else:
+ # No matching opening bracket found!!!
+ # For now, pretend that the line contains matching brackets.
+ # XXX Fix this -- what should it do?
+ returnStmnt = 'none', line, startLineNum, endLineNum
+ elif umbType == 'none':
+ returnStmnt = 'none', line, startLineNum, endLineNum
+ return returnStmnt
+
+
+ def __findUnmatchedBrackets(self, line, startLineNum, endLineNum):
+ """Search 'line' for type and position of unmatched brackets. Return
(type, position).
+
+ type
+ One of 'opening', 'closing' or 'none'.
+ position
+ For opening brackets, position in string of the last unmatched bracket.
+ For closing brackets, position in string of the first unmatched
bracket.
+ If there are no unmatched brackets, -1.
+ """
+ print 'FND UNMTCHD BRCKTS 1: line =', line
+ lineStartPos = self.PositionFromLine(startLineNum)
+ brackets = {'(': [], ')': [], '{': [], '}': [], '[': [], ']': []}
+ for b in brackets.keys():
+ bpos = -1
+ for i in range(line.count(b)):
+ bpos = line.find(b, bpos + 1)
+ if bpos > -1:
+ print 'FND UNMTCHD BRCKTS 2: found bracket',
chr(self.GetCharAt(lineStartPos + bpos + len(line[:bpos].splitlines()) * 4 ))
+ if bpos > -1 and self.GetStyleAt(lineStartPos + bpos +
len(line[:bpos].splitlines()) * 4) == \
+ wx.stc.STC_P_OPERATOR:
+ brackets[b].append(bpos)
+ print brackets
+ lastOpenBracket = []
+ firstCloseBracket = []
+ openBrackets = ['(', '{', '[']
+ closeBrackets = [')', '}', ']']
+ for i in range(3):
+ ob = openBrackets[i]
+ cb = closeBrackets[i]
+ numOpenBrackets = len(brackets[ob])
+ numClosedBrackets = len(brackets[cb])
+ if numOpenBrackets > numClosedBrackets:
+ lastOpenBracket.append(brackets[ob][-1-numClosedBrackets])
+ elif numOpenBrackets < numClosedBrackets:
+ firstCloseBracket.append(brackets[cb][-1-numOpenBrackets])
+ if lastOpenBracket:
+ lastOpenBracket.sort()
+ print 'FND UNMTCHD BRCKTS 3: lastOpenBracket', lastOpenBracket
+ return 'opening', lastOpenBracket[-1]
+ if firstCloseBracket:
+ firstCloseBracket.sort()
+ print 'FND UNMTCHD BRCKTS 4: firstCloseBracket', firstCloseBracket
+ numPromptsRemoved = len(line[:firstCloseBracket[0]].splitlines())
+ return 'closing', firstCloseBracket[0] + numPromptsRemoved * 4
+ print 'FND UNMTCHD BRCKTS 5: brackets match'
+ return 'none', -1
+
+
+ def __handleBackslashIndent(self, line, startLineNum, endLineNum):
+ """
+ Return line concatenated with previous \-continuation lines.
+ """
+ # Check if line prior to the one we have just left is a continuation line.
+ prevPrevLine = self.lstripPrompt(self.GetLine(startLineNum - 1))
+ print 'HNDL BCKSLSH INDNT 1: line=', line
+ print 'HNDL BCKSLSH INDNT 2: prevPrevLine =', prevPrevLine
+ try:
+ lastChar = prevPrevLine[-len(self.eolMarker) - 1]
+ print 'HNDL BCKSLSH INDNT 3: lastCharPrevLine =', lastChar
+ except IndexError:
+ return line, startLineNum, endLineNum
+ else:
+ lastCharPos = self.PositionFromLine(startLineNum) -
len(self.eolMarker) - 1
+ print 'HNDL BCKSLSH INDNT 4: lastCharPos =', lastCharPos
+ print 'HNDL BCKSLSH INDNT 5: lastChar = ' +
chr(self.GetCharAt(lastCharPos))
+ if lastChar == '\\' and self.GetStyleAt(lastCharPos) == \
+ wx.stc.STC_P_DEFAULT:
+ line = prevPrevLine + line
+ return self.__handleBackslashIndent(line, startLineNum - 1,
+ endLineNum)
+ else:
+ return line, startLineNum, endLineNum
+
+
+ def __indentLine(self, line, startLineNum, endLineNum):
+ """Indents the new line.
+ """
+ print 'INDNT LINE 1: line =', line
+ indentLength = len(line) - len(line.lstrip())
+ numtabs = indentLength / self.tabwidth
+ offset = indentLength % self.tabwidth
+ print 'INDNT LINE 1.5: numtabs =', numtabs
+ # Check whether the line we have just left is a continuation line.
+ try:
+ lastChar = line[-len(self.eolMarker) - 1]
+ print 'INDNT LINE 2: lastChar =', lastChar
+ except IndexError:
+ pass
+ else:
+ lastCharPos = self.GetLineEndPosition(endLineNum) - 1
+ print 'INDNT LINE 3: lastCharPos =', lastCharPos
+ print 'INDNT LINE 4: lastChar =', chr(self.GetCharAt(lastCharPos))
+ print 'INDNT LINE 5: lastCharStyle =', self.GetStyleAt(lastCharPos)
+ if lastChar == '\\' and self.GetStyleAt(lastCharPos) == \
+ wx.stc.STC_P_DEFAULT:
+ # XXX The following works well for lines such as
+ # if age == 27 and ... \
+ # but it doesn't work so well for lines such as
+ # var = var1 + var2 + ... + \
+ indent = self.reContinuationIndent.match(line).end()
+ numtabs = indent / self.tabwidth
+ offset = indent % self.tabwidth
+ indent = self.tabChar * numtabs + ' ' * offset
+ self.AddText(indent)
+ print 'INDNT LINE 5.4: added', numtabs, 'tabs + offset of', offset
+ return
+
+ # The line we have just left is not a continuation line.
+ # Check to see if it ended with a `:'.
+ lineJustLeft = line.splitlines()[-1]
+ commentPos = -1
+ for i in range(lineJustLeft.count('#')):
+ commentPos = lineJustLeft.find('#', commentPos+1)
+ print "INDT LINE 5.5: '#' found at ", commentPos
+ style = self.GetStyleAt(self.PositionFromLine(endLineNum) +
+ commentPos + 4) # Adjust to take prompt
into account
+ print "INDT LINE 5.6: style =", style
+ if style == wx.stc.STC_P_COMMENTLINE or style ==
wx.stc.STC_P_COMMENTBLOCK:
+ lineJustLeft = lineJustLeft[:commentPos]
+ break
+ try:
+ lastChar = lineJustLeft.rstrip()[-1]
+ print 'INDNT LINE 6: lastChar.rstrip() =', lastChar
+ except IndexError:
+ pass
+ else:
+ if lastChar == ':':
+ numtabs += 1
+ self.AddText(self.tabChar * numtabs)
+ print 'INDNT LINE 6.5: added', numtabs, 'tabs'
+ return
+
+ # The line we have just left doesn't end with `:'.
+ # Check to see if it contains a dedenting keyword, e.g. `return'
+ mo = self.reContainsKeyword.search(line)
+ if mo:
+ numPromptsRemoved = len(line[:mo.start()].splitlines())
+ if self.GetStyleAt(self.PositionFromLine(startLineNum) +
+ mo.start() + numPromptsRemoved * 4) ==
wx.stc.STC_P_WORD:
+ print 'INDNT LINE 7: keyword =', mo.group()
+ # Check whether line is similar to 'if x == 0: pass'.
+ justBeforeKeyword = line[:mo.start()].rstrip()
+ try:
+ lastChar = justBeforeKeyword[-1]
+ except IndexError:
+ self.AddText(self.tabChar * (numtabs - 1))
+ return
+ else:
+ if lastChar != ':':
+ numtabs -= 1
+ self.AddText(self.tabChar * numtabs)
+ print 'INDNT LINE 7.5: added', numtabs, 'tabs'
+ return
+
+ # There is nothing special about the line we have just left. Indent
+ # the new line the same as the previous line.
+ self.AddText(self.tabChar * numtabs + ' ' * offset)
+ print 'INDNT LINE 8: added', numtabs, 'tabs + offset of', offset
def readline(self):
"""Replacement for stdin.readline()."""
----------------------------------------------
This mail sent through http://www.ukonline.net