def _doIndentHere(self, scimoz, indentStyle, continueComments, style_info):
     # Returns either None or an indent string
     pos = scimoz.positionBefore(scimoz.currentPos)
     startPos = scimoz.currentPos
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != "]":
         return None
     pos -= 1
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != "%":
         return None
     pos -= 1
     curLineNo = scimoz.lineFromPosition(pos)
     lineStartPos = scimoz.positionFromLine(curLineNo)
     delta, numTags = self._getTagDiffDelta(scimoz, lineStartPos, startPos)
     if delta < 0 and numTags == 1 and curLineNo > 0:
         didDedent, dedentAmt = self.dedentThisLine(scimoz, curLineNo,
                                                    startPos)
         if didDedent:
             return dedentAmt
         else:
             return None
     indentWidth = self._getIndentWidthForLine(scimoz, curLineNo)
     indent = scimoz.indent
     newIndentWidth = indentWidth + delta * indent
     if newIndentWidth < 0:
         newIndentWidth = 0
     return scimozindent.makeIndentFromWidth(scimoz, newIndentWidth)
    def _computeIndent(self, scimoz, indentStyle, continueComments, style_info, calculatedData=None):
        """
        If the current line starts with an indenter, count all the keywords
        on the line to decide what the final indent should be.
        """
        if calculatedData is None:
            calculatedData = self.getTokenDataForComputeIndent(scimoz, style_info)
        non_ws_tokens = calculatedData["non_ws_tokens"]
        if len(non_ws_tokens) == 0:
            return
        if non_ws_tokens[0].style not in style_info._keyword_styles:
            return
        if non_ws_tokens[0].text not in self._indenting_statements:
            # Do this only if the line starts with an indenter.
            # Otherwise we want to use the general language-service's indenter
            # to look for braces to match.
            return
        delta = 1
        for tok in non_ws_tokens[1:]:
            if tok.style in style_info._keyword_styles:
                text = tok.text
                if text in self._indenting_statements:
                    delta += 1
                # not an elif, because some keywords are both indenters and dedenters
                # This works because if the first keyword is only counted as an indenter.
                if text in self._keyword_dedenting_keywords:
                    delta -= 1

        tok0 = calculatedData["tokens"][0]
        if tok0.style not in style_info._default_styles:
            currentIndentWidth = 0
        else:
            currentIndentWidth = len(tok0.text.expandtabs(scimoz.tabWidth))
        nextIndentWidth = currentIndentWidth + delta * scimoz.indent
        return scimozindent.makeIndentFromWidth(scimoz, nextIndentWidth)
 def _doIndentHere(self, scimoz, indentStyle, continueComments, style_info):
     pos = scimoz.positionBefore(scimoz.currentPos)
     startPos = scimoz.currentPos
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != ">":
         return None
     pos -= 1
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != "%":
         return None
     curLineNo = scimoz.lineFromPosition(pos)
     lineStartPos = scimoz.positionFromLine(curLineNo)
     delta, numTags = self._getTagDiffDelta(scimoz, lineStartPos, startPos)
     if delta < 0 and numTags == 1 and curLineNo > 0:
         didDedent, dedentAmt = self.dedentThisLine(scimoz, curLineNo, startPos)
         if didDedent:
             return dedentAmt
         else:
             # Since EJS tags end with a ">", keep the
             # HTML auto-indenter out of here.
             return self._getRawIndentForLine(scimoz, curLineNo)
     indentWidth = self._getIndentWidthForLine(scimoz, curLineNo)
     indent = scimoz.indent
     if not indent:
         indent = scimoz.tabWidth # if 0, Scintilla uses tabWidth
     newIndentWidth = indentWidth + delta * indent
     if newIndentWidth < 0:
         newIndentWidth = 0
     #qlog.debug("new indent width: %d", newIndentWidth)
     return scimozindent.makeIndentFromWidth(scimoz, newIndentWidth)
 def _doIndentHere(self, scimoz, indentStyle, continueComments, style_info):
     # Returns either None or an indent string
     pos = scimoz.positionBefore(scimoz.currentPos)
     startPos = scimoz.currentPos
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != "]":
         return None
     pos -= 1
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != "%":
         return None
     pos -= 1
     curLineNo = scimoz.lineFromPosition(pos)
     lineStartPos = scimoz.positionFromLine(curLineNo)
     delta, numTags = self._getTagDiffDelta(scimoz, lineStartPos, startPos)
     if delta < 0 and numTags == 1 and curLineNo > 0:
         didDedent, dedentAmt = self.dedentThisLine(
             scimoz, curLineNo, startPos)
         if didDedent:
             return dedentAmt
         else:
             return None
     indentWidth = self._getIndentWidthForLine(scimoz, curLineNo)
     indent = scimoz.indent
     newIndentWidth = indentWidth + delta * indent
     if newIndentWidth < 0:
         newIndentWidth = 0
     return scimozindent.makeIndentFromWidth(scimoz, newIndentWidth)
 def dedentThisLine(self, scimoz, curLineNo, startPos):
     # Used by UDL template languages
     # Returns a tuple:
     # First item: whether the current line needed to be dedented
     # Second item: the new indentation for the current line
     
     thisLinesIndent = scimoz.getLineIndentation(curLineNo)
     prevLinesIndent = scimoz.getLineIndentation(curLineNo - 1)
     if prevLinesIndent <= thisLinesIndent:
         # We need to dedent this line
         lineStartPos = scimoz.positionFromLine(curLineNo)
         text = scimoz.getTextRange(lineStartPos, startPos)
         m = self._leadingWSRE.match(text)
         if m:
             leadingWS = m.group(1)
             tabFreeLeadingWS = leadingWS.expandtabs(scimoz.tabWidth)
             currWidth = len(tabFreeLeadingWS)
             indent = scimoz.indent
             if not indent:
                 indent = scimoz.tabWidth # if 0, Scintilla uses tabWidth
             targetWidth = currWidth - indent
             if targetWidth < 0:
                 fixedLeadingWS = ""
             else:
                 fixedLeadingWS = scimozindent.makeIndentFromWidth(scimoz, targetWidth)
             scimoz.targetStart = lineStartPos
             scimoz.targetEnd = lineStartPos + len(leadingWS)
             scimoz.replaceTarget(len(fixedLeadingWS), fixedLeadingWS)
             return (True, fixedLeadingWS)
     return (False, None)
    def dedentThisLine(self, scimoz, curLineNo, startPos):
        # Used by UDL template languages
        # Returns a tuple:
        # First item: whether the current line needed to be dedented
        # Second item: the new indentation for the current line

        thisLinesIndent = scimoz.getLineIndentation(curLineNo)
        prevLinesIndent = scimoz.getLineIndentation(curLineNo - 1)
        if prevLinesIndent == thisLinesIndent:
            # We need to dedent this line
            lineStartPos = scimoz.positionFromLine(curLineNo)
            text = scimoz.getTextRange(lineStartPos, startPos)
            m = self._leadingWSRE.match(text)
            if m:
                leadingWS = m.group(1)
                tabFreeLeadingWS = leadingWS.expandtabs(scimoz.tabWidth)
                currWidth = len(tabFreeLeadingWS)
                targetWidth = currWidth - scimoz.indent
                if targetWidth < 0:
                    fixedLeadingWS = ""
                else:
                    fixedLeadingWS = scimozindent.makeIndentFromWidth(
                        scimoz, targetWidth)
                scimoz.targetStart = lineStartPos
                scimoz.targetEnd = lineStartPos + len(leadingWS)
                scimoz.replaceTarget(len(fixedLeadingWS), fixedLeadingWS)
                return (True, fixedLeadingWS)
        return (False, None)
