示例#1
0
    def reindentLine(self, stc, linenum=None, dedent_only=False):
        """Reindent the specified line to the correct level.

        Changes the indentation of the given line by inserting or deleting
        whitespace as required.  This operation is typically bound to the tab
        key, but regardless to the actual keypress to which it is bound is
        *only* called in response to a user keypress.
        
        @param stc: the stc of interest
        @param linenum: the line number, or None to use the current line
        @param dedent_only: flag to indicate that indentation should only be
        removed, not added
        @return: the new cursor position, in case the cursor has moved as a
        result of the indention.
        """
        if linenum is None:
            linenum = stc.GetCurrentLine()
        if linenum == 0:
            # first line is always indented correctly
            return stc.GetCurrentPos()
        
        linestart = stc.PositionFromLine(linenum)

        # actual indention of current line
        indcol = stc.GetLineIndentation(linenum) # columns
        pos = stc.GetCurrentPos()
        indpos = stc.GetLineIndentPosition(linenum) # absolute character position
        col = stc.GetColumn(pos)
        self.dprint("linestart=%d indpos=%d pos=%d col=%d indcol=%d" % (linestart, indpos, pos, col, indcol))

        newind = self.findIndent(stc, linenum)
        if newind is None:
            return pos
        if dedent_only and newind > indcol:
            return pos
            
        # the target to be replaced is the leading indention of the
        # current line
        indstr = stc.GetIndentString(newind)
        self.dprint("linenum=%d indstr='%s'" % (linenum, indstr))
        stc.SetTargetStart(linestart)
        stc.SetTargetEnd(indpos)
        stc.ReplaceTarget(indstr)

        # recalculate cursor position, because it may have moved if it
        # was within the target
        after = stc.GetLineIndentPosition(linenum)
        self.dprint("after: indent=%d cursor=%d" % (after, stc.GetCurrentPos()))
        if pos < linestart:
            return pos
        newpos = pos - indpos + after
        if newpos < linestart:
            # we were in the indent region, but the region was made smaller
            return after
        elif pos < indpos:
            # in the indent region
            return after
        return newpos
示例#2
0
 def electricBackspace(self, stc):
     """Delete all whitespace before the cursor unless in a string or comment
     """
     start, end = stc.GetSelection()
     if start != end:
         stc.ReplaceSelection("")
         return
     pos = stc.GetCurrentPos()
     if pos <= 0:
         return
     s = stc.GetStyleAt(pos - 1)
     if stc.isStyleComment(s) or stc.isStyleString(s):
         stc.CmdKeyExecute(wx.stc.STC_CMD_DELETEBACK)
     else:
         self.dprint("backspace from pos %d" % pos)
         start = pos
         while start > 0:
             c = stc.GetCharAt(start - 1)
             if c == ord(' ') or c == ord('\t') or c == 10 or c == 13:
                 start -= 1
             else:
                 break
         if start < pos:
             stc.SetTargetStart(start)
             stc.SetTargetEnd(pos)
             stc.ReplaceTarget('')
         else:
             stc.CmdKeyExecute(wx.stc.STC_CMD_DELETEBACK)
示例#3
0
 def electricDelete(self, stc):
     """Delete all whitespace after the cursor unless in a string or comment
     """
     start, end = stc.GetSelection()
     if start != end:
         stc.ReplaceSelection("")
         return
     pos = stc.GetCurrentPos()
     s = stc.GetStyleAt(pos)
     if stc.isStyleComment(s) or stc.isStyleString(s):
         stc.CmdKeyExecute(wx.stc.STC_CMD_CLEAR)
     else:
         self.dprint("deleting from pos %d" % pos)
         end = pos
         while end < stc.GetLength():
             c = stc.GetCharAt(end)
             if c == ord(' ') or c == ord('\t') or c == 10 or c == 13:
                 end += 1
             else:
                 break
         if end > pos:
             stc.SetTargetStart(pos)
             stc.SetTargetEnd(end)
             stc.ReplaceTarget('')
         else:
             stc.CmdKeyExecute(wx.stc.STC_CMD_CLEAR)