Exemple #7
0
 def _doIndentHere(self, scimoz, indentStyle, continueComments, style_info):
     # Returns either None or an indent string
     pos = scimoz.positionBefore(scimoz.currentPos)
     startPos = scimoz.currentPos
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != ">":
         return None
     pos -= 1
     curLineNo = scimoz.lineFromPosition(pos)
     lineStartPos = scimoz.positionFromLine(curLineNo)
     delta, numTags = self._getTagDiffDelta(scimoz, lineStartPos, startPos)
     if delta < 0 and numTags == 1 and curLineNo > 0:
         didDedent, dedentAmt = self.dedentThisLine(scimoz, curLineNo,
                                                    startPos)
         if didDedent:
             return dedentAmt
         else:
             # Since Mason tags end with a ">", keep the
             # HTML auto-indenter out of here.
             return self._getRawIndentForLine(scimoz, curLineNo)
     indentWidth = self._getIndentWidthForLine(scimoz, curLineNo)
     indent = scimoz.indent
     if not indent:
         indent = scimoz.tabWidth  # if 0, Scintilla uses tabWidth
     newIndentWidth = indentWidth + delta * indent
     if newIndentWidth < 0:
         newIndentWidth = 0
     return scimozindent.makeIndentFromWidth(scimoz, newIndentWidth)
 def _doIndentHere(self, scimoz, indentStyle, continueComments, style_info):
     pos = scimoz.positionBefore(scimoz.currentPos)
     startPos = scimoz.currentPos
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != ">":
         return None
     pos -= 1
     style = scimoz.getStyleAt(pos)
     if style != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getWCharAt(pos) != "%":
         return None
     curLineNo = scimoz.lineFromPosition(pos)
     lineStartPos = scimoz.positionFromLine(curLineNo)
     delta, numTags = self._getTagDiffDelta(scimoz, lineStartPos, startPos)
     if delta < 0 and numTags == 1 and curLineNo > 0:
         didDedent, dedentAmt = self.dedentThisLine(scimoz, curLineNo,
                                                    startPos)
         if didDedent:
             return dedentAmt
         else:
             # Since RHTML tags end with a ">", keep the
             # HTML auto-indenter out of here.
             return self._getRawIndentForLine(scimoz, curLineNo)
     indentWidth = self._getIndentWidthForLine(scimoz, curLineNo)
     indent = scimoz.indent
     newIndentWidth = indentWidth + delta * indent
     if newIndentWidth < 0:
         newIndentWidth = 0
     #qlog.debug("new indent width: %d", newIndentWidth)
     return scimozindent.makeIndentFromWidth(scimoz, newIndentWidth)
 def _computeIndent(self, scimoz, indentStyle, continueComments, style_info, calculatedData):
     if not self._lookingAtReturnFunction(calculatedData["non_ws_tokens"], style_info):
         return None
     tok0 = calculatedData["tokens"][0]
     if tok0.style in style_info._default_styles:
         currWSLen = len(tok0.text.expandtabs(scimoz.tabWidth))
         newWSLen = currWSLen + scimoz.indent
     else:
         newWSLen = scimoz.indent
     return scimozindent.makeIndentFromWidth(scimoz, newWSLen)
Exemple #10
0
 def _computeIndent(self, scimoz, indentStyle, continueComments, style_info,
                    calculatedData):
     if not self._lookingAtReturnFunction(calculatedData['non_ws_tokens'],
                                          style_info):
         return None
     tok0 = calculatedData['tokens'][0]
     if tok0.style in style_info._default_styles:
         currWSLen = len(tok0.text.expandtabs(scimoz.tabWidth))
         newWSLen = currWSLen + scimoz.indent
     else:
         newWSLen = scimoz.indent
     return scimozindent.makeIndentFromWidth(scimoz, newWSLen)
Exemple #11
0
    def _computeIndent(self,
                       scimoz,
                       indentStyle,
                       continueComments,
                       style_info,
                       calculatedData=None):
        """
        If the current line starts with an indenter, count all the keywords
        on the line to decide what the final indent should be.
        """
        if calculatedData is None:
            calculatedData = self.getTokenDataForComputeIndent(
                scimoz, style_info)
        non_ws_tokens = calculatedData['non_ws_tokens']
        if len(non_ws_tokens) == 0:
            return
        if non_ws_tokens[0].style not in style_info._keyword_styles:
            return
        if non_ws_tokens[0].text not in self._indenting_statements:
            # Do this only if the line starts with an indenter.
            # Otherwise we want to use the general language-service's indenter
            # to look for braces to match.
            return
        delta = 1
        for tok in non_ws_tokens[1:]:
            if tok.style in style_info._keyword_styles:
                text = tok.text
                if text in self._indenting_statements:
                    delta += 1
                # not an elif, because some keywords are both indenters and dedenters
                # This works because if the first keyword is only counted as an indenter.
                if text in self._keyword_dedenting_keywords:
                    delta -= 1

        tok0 = calculatedData['tokens'][0]
        if tok0.style not in style_info._default_styles:
            currentIndentWidth = 0
        else:
            currentIndentWidth = len(tok0.text.expandtabs(scimoz.tabWidth))
        indent = scimoz.indent
        if not indent:
            indent = scimoz.tabWidth  # if 0, Scintilla uses tabWidth
        nextIndentWidth = currentIndentWidth + delta * indent
        return scimozindent.makeIndentFromWidth(scimoz, nextIndentWidth)
 def _keyPressedAux(self, ch, scimoz, style_info):
     """
     If we're at the start of a line, we're at the end of a dedenting_statement
     (Consult pref edit.indent.keyword.dedent_on_last_char to determine whether
     to do this on the last char of the keyword, or one after the last char),
     1. get the parent indent
     2. subtract one tabwidth from the current indent
     3. convert the leading white-space to tabs, if necessary
     4. replace the leading white-space with new white-space
     
     5. Assume self._keyword_dedenting_keywords is non-empty.
        Otherwise why would the subclass be using this as a superclass?
     """
     if not self._editAutoIndentStyle.startswith("smart"):
         return
     if ch in ('\n', '\r'):
         return self._checkIndentingCurrentAndPreviousLine(ch, scimoz, style_info)
     currentPos = scimoz.currentPos
     lastCharPos = scimoz.positionBefore(currentPos)
     currLineNo = scimoz.lineFromPosition(lastCharPos)
     if currLineNo == 0:
         # Nothing to do on the first line
         return
     lineStartPos = scimoz.positionFromLine(currLineNo)
     # If we aren't at the end of the line, back out.
     tokens = self._get_line_tokens(scimoz, lineStartPos, lastCharPos, style_info)
     if (len(tokens) not in (2, 3)
         or tokens[0].style not in style_info._default_styles):
         return
     if not self._dedent_on_last_char and len(tokens) == 2:
         return
     word2Style = tokens[1].style
     if len(tokens) == 3:
         if (tokens[2].style not in style_info._default_styles
             or len(tokens[2].text) != 1
             or word2Style not in style_info._keyword_styles):
             return
     elif word2Style not in (style_info._keyword_styles + style_info._variable_styles):
         return
     # If the edit.indent.keyword.dedent_on_last_char pref is on, we can dedent
     # either on the last char on the pref, or one after.
     # If it's off, dedent only one after.
     if tokens[1].text not in self._keyword_dedenting_keywords:
         return
     # Next figure out what this line's indent should be based on the previous line.
     # If it's not the current indent, then the buffer's been changed, and don't
     # bother second-guessing the user.
     scimoz.currentPos = scimoz.getLineEndPosition(currLineNo - 1)
     try:
         expected_indent = self.computeIndent(scimoz, 'keyword', False)
     finally:
         scimoz.currentPos = currentPos
     leadingWS_sp = tokens[0].text.expandtabs(scimoz.tabWidth)
     currWSLen = len(leadingWS_sp)
     expected_indent_sp = expected_indent.expandtabs(scimoz.tabWidth)
     if len(expected_indent_sp) != currWSLen:
         return
     # If the parent line triggered a dedent (expected_indent < that line's
     # leading white-space, then we've already done it.
     #
     if self._thisLineAlreadyDedented(scimoz, currLineNo, expected_indent):
         return
                    
     # Dedent!
     indent = scimoz.indent
     if not indent:
         indent = scimoz.tabWidth # if 0, Scintilla uses tabWidth
     newWSLen = currWSLen - indent
     if newWSLen <= 0:
         ws_reduced = ""
     else:
         ws_reduced = scimozindent.makeIndentFromWidth(scimoz, newWSLen)
     scimoz.targetStart = lineStartPos
     scimoz.targetEnd = lineStartPos + len(tokens[0].text)
     scimoz.beginUndoAction()
     try:
         scimoz.replaceTarget(len(ws_reduced), ws_reduced)
     finally:
         scimoz.endUndoAction()
     return True
 def _checkIndentingCurrentAndPreviousLine(self, ch, scimoz, style_info):
     # This is complicated because the computeIndent was called to calculate
     # the indentation of the current line, so we need to check both this line
     # and the previous line.
     currentPos = scimoz.currentPos
     lastCharPos = scimoz.positionBefore(currentPos)
     currLineNo = scimoz.lineFromPosition(lastCharPos)
     if currLineNo <= 1:
         # Nothing to do on the first line
         return
     lineStartPos = scimoz.positionFromLine(currLineNo)
     # First make sure this line is all blank
     # If we aren't at the end of the line, back out.
     tokens = self._get_line_tokens(scimoz, lineStartPos, lastCharPos, style_info)
     if not tokens:
         # Nothing to do
         return
     if (len(tokens) != 1
         or tokens[0].style not in style_info._default_styles):
         return
     # Now look at the previous line.
     prevLineNo = currLineNo - 1
     prevLineStartPos = scimoz.positionFromLine(prevLineNo)
     prevLineEndPos = scimoz.getLineEndPosition(prevLineNo)
     prevTokens = self._get_line_tokens(scimoz, prevLineStartPos, prevLineEndPos - 1, style_info)
     if len(prevTokens) != 2:
         return
     if prevTokens[0].style not in style_info._default_styles:
         return
     if (prevTokens[1].style not in style_info._keyword_styles
         or prevTokens[1].text not in self._keyword_dedenting_keywords):
         return
     if len(prevTokens[0].text) > len(tokens[0].text):
         return
     # So now figure out what currLine - 2 indentation should have been
     currentPos = scimoz.currentPos
     scimoz.currentPos = scimoz.getLineEndPosition(prevLineNo - 1)
     try:
         expected_indent = self.computeIndent(scimoz, 'keyword', False)
     finally:
         scimoz.currentPos = currentPos
     expected_indent_sp = expected_indent.expandtabs(scimoz.tabWidth)
     leadingWS_sp = prevTokens[0].text.expandtabs(scimoz.tabWidth)
     currWSLen = len(leadingWS_sp)
     
     if len(expected_indent_sp) != currWSLen:
         return
     if self._thisLineAlreadyDedented(scimoz, prevLineNo, expected_indent):
         return
     # Dedent!
     ws_reduced = [None, None]
     indent = scimoz.indent
     if not indent:
         indent = scimoz.tabWidth # if 0, Scintilla uses tabWidth
     newWSLen = currWSLen - indent
     if newWSLen <= 0:
         ws_reduced[0] = ""
         posDelta = len(tokens[0].text)
     else:
         ws_reduced[0] = scimozindent.makeIndentFromWidth(scimoz, newWSLen)
         posDelta = indent
     currWSLen = len(prevTokens[0].text.expandtabs(scimoz.tabWidth))
     newWSLen = currWSLen - indent
     if newWSLen <= 0:
         ws_reduced[1] = ""
         posDelta += len(prevTokens[0].text)
     else:
         ws_reduced[1] = scimozindent.makeIndentFromWidth(scimoz, newWSLen)
         posDelta += indent
     scimoz.beginUndoAction()
     try:
         # Dedent the second line first
         scimoz.targetStart = tokens[0].start_pos
         scimoz.targetEnd = tokens[0].start_pos + len(tokens[0].text)
         scimoz.replaceTarget(len(ws_reduced[0]), ws_reduced[0])
         scimoz.targetStart = prevTokens[0].start_pos
         scimoz.targetEnd = prevTokens[0].start_pos + len(prevTokens[0].text)
         scimoz.replaceTarget(len(ws_reduced[1]), ws_reduced[1])
         scimoz.currentPos = scimoz.anchor = currentPos - posDelta
     finally:
         scimoz.endUndoAction()
     return True
 def insertInternalNewline_Special(self, scimoz, indentStyle, currentPos,
                                   allowExtraNewline, style_info):
     """
     Handle cases where the user presses newline between the end of a start-tag
     and the start of the following end-tag.  Tag names must match.
     Precondition: the current pos is between two characters, so we know
     0 < currentPos < scimoz.length, so we don't have to test for those boundaries.
     """
     if indentStyle is None:
         return None
     if scimoz.getStyleAt(currentPos) != scimoz.SCE_UDL_M_ETAGO:
         return None
     startTagLineNo = self._immediatelyPrecedingStartTagLineNo(scimoz, currentPos)
               
     if startTagLineNo is None:
         # returns (startTag:s, startTag:e, endTag:s, endTag:e)
         startTagInfo = scimozindent.startTagInfo_from_endTagPos(scimoz, currentPos)
         if startTagInfo is None:
             return None
         startTagLineNo = scimoz.lineFromPosition(startTagInfo[0])
         allowExtraNewline = False
         indentStyle = 'plain'  # Don't indent new part
         
     closeIndentWidth = self._getIndentWidthForLine(scimoz, startTagLineNo)
     if indentStyle == 'smart' and self.supportsSmartIndent == 'XML':
         """
         i<foo>|</foo> ==>
         
         i<foo>
         i....<|>
         i</foo>
         
         where "i" denotes the current leading indentation
         """
         intermediateLineIndentWidth = self._getNextLineIndent(scimoz, startTagLineNo)
     else:
         """
         i<foo>|</foo> ==>
         
         i<foo>
         i<|>
         i</foo>
         
         Note that the indentation of inner attr lines are ignored, even in block-indent mode:
         i<foo
         i........attr="val">|</foo> =>
         
         i<foo
         i........attr="val">
         i</foo>
         
         On ctrl-shift-newline, we don't get an extra blank line before the end-tag.
         """
         intermediateLineIndentWidth = closeIndentWidth
     
     currentEOL = eollib.eol2eolStr[eollib.scimozEOL2eol[scimoz.eOLMode]]
     textToInsert = currentEOL + scimozindent.makeIndentFromWidth(scimoz, intermediateLineIndentWidth)
     finalPosn = currentPos + len(textToInsert) #ascii-safe
     if allowExtraNewline:
         textToInsert += currentEOL + scimozindent.makeIndentFromWidth(scimoz, closeIndentWidth)
     scimoz.addText(len(textToInsert), textToInsert) #ascii-safe
     return finalPosn