示例#4
0
    def processReturn(self, stc):
        """Add a newline and indent to the proper tab level.

        Indent to the level of the line above.  This uses the findIndent method
        to determine the proper indentation of the line about to be added,
        inserts the appropriate end-of-line characters, and indents the new
        line to that indentation level.
        
        @param stc: stc of interest
        """
        linesep = stc.getLinesep()
        
        stc.BeginUndoAction()
        # reindent current line (if necessary), then process the return
        #pos = stc.reindentLine()
        
        linenum = stc.GetCurrentLine()
        pos = stc.GetCurrentPos()
        col = stc.GetColumn(pos)
        #linestart = stc.PositionFromLine(linenum)
        #line = stc.GetLine(linenum)[:pos-linestart]
    
        #get info about the current line's indentation
        ind = stc.GetLineIndentation(linenum)

        self.dprint("format = %s col=%d ind = %d" % (repr(linesep), col, ind)) 

        stc.SetTargetStart(pos)
        stc.SetTargetEnd(pos)
        if col <= ind:
            newline = linesep + self.getNewLineIndentString(stc, col, ind)
        elif not pos:
            newline = linesep
        else:
            stc.ReplaceTarget(linesep)
            pos += len(linesep)
            end = min(pos + 1, stc.GetTextLength())
            
            # Scintilla always returns a fold level of zero on the last line,
            # so when trying to indent the last line, must add a newline
            # character.
            if pos == end and self.folding_last_line_bug:
                stc.AddText("\n")
                end = stc.GetTextLength()
            
            # When we insert a new line, the colorization isn't always
            # immediately updated, so we have to force that here before
            # calling findIndent to guarantee that the new line will have the
            # correct fold property set.
            stc.Colourise(stc.PositionFromLine(linenum), end)
            stc.SetTargetStart(pos)
            stc.SetTargetEnd(pos)
            ind = self.findIndent(stc, linenum + 1)
            self.dprint("pos=%d ind=%d fold=%d" % (pos, ind, (stc.GetFoldLevel(linenum+1)&wx.stc.STC_FOLDLEVELNUMBERMASK) - wx.stc.STC_FOLDLEVELBASE))
            newline = stc.GetIndentString(ind)
        stc.ReplaceTarget(newline)
        stc.GotoPos(pos + len(newline))
        stc.EndUndoAction()
示例#5
0
 def electricChar(self, stc, uchar):
     """Reindent the line and insert a newline when special chars are typed.
     
     Like emacs, a semicolon or curly brace causes the line to be reindented
     and the next line to be indented to the correct column.
     
     @param stc: stc instance
     
     @param uchar: unicode character that was just typed by the user (note
     that it hasn't been inserted into the document yet.)
     
     @return: True if this method handled the character and the text
     was modified; False if the calling event handler should handle the
     character.
     """
     implicit_return = True
     
     if uchar == u';' or uchar == u':' or uchar == '{' or uchar == '}':
         pos = stc.GetCurrentPos()
         s = stc.GetStyleAt(pos)
         if not stc.isStyleComment(s) and not stc.isStyleString(s):
             if uchar == u':':
                 # FIXME: currently only process the : if the current
                 # line is a case statement.  Emacs also indents labels
                 # and namespace operators with a :: by checking if the
                 # last character on the previous line is a : and if so
                 # collapses the current line with the previous line and
                 # reindents the new line
                 linenum = stc.GetCurrentLine()
                 line = self.getCodeChars(stc, linenum, pos) + ":"
                 if not self.reCase.match(line) and not self.reClassAttrScope.match(line):
                     c, prev = self.getLastNonWhitespaceChar(stc, pos)
                     if c == u':':
                         # Found previous ':', so make it a double colon
                         stc.SetSelection(prev + 1, pos)
                         #dprint("selection: %d - %d" % (prev + 1, pos))
                     implicit_return = False
             elif uchar == u';':
                 # Don't process the semicolon if we're in the middle of an
                 # open statement
                 if self.isInsideStatement(stc, pos):
                     return False
             stc.BeginUndoAction()
             start, end = stc.GetSelection()
             if start == end:
                 stc.AddText(uchar)
             else:
                 stc.ReplaceSelection(uchar)
             
             # Always reindent the line, but only process a return if needed
             self.processTab(stc)
             if implicit_return:
                 self.processReturn(stc)
             
             stc.EndUndoAction()
             return True
     return False
示例#6
0
 def reindentLine(self, stc, linenum=None, dedent_only=False):
     if linenum is None:
         linenum = stc.GetCurrentLine()
     
     pos = stc.GetCurrentPos()
     s = stc.GetStyleAt(pos)
     if stc.isStyleComment(s):
         return self.reindentComment(stc, linenum, dedent_only)
     else:
         return self.reindentSourceLine(stc, linenum, dedent_only)
示例#7
0
 def reindentComment(self, stc, ln, dedent_only):
     cursor = stc.GetCurrentPos()
     fc = stc.PositionFromLine(ln)
     lc = stc.GetLineEndPosition(ln)
     text = stc.GetTextRange(fc, lc)
     count = len(text)
     pos = 0
     while pos < count and text[pos] == ' ':
         pos += 1
     stc.SetTargetStart(fc)
     stc.SetTargetEnd(lc)
     stc.ReplaceTarget(text[pos:count])
     cursor -= pos
     return cursor
示例#8
0
    def OnFind(self, event):
        stc = self.docMgr.GetCurrDoc()
        d = drFindReplaceDialog(self, -1, "Find", stc)

        #d.SetOptions(self.FindOptions)

        if stc.GetSelectionStart() < stc.GetSelectionEnd():
            d.SetFindString(stc.GetSelectedText())
        elif config.prefs.findreplaceundercursor:
            pos = stc.GetCurrentPos()
            d.SetFindString(
                stc.GetTextRange(stc.WordStartPosition(pos, 1),
                                 stc.WordEndPosition(pos, 1)))
        d.Show(True)