Exemple #15
0
    def _keyPressedAux(self, ch, scimoz, style_info):
        """
        If we're at the start of a line, we're at the end of a dedenting_statement
        (Consult pref edit.indent.keyword.dedent_on_last_char to determine whether
        to do this on the last char of the keyword, or one after the last char),
        1. get the parent indent
        2. subtract one tabwidth from the current indent
        3. convert the leading white-space to tabs, if necessary
        4. replace the leading white-space with new white-space
        
        5. Assume self._keyword_dedenting_keywords is non-empty.
           Otherwise why would the subclass be using this as a superclass?
        """
        if self._editAutoIndentStyle != "smart":
            return
        if ch in ('\n', '\r'):
            return self._checkIndentingCurrentAndPreviousLine(
                ch, scimoz, style_info)
        currentPos = scimoz.currentPos
        lastCharPos = scimoz.positionBefore(currentPos)
        currLineNo = scimoz.lineFromPosition(lastCharPos)
        if currLineNo == 0:
            # Nothing to do on the first line
            return
        lineStartPos = scimoz.positionFromLine(currLineNo)
        # If we aren't at the end of the line, back out.
        tokens = self._get_line_tokens(scimoz, lineStartPos, lastCharPos,
                                       style_info)
        if (len(tokens) not in (2, 3)
                or tokens[0].style not in style_info._default_styles):
            return
        if not self._dedent_on_last_char and len(tokens) == 2:
            return
        word2Style = tokens[1].style
        if len(tokens) == 3:
            if (tokens[2].style not in style_info._default_styles
                    or len(tokens[2].text) != 1
                    or word2Style not in style_info._keyword_styles):
                return
        elif word2Style not in (style_info._keyword_styles +
                                style_info._variable_styles):
            return
        # If the edit.indent.keyword.dedent_on_last_char pref is on, we can dedent
        # either on the last char on the pref, or one after.
        # If it's off, dedent only one after.
        if tokens[1].text not in self._keyword_dedenting_keywords:
            return
        # Next figure out what this line's indent should be based on the previous line.
        # If it's not the current indent, then the buffer's been changed, and don't
        # bother second-guessing the user.
        scimoz.currentPos = scimoz.getLineEndPosition(currLineNo - 1)
        try:
            expected_indent = self.computeIndent(scimoz, 'keyword', False)
        finally:
            scimoz.currentPos = currentPos
        leadingWS_sp = tokens[0].text.expandtabs(scimoz.tabWidth)
        currWSLen = len(leadingWS_sp)
        expected_indent_sp = expected_indent.expandtabs(scimoz.tabWidth)
        if len(expected_indent_sp) != currWSLen:
            return
        # If the parent line triggered a dedent (expected_indent < that line's
        # leading white-space, then we've already done it.
        #
        if self._thisLineAlreadyDedented(scimoz, currLineNo, expected_indent):
            return

        # Dedent!
        newWSLen = currWSLen - scimoz.indent
        if newWSLen <= 0:
            ws_reduced = ""
        else:
            ws_reduced = scimozindent.makeIndentFromWidth(scimoz, newWSLen)
        scimoz.targetStart = lineStartPos
        scimoz.targetEnd = lineStartPos + len(tokens[0].text)
        scimoz.beginUndoAction()
        try:
            scimoz.replaceTarget(len(ws_reduced), ws_reduced)
        finally:
            scimoz.endUndoAction()
        return True
Exemple #16
0
    def _checkIndentingCurrentAndPreviousLine(self, ch, scimoz, style_info):
        # This is complicated because the computeIndent was called to calculate
        # the indentation of the current line, so we need to check both this line
        # and the previous line.
        currentPos = scimoz.currentPos
        lastCharPos = scimoz.positionBefore(currentPos)
        currLineNo = scimoz.lineFromPosition(lastCharPos)
        if currLineNo <= 1:
            # Nothing to do on the first line
            return
        lineStartPos = scimoz.positionFromLine(currLineNo)
        # First make sure this line is all blank
        # If we aren't at the end of the line, back out.
        tokens = self._get_line_tokens(scimoz, lineStartPos, lastCharPos,
                                       style_info)
        if not tokens:
            # Nothing to do
            return
        if (len(tokens) != 1
                or tokens[0].style not in style_info._default_styles):
            return
        # Now look at the previous line.
        prevLineNo = currLineNo - 1
        prevLineStartPos = scimoz.positionFromLine(prevLineNo)
        prevLineEndPos = scimoz.getLineEndPosition(prevLineNo)
        prevTokens = self._get_line_tokens(scimoz, prevLineStartPos,
                                           prevLineEndPos - 1, style_info)
        if len(prevTokens) != 2:
            return
        if prevTokens[0].style not in style_info._default_styles:
            return
        if (prevTokens[1].style not in style_info._keyword_styles
                or prevTokens[1].text not in self._keyword_dedenting_keywords):
            return
        if len(prevTokens[0].text) > len(tokens[0].text):
            return
        # So now figure out what currLine - 2 indentation should have been
        currentPos = scimoz.currentPos
        scimoz.currentPos = scimoz.getLineEndPosition(prevLineNo - 1)
        try:
            expected_indent = self.computeIndent(scimoz, 'keyword', False)
        finally:
            scimoz.currentPos = currentPos
        expected_indent_sp = expected_indent.expandtabs(scimoz.tabWidth)
        leadingWS_sp = prevTokens[0].text.expandtabs(scimoz.tabWidth)
        currWSLen = len(leadingWS_sp)

        if len(expected_indent_sp) != currWSLen:
            return
        if self._thisLineAlreadyDedented(scimoz, prevLineNo, expected_indent):
            return
        # Dedent!
        ws_reduced = [None, None]
        newWSLen = currWSLen - scimoz.indent
        if newWSLen <= 0:
            ws_reduced[0] = ""
            posDelta = len(tokens[0].text)
        else:
            ws_reduced[0] = scimozindent.makeIndentFromWidth(scimoz, newWSLen)
            posDelta = scimoz.indent
        currWSLen = len(prevTokens[0].text.expandtabs(scimoz.tabWidth))
        newWSLen = currWSLen - scimoz.indent
        if newWSLen <= 0:
            ws_reduced[1] = ""
            posDelta += len(prevTokens[0].text)
        else:
            ws_reduced[1] = scimozindent.makeIndentFromWidth(scimoz, newWSLen)
            posDelta += scimoz.indent
        scimoz.beginUndoAction()
        try:
            # Dedent the second line first
            scimoz.targetStart = tokens[0].start_pos
            scimoz.targetEnd = tokens[0].start_pos + len(tokens[0].text)
            scimoz.replaceTarget(len(ws_reduced[0]), ws_reduced[0])
            scimoz.targetStart = prevTokens[0].start_pos
            scimoz.targetEnd = prevTokens[0].start_pos + len(
                prevTokens[0].text)
            scimoz.replaceTarget(len(ws_reduced[1]), ws_reduced[1])
            scimoz.currentPos = scimoz.anchor = currentPos - posDelta
        finally:
            scimoz.endUndoAction()
        return True
    def insertInternalNewline_Special(self, scimoz, indentStyle, currentPos,
                                      allowExtraNewline, style_info):
        """
        Handle cases where the user presses newline between the end of a start-tag
        and the start of the following end-tag.  Tag names must match.
        Precondition: the current pos is between two characters, so we know
        0 < currentPos < scimoz.length, so we don't have to test for those boundaries.
        """
        if indentStyle is None:
            return None
        if scimoz.getStyleAt(currentPos) != scimoz.SCE_UDL_M_ETAGO:
            return None
        startTagLineNo = self._immediatelyPrecedingStartTagLineNo(
            scimoz, currentPos)

        if startTagLineNo is None:
            # returns (startTag:s, startTag:e, endTag:s, endTag:e)
            startTagInfo = scimozindent.startTagInfo_from_endTagPos(
                scimoz, currentPos)
            if startTagInfo is None:
                return None
            startTagLineNo = scimoz.lineFromPosition(startTagInfo[0])
            allowExtraNewline = False
            indentStyle = 'plain'  # Don't indent new part

        closeIndentWidth = self._getIndentWidthForLine(scimoz, startTagLineNo)
        if indentStyle == 'smart' and self.supportsSmartIndent == 'XML':
            """
            i<foo>|</foo> ==>
            
            i<foo>
            i....<|>
            i</foo>
            
            where "i" denotes the current leading indentation
            """
            intermediateLineIndentWidth = self._getNextLineIndent(
                scimoz, startTagLineNo)
        else:
            """
            i<foo>|</foo> ==>
            
            i<foo>
            i<|>
            i</foo>
            
            Note that the indentation of inner attr lines are ignored, even in block-indent mode:
            i<foo
            i........attr="val">|</foo> =>
            
            i<foo
            i........attr="val">
            i</foo>
            
            On ctrl-shift-newline, we don't get an extra blank line before the end-tag.
            """
            intermediateLineIndentWidth = closeIndentWidth

        currentEOL = eollib.eol2eolStr[eollib.scimozEOL2eol[scimoz.eOLMode]]
        textToInsert = currentEOL + scimozindent.makeIndentFromWidth(
            scimoz, intermediateLineIndentWidth)
        finalPosn = currentPos + len(textToInsert)  #ascii-safe
        if allowExtraNewline:
            textToInsert += currentEOL + scimozindent.makeIndentFromWidth(
                scimoz, closeIndentWidth)
        scimoz.addText(len(textToInsert), textToInsert)  #ascii-safe
        return finalPosn
    def insertInternalNewline_Special(self, scimoz, indentStyle, currentPos,
                                      allowExtraNewline, style_info):
        """
        Split %|% so the %'s are on separate lines, and there's a blank line
        in the middle.
        """
        if indentStyle is None or currentPos < 2:
            return None
        if scimoz.getStyleAt(currentPos) != scimoz.SCE_UDL_TPL_OPERATOR:
            return None
        percentChar = ord("%")
        if scimoz.getCharAt(currentPos) != percentChar:
            return None
        prevPos = currentPos - 1  # ascii
        if scimoz.getStyleAt(prevPos) != scimoz.SCE_UDL_TPL_OPERATOR:
            return None
        if scimoz.getCharAt(prevPos) != percentChar:
            return None
        prev2Pos = prevPos - 1
        if scimoz.getStyleAt(prev2Pos) != scimoz.SCE_UDL_TPL_OPERATOR:
            return None
        if scimoz.getCharAt(prev2Pos) != ord("<"):
            return None
        lineNo = scimoz.lineFromPosition(currentPos)
        closeIndentWidth = self._getIndentWidthForLine(scimoz, lineNo)
        if indentStyle == 'smart':
            """
            i<%|% ==>
            
            i<%
            i....<|>
            i%
            
            where "i" denotes the current leading indentation
            """
            intermediateLineIndentWidth = self._getNextLineIndent(
                scimoz, lineNo)
        else:
            """
            i<%|% ==>
            
            i<%
            i<|>
            i%
            
            Note that the indentation of inner attr lines are ignored, even in block-indent mode:
            i<foo
            i........attr="val">|</foo> =>
            
            i<foo
            i........attr="val">
            i</foo>
            """
            intermediateLineIndentWidth = closeIndentWidth

        currentEOL = eollib.eol2eolStr[eollib.scimozEOL2eol[scimoz.eOLMode]]
        textToInsert = currentEOL + scimozindent.makeIndentFromWidth(
            scimoz, intermediateLineIndentWidth)
        finalPosn = currentPos + len(textToInsert)  #ascii-safe
        if allowExtraNewline:
            textToInsert += currentEOL + scimozindent.makeIndentFromWidth(
                scimoz, closeIndentWidth)
        scimoz.addText(len(textToInsert), textToInsert)  #ascii-safe
        return finalPosn
 def insertInternalNewline_Special(self, scimoz, indentStyle, currentPos,
                                   allowExtraNewline, style_info):
     """
     Split %|% so the %'s are on separate lines, and there's a blank line
     in the middle.
     """
     if indentStyle is None or currentPos < 2:
         return None
     if scimoz.getStyleAt(currentPos) != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     percentChar = ord("%")
     if scimoz.getCharAt(currentPos) != percentChar:
         return None
     prevPos = currentPos - 1 # ascii
     if scimoz.getStyleAt(prevPos) != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getCharAt(prevPos) != percentChar:
         return None
     prev2Pos = prevPos - 1
     if scimoz.getStyleAt(prev2Pos) != scimoz.SCE_UDL_TPL_OPERATOR:
         return None
     if scimoz.getCharAt(prev2Pos) != ord("<"):
         return None        
     lineNo = scimoz.lineFromPosition(currentPos)
     closeIndentWidth = self._getIndentWidthForLine(scimoz, lineNo)
     if indentStyle.startswith('smart'):
         """
         i<%|% ==>
         
         i<%
         i....<|>
         i%
         
         where "i" denotes the current leading indentation
         """
         intermediateLineIndentWidth = self._getNextLineIndent(scimoz, lineNo)
     else:
         """
         i<%|% ==>
         
         i<%
         i<|>
         i%
         
         Note that the indentation of inner attr lines are ignored, even in block-indent mode:
         i<foo
         i........attr="val">|</foo> =>
         
         i<foo
         i........attr="val">
         i</foo>
         """
         intermediateLineIndentWidth = closeIndentWidth
     
     currentEOL = eollib.eol2eolStr[eollib.scimozEOL2eol[scimoz.eOLMode]]
     textToInsert = currentEOL + scimozindent.makeIndentFromWidth(scimoz, intermediateLineIndentWidth)
     finalPosn = currentPos + len(textToInsert) #ascii-safe
     if allowExtraNewline:
         textToInsert += currentEOL + scimozindent.makeIndentFromWidth(scimoz, closeIndentWidth)
     scimoz.addText(len(textToInsert), textToInsert) #ascii-safe
     return finalPosn