示例#9
0
文件: diffedit.py 项目: zendbit/peppy
 def action(self, index=-1, multiplier=1):
     stc = self.mode
     start = stc.GetCurrentPos()
     end = 0
     while True:
         pos = stc.FindText(start, end, "--- ", 0)
         if pos < 0:
             self.dprint("not found")
             break
         if stc.GetColumn(pos) == 0 and pos != start:
             line = stc.LineFromPosition(pos)
             stc.showLine(line)
             break
         start = pos - 1
示例#10
0
 def reindentSourceLine(self, stc, ln, dedent_only):
     cursor = stc.GetCurrentPos()
     fc = stc.PositionFromLine(ln)
     lc = stc.GetLineEndPosition(ln)
     text = stc.GetTextRange(fc, lc)
     #dprint("1234567")
     #dprint(text)
     #col = stc.GetColumn(cursor)
     #dprint(" "*col + "_")
     if len(text) > 5:
         numbers = text[0:5]
         continuation = text[5]
         remainder = text[6:]
     else:
         numbers = text + " "*(5 - len(text))
         continuation = " "
         remainder = ""
     
     newind = self.findIndent(stc, ln) - 6
     if newind < 0:
         newind = 0
     #dprint("newind: %d" % newind)
     
     col = stc.GetColumn(cursor)
     if col < 5:
         cursor = fc + 6 + newind
     elif col > 5:
         before = len(remainder)
         remainder = remainder.lstrip()
         leading_blanks = before - len(remainder)
         #dprint("leading blanks: %d" % leading_blanks)
         if leading_blanks > newind:
             cursor -= leading_blanks - newind
         elif col - 6 <= newind:
             cursor = fc + 6 + newind
     remainder = remainder.lstrip()
     remainder = " "*newind + remainder
     
     numbers = numbers.strip()
     line = "%-5s%s%s" % (numbers, continuation, remainder)
     #dprint("1234567")
     #dprint(line)
     #col = stc.GetColumn(cursor)
     #dprint(" "*col + "_")
     stc.SetTargetStart(fc)
     stc.SetTargetEnd(lc)
     stc.ReplaceTarget(line)
     return cursor
示例#11
0
 def electricChar(self, stc, uchar):
     i = ord(uchar)
     if i >= ord('0') and i <= ord('9'):
         pos = stc.GetCurrentPos()
         s = stc.GetStyleAt(pos)
         col = stc.GetColumn(pos)
         if not stc.isStyleComment(s) and col < 5:
             ln = stc.LineFromPosition(pos)
             fc = stc.PositionFromLine(ln)
             lc = stc.GetLineEndPosition(ln)
             text = stc.GetTextRange(fc, lc)
             #dprint("pos=%d col=%d ln=%d fc=%d lc=%d len=%d" % (pos, col, ln, fc, lc, len(text)))
             #dprint("1234567")
             #dprint(text)
             if len(text) > 5:
                 numbers = text[0:5]
                 continuation = text[5]
                 remainder = text[6:]
             else:
                 numbers = text + " "*(5 - len(text))
                 continuation = " "
                 remainder = ""
             numbers = numbers[0:col] + uchar + numbers[col:]
             before = len(numbers)
             numbers = numbers.lstrip()
             if before > len(numbers):
                 col -= before - len(numbers)
             numbers = numbers.strip()
             #dprint("pos=%d col=%d ln=%d fc=%d lc=%d len=%d" % (pos, col, ln, fc, lc, len(text)))
             line = "%-5s%s%s" % (numbers, continuation, remainder)
             #dprint("1234567")
             #dprint(line)
             stc.SetTargetStart(fc)
             stc.SetTargetEnd(lc)
             stc.ReplaceTarget(line)
             stc.GotoPos(fc + col + 1)
             return True
     return False
示例#12
0
 def electricChar(self, stc, uchar):
     """Reindent the line and insert a newline when special chars are typed.
     
     For python mode, a colon should reindent the line (for example, after
     an else statement, it should dedent it one level)
     """
     if uchar == u':':
         pos = stc.GetCurrentPos()
         s = stc.GetStyleAt(pos)
         if stc.isStyleComment(s) or stc.isStyleString(s):
             # These will report true if the cursor is before the first
             # character of a comment or string, meaning that:
             #
             #    else#blah
             #
             # where the cursor is between the 'e' and the '#' will fail.
             # So, we have to check for this as a special case and allow it
             if pos > 0:
                 s = stc.GetStyleAt(pos - 1)
                 allow = not stc.isStyleComment(
                     s) and not stc.isStyleString(s)
             else:
                 allow = False
         else:
             allow = True
         if allow:
             stc.BeginUndoAction()
             start, end = stc.GetSelection()
             if start == end:
                 stc.AddText(uchar)
             else:
                 stc.ReplaceSelection(uchar)
             self.reindentLine(stc, dedent_only=True)
             stc.EndUndoAction()
             return True
     return False
示例#13
0
 def reindentLine(self, stc, linenum=None, dedent_only=False):
     """No-op that doesn't change the current indent level."""
     return stc.GetCurrentPos()