コード例 #1
0
 def _on_key_pressed(self, event):
     """
     Override key press to select the current scope if the user wants
     to deleted a folded scope (without selecting it).
     """
     delete_request = event.key() in [Qt.Key_Backspace, Qt.Key_Delete]
     if event.text() or delete_request:
         cursor = self.editor.textCursor()
         if cursor.hasSelection():
             # change selection to encompass the whole scope.
             positions_to_check = cursor.selectionStart(
             ), cursor.selectionEnd()
         else:
             positions_to_check = (cursor.position(), )
         for pos in positions_to_check:
             block = self.editor.document().findBlock(pos)
             th = TextBlockHelper()
             if th.is_fold_trigger(block) and th.is_collapsed(block):
                 self.toggle_fold_trigger(block)
                 if delete_request and cursor.hasSelection():
                     scope = FoldScope(self.find_parent_scope(block))
                     tc = TextHelper(
                         self.editor).select_lines(*scope.get_range())
                     if tc.selectionStart() > cursor.selectionStart():
                         start = cursor.selectionStart()
                     else:
                         start = tc.selectionStart()
                     if tc.selectionEnd() < cursor.selectionEnd():
                         end = cursor.selectionEnd()
                     else:
                         end = tc.selectionEnd()
                     tc.setPosition(start)
                     tc.setPosition(end, tc.KeepAnchor)
                     self.editor.setTextCursor(tc)
コード例 #2
0
    def find_parent_scope(block):
        """
        Find parent scope, if the block is not a fold trigger.

        :param block: block from which the research will start
        """
        # if we moved up for more than n lines, just give up otherwise this
        # would take too much time.
        limit = 5000
        counter = 0
        original = block
        if not TextBlockHelper.is_fold_trigger(block):
            # search level of next non blank line
            while block.text().strip() == '' and block.isValid():
                block = block.next()
            ref_lvl = TextBlockHelper.get_fold_lvl(block) - 1
            block = original
            while (block.blockNumber() and counter < limit
                   and (not TextBlockHelper.is_fold_trigger(block)
                        or TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
                counter += 1
                block = block.previous()
        if counter < limit:
            return block
        return None
コード例 #3
0
ファイル: folding.py プロジェクト: xiaomailong/spyder
def print_tree(editor, file=sys.stdout, print_blocks=False, return_list=False):
    """
    Prints the editor fold tree to stdout, for debugging purpose.

    :param editor: CodeEditor instance.
    :param file: file handle where the tree will be printed. Default is stdout.
    :param print_blocks: True to print all blocks, False to only print blocks
        that are fold triggers
    """
    output_list = []

    block = editor.document().firstBlock()
    while block.isValid():
        trigger = TextBlockHelper().is_fold_trigger(block)
        trigger_state = TextBlockHelper().is_collapsed(block)
        lvl = TextBlockHelper().get_fold_lvl(block)
        visible = 'V' if block.isVisible() else 'I'
        if trigger:
            trigger = '+' if trigger_state else '-'
            if return_list:
                output_list.append([block.blockNumber() + 1, lvl, visible])
            else:
                print('l%d:%s%s%s' %
                      (block.blockNumber() + 1, lvl, trigger, visible),
                      file=file)
        elif print_blocks:
            if return_list:
                output_list.append([block.blockNumber() + 1, lvl, visible])
            else:
                print('l%d:%s%s' % (block.blockNumber() + 1, lvl, visible),
                      file=file)
        block = block.next()

    if return_list:
        return output_list
コード例 #4
0
 def collapse_all(self):
     """
     Collapses all triggers and makes all blocks with fold level > 0
     invisible.
     """
     self._clear_block_deco()
     block = self.editor.document().firstBlock()
     last = self.editor.document().lastBlock()
     while block.isValid():
         lvl = TextBlockHelper.get_fold_lvl(block)
         trigger = TextBlockHelper.is_fold_trigger(block)
         if trigger:
             if lvl == 0:
                 self._show_previous_blank_lines(block)
             TextBlockHelper.set_collapsed(block, True)
         block.setVisible(lvl == 0)
         if block == last and block.text().strip() == '':
             block.setVisible(True)
             self._show_previous_blank_lines(block)
         block = block.next()
     self._refresh_editor_and_scrollbars()
     tc = self.editor.textCursor()
     tc.movePosition(tc.Start)
     self.editor.setTextCursor(tc)
     self.collapse_all_triggered.emit()
コード例 #5
0
ファイル: folding.py プロジェクト: burrbull/spyder
    def find_parent_scope(block):
        """
        Find parent scope, if the block is not a fold trigger.

        :param block: block from which the research will start
        """
        # if we moved up for more than n lines, just give up otherwise this
        # would take too much time.
        limit = 5000
        counter = 0
        original = block
        if not TextBlockHelper.is_fold_trigger(block):
            # search level of next non blank line
            while block.text().strip() == '' and block.isValid():
                block = block.next()
            ref_lvl = TextBlockHelper.get_fold_lvl(block) - 1
            block = original
            while (block.blockNumber() and counter < limit and
                   (not TextBlockHelper.is_fold_trigger(block) or
                    TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
                counter += 1
                block = block.previous()
        if counter < limit:
            return block
        return None
コード例 #6
0
ファイル: folding.py プロジェクト: burrbull/spyder
 def fold(self):
     """Folds the region."""
     start, end = self.get_range()
     TextBlockHelper.set_collapsed(self._trigger, True)
     block = self._trigger.next()
     while block.blockNumber() <= end and block.isValid():
         block.setVisible(False)
         block = block.next()
コード例 #7
0
 def fold(self):
     """Folds the region."""
     start, end = self.get_range()
     TextBlockHelper.set_collapsed(self._trigger, True)
     block = self._trigger.next()
     while block.blockNumber() <= end and block.isValid():
         block.setVisible(False)
         block = block.next()
コード例 #8
0
 def unfold(self):
     """Unfolds the region."""
     # set all direct child blocks which are not triggers to be visible
     self._trigger.setVisible(True)
     TextBlockHelper.set_collapsed(self._trigger, False)
     for block in self.blocks(ignore_blank_lines=False):
         block.setVisible(True)
         if TextBlockHelper.is_fold_trigger(block):
             TextBlockHelper.set_collapsed(block, False)
コード例 #9
0
ファイル: folding.py プロジェクト: burrbull/spyder
 def unfold(self):
     """Unfolds the region."""
     # set all direct child blocks which are not triggers to be visible
     self._trigger.setVisible(True)
     TextBlockHelper.set_collapsed(self._trigger, False)
     for block in self.blocks(ignore_blank_lines=False):
         block.setVisible(True)
         if TextBlockHelper.is_fold_trigger(block):
             TextBlockHelper.set_collapsed(block, False)
コード例 #10
0
 def expand_all(self):
     """Expands all fold triggers."""
     block = self.editor.document().firstBlock()
     while block.isValid():
         TextBlockHelper.set_collapsed(block, False)
         block.setVisible(True)
         block = block.next()
     self._clear_block_deco()
     self._refresh_editor_and_scrollbars()
     self.expand_all_triggered.emit()
コード例 #11
0
 def child_regions(self):
     """This generator generates the list of direct child regions."""
     start, end = self.get_range()
     block = self._trigger.next()
     ref_lvl = self.scope_level
     while block.blockNumber() <= end and block.isValid():
         lvl = TextBlockHelper.get_fold_lvl(block)
         trigger = TextBlockHelper.is_fold_trigger(block)
         if lvl == ref_lvl and trigger:
             yield FoldScope(block)
         block = block.next()
コード例 #12
0
ファイル: folding.py プロジェクト: burrbull/spyder
 def child_regions(self):
     """This generator generates the list of direct child regions."""
     start, end = self.get_range()
     block = self._trigger.next()
     ref_lvl = self.scope_level
     while block.blockNumber() <= end and block.isValid():
         lvl = TextBlockHelper.get_fold_lvl(block)
         trigger = TextBlockHelper.is_fold_trigger(block)
         if lvl == ref_lvl and trigger:
             yield FoldScope(block)
         block = block.next()
コード例 #13
0
ファイル: folding.py プロジェクト: burrbull/spyder
 def detect_fold_level(self, prev_block, block):
     if prev_block:
         prev_text = prev_block.text().strip()
     else:
         prev_text = ''
     text = block.text().strip()
     if text in self.open_chars:
         return TextBlockHelper.get_fold_lvl(prev_block) + 1
     if prev_text.endswith(self.open_chars) and prev_text not in \
             self.open_chars:
         return TextBlockHelper.get_fold_lvl(prev_block) + 1
     if self.close_chars in prev_text:
         return TextBlockHelper.get_fold_lvl(prev_block) - 1
     return TextBlockHelper.get_fold_lvl(prev_block)
コード例 #14
0
 def detect_fold_level(self, prev_block, block):
     if prev_block:
         prev_text = prev_block.text().strip()
     else:
         prev_text = ''
     text = block.text().strip()
     if text in self.open_chars:
         return TextBlockHelper.get_fold_lvl(prev_block) + 1
     if prev_text.endswith(self.open_chars) and prev_text not in \
             self.open_chars:
         return TextBlockHelper.get_fold_lvl(prev_block) + 1
     if self.close_chars in prev_text:
         return TextBlockHelper.get_fold_lvl(prev_block) - 1
     return TextBlockHelper.get_fold_lvl(prev_block)
コード例 #15
0
 def find_parent_scope(block):
     """Find parent scope, if the block is not a fold trigger."""
     original = block
     if not TextBlockHelper.is_fold_trigger(block):
         # search level of next non blank line
         while block.text().strip() == '' and block.isValid():
             block = block.next()
         ref_lvl = TextBlockHelper.get_fold_lvl(block) - 1
         block = original
         while (block.blockNumber()
                and (not TextBlockHelper.is_fold_trigger(block)
                     or TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
             block = block.previous()
     return block
コード例 #16
0
ファイル: indentationguides.py プロジェクト: impact27/spyder
    def paintEvent(self, event):
        """Override Qt method."""
        painter = QPainter(self)

        color = QColor(self.color)
        color.setAlphaF(.5)
        painter.setPen(color)
        offset = self.editor.document().documentMargin() + \
            self.editor.contentOffset().x()

        for _, line_number, block in self.editor.visible_blocks:

            indentation = TextBlockHelper.get_fold_lvl(block)
            ref_lvl = indentation
            block = block.next()
            last_line = block.blockNumber()
            lvl = TextBlockHelper.get_fold_lvl(block)
            if ref_lvl == lvl:  # for zone set programmatically such as imports
                # in pyqode.python
                ref_lvl -= 1

            while (block.isValid() and
                   TextBlockHelper.get_fold_lvl(block) > ref_lvl):
                last_line = block.blockNumber()
                block = block.next()

            end_of_sub_fold = block
            if last_line:
                block = block.document().findBlockByNumber(last_line)
                while ((block.blockNumber()) and (block.text().strip() == ''
                       or block.text().strip().startswith('#'))):
                    block = block.previous()
                    last_line = block.blockNumber()

            block = self.editor.document().findBlockByNumber(line_number)
            top = int(self.editor.blockBoundingGeometry(block).translated(
                self.editor.contentOffset()).top())
            bottom = top + int(self.editor.blockBoundingRect(block).height())

            indentation = TextBlockHelper.get_fold_lvl(block)

            for i in range(1, indentation):
                if (line_number > last_line and
                        TextBlockHelper.get_fold_lvl(end_of_sub_fold) <= i):
                    continue
                else:
                    x = self.editor.fontMetrics().width(i * self.i_width *
                                                        '9') + offset
                    painter.drawLine(x, top, x, bottom)
コード例 #17
0
ファイル: indentationguides.py プロジェクト: tovogt/spyder
    def paintEvent(self, event):
        """Override Qt method."""
        painter = QPainter(self)

        color = QColor(self.color)
        color.setAlphaF(.5)
        painter.setPen(color)
        offset = self.editor.document().documentMargin() + \
            self.editor.contentOffset().x()

        for _, line_number, block in self.editor.visible_blocks:

            indentation = TextBlockHelper.get_fold_lvl(block)
            ref_lvl = indentation
            block = block.next()
            last_line = block.blockNumber()
            lvl = TextBlockHelper.get_fold_lvl(block)
            if ref_lvl == lvl:  # for zone set programmatically such as imports
                # in pyqode.python
                ref_lvl -= 1

            while (block.isValid() and
                   TextBlockHelper.get_fold_lvl(block) > ref_lvl):
                last_line = block.blockNumber()
                block = block.next()

            end_of_sub_fold = block
            if last_line:
                block = block.document().findBlockByNumber(last_line)
                while ((block.blockNumber()) and (block.text().strip() == ''
                       or block.text().strip().startswith('#'))):
                    block = block.previous()
                    last_line = block.blockNumber()

            block = self.editor.document().findBlockByNumber(line_number)
            top = int(self.editor.blockBoundingGeometry(block).translated(
                self.editor.contentOffset()).top())
            bottom = top + int(self.editor.blockBoundingRect(block).height())

            indentation = TextBlockHelper.get_fold_lvl(block)

            for i in range(1, indentation):
                if (line_number > last_line and
                        TextBlockHelper.get_fold_lvl(end_of_sub_fold) <= i):
                    continue
                else:
                    x = self.editor.fontMetrics().width(i * self.i_width *
                                                        '9') + offset
                    painter.drawLine(x, top, x, bottom)
コード例 #18
0
    def get_range(self, ignore_blank_lines=True):
        """
        Gets the fold region range (start and end line).

        .. note:: Start line do no encompass the trigger line.

        :param ignore_blank_lines: True to ignore blank lines at the end of the
            scope (the method will rewind to find that last meaningful block
            that is part of the fold scope).
        :returns: tuple(int, int)
        """
        ref_lvl = self.trigger_level
        first_line = self._trigger.blockNumber()
        block = self._trigger.next()
        last_line = block.blockNumber()
        lvl = self.scope_level
        if ref_lvl == lvl:  # for zone set programmatically such as imports
            # in pyqode.python
            ref_lvl -= 1
        while (block.isValid()
               and TextBlockHelper.get_fold_lvl(block) > ref_lvl):
            last_line = block.blockNumber()
            block = block.next()

        if ignore_blank_lines and last_line:
            block = block.document().findBlockByNumber(last_line)
            while block.blockNumber() and block.text().strip() == '':
                block = block.previous()
                last_line = block.blockNumber()
        return first_line, last_line
コード例 #19
0
def _get_fold_levels(editor):
    """
    Return a list of all the class/function definition ranges.

    Parameters
    ----------
    editor : :class:`spyder.plugins.editor.widgets.codeeditor.CodeEditor`

    Returns
    -------
    folds : list of :class:`FoldScopeHelper`
        A list of all the class or function defintion fold points.
    """

    folds = []
    parents = []
    prev = None

    for oedata in editor.outlineexplorer_data_list():
        if TextBlockHelper.is_fold_trigger(oedata.block):
            try:
                if oedata.def_type in (OED.CLASS, OED.FUNCTION):
                    fsh = FoldScopeHelper(FoldScope(oedata.block), oedata)

                    # Determine the parents of the item using a stack.
                    _adjust_parent_stack(fsh, prev, parents)

                    # Update the parents of this FoldScopeHelper item
                    fsh.parents = copy.copy(parents)
                    folds.append(fsh)
                    prev = fsh
            except KeyError:
                pass
    return folds
コード例 #20
0
ファイル: folding.py プロジェクト: burrbull/spyder
    def get_range(self, ignore_blank_lines=True):
        """
        Gets the fold region range (start and end line).

        .. note:: Start line do no encompass the trigger line.

        :param ignore_blank_lines: True to ignore blank lines at the end of the
            scope (the method will rewind to find that last meaningful block
            that is part of the fold scope).
        :returns: tuple(int, int)
        """
        ref_lvl = self.trigger_level
        first_line = self._trigger.blockNumber()
        block = self._trigger.next()
        last_line = block.blockNumber()
        lvl = self.scope_level
        if ref_lvl == lvl:  # for zone set programmatically such as imports
                            # in pyqode.python
            ref_lvl -= 1
        while (block.isValid() and
                TextBlockHelper.get_fold_lvl(block) > ref_lvl):
            last_line = block.blockNumber()
            block = block.next()

        if ignore_blank_lines and last_line:
            block = block.document().findBlockByNumber(last_line)
            while block.blockNumber() and block.text().strip() == '':
                block = block.previous()
                last_line = block.blockNumber()
        return first_line, last_line
コード例 #21
0
    def detect_fold_level(self, prev_block, block):
        """
        Detects fold level by looking at the block indentation.

        :param prev_block: previous text block
        :param block: current block to highlight
        """
        text = block.text()
        prev_lvl = TextBlockHelper().get_fold_lvl(prev_block)
        cont_line_regex = (r"(and|or|'|\+|\-|\*|\^|>>|<<|"
                           r"\*|\*{2}|\||\*|//|/|,|\\|\")$")
        # round down to previous indentation guide to ensure contiguous block
        # fold level evolution.
        indent_len = 0
        if (prev_lvl and prev_block is not None
                and not self.editor.is_comment(prev_block)):
            # ignore commented lines (could have arbitary indentation)
            prev_text = prev_block.text()
            indent_len = (len(prev_text) - len(prev_text.lstrip())) // prev_lvl
            # Verify if the previous line ends with a continuation line
            # with a regex
            if (re.search(cont_line_regex, prev_block.text())
                    and indent_len > prev_lvl):
                # Calculate act level of line
                act_lvl = (len(text) - len(text.lstrip())) // indent_len
                if act_lvl == prev_lvl:
                    # If they are the same, don't change the level
                    return prev_lvl
                if prev_lvl > act_lvl:
                    return prev_lvl - 1
                return prev_lvl + 1
        if indent_len == 0:
            indent_len = len(self.editor.indent_chars)
        act_lvl = (len(text) - len(text.lstrip())) // indent_len
        return act_lvl
コード例 #22
0
ファイル: folding.py プロジェクト: burrbull/spyder
    def scope_level(self):
        """
        Returns the fold level of the first block of the foldable scope (
        just after the trigger).

        :return:
        """
        return TextBlockHelper.get_fold_lvl(self._trigger.next())
コード例 #23
0
    def scope_level(self):
        """
        Returns the fold level of the first block of the foldable scope (
        just after the trigger).

        :return:
        """
        return TextBlockHelper.get_fold_lvl(self._trigger.next())
コード例 #24
0
ファイル: folding.py プロジェクト: burrbull/spyder
    def parent(self):
        """
        Return the parent scope.

        :return: FoldScope or None
        """
        if TextBlockHelper.get_fold_lvl(self._trigger) > 0 and \
                self._trigger.blockNumber():
            block = self._trigger.previous()
            ref_lvl = self.trigger_level - 1
            while (block.blockNumber() and
                    (not TextBlockHelper.is_fold_trigger(block) or
                     TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
                block = block.previous()
            try:
                return FoldScope(block)
            except ValueError:
                return None
        return None
コード例 #25
0
    def parent(self):
        """
        Return the parent scope.

        :return: FoldScope or None
        """
        if TextBlockHelper.get_fold_lvl(self._trigger) > 0 and \
                self._trigger.blockNumber():
            block = self._trigger.previous()
            ref_lvl = self.trigger_level - 1
            while (block.blockNumber()
                   and (not TextBlockHelper.is_fold_trigger(block)
                        or TextBlockHelper.get_fold_lvl(block) > ref_lvl)):
                block = block.previous()
            try:
                return FoldScope(block)
            except ValueError:
                return None
        return None
コード例 #26
0
 def paintEvent(self, event):
     # Paints the fold indicators and the possible fold region background
     # on the folding panel.
     super(FoldingPanel, self).paintEvent(event)
     painter = QPainter(self)
     # Draw background over the selected non collapsed fold region
     if self._mouse_over_line is not None:
         block = self.editor.document().findBlockByNumber(
             self._mouse_over_line)
         try:
             self._draw_fold_region_background(block, painter)
         except ValueError:
             pass
     # Draw fold triggers
     for top_position, line_number, block in self.editor.visible_blocks:
         if TextBlockHelper.is_fold_trigger(block):
             collapsed = TextBlockHelper.is_collapsed(block)
             mouse_over = self._mouse_over_line == line_number
             self._draw_fold_indicator(top_position, mouse_over, collapsed,
                                       painter)
             if collapsed:
                 # check if the block already has a decoration, it might
                 # have been folded by the parent editor/document in the
                 # case of cloned editor
                 for deco in self._block_decos:
                     if deco.block == block:
                         # no need to add a deco, just go to the next block
                         break
                 else:
                     self._add_fold_decoration(block, FoldScope(block))
             else:
                 for deco in self._block_decos:
                     # check if the block decoration has been removed, it
                     # might have been unfolded by the parent
                     # editor/document in the case of cloned editor
                     if deco.block == block:
                         # remove it and
                         self._block_decos.remove(deco)
                         self.editor.decorations.remove(deco)
                         del deco
                         break
コード例 #27
0
    def __init__(self, block):
        """
        Create a fold-able region from a fold trigger block.

        :param block: The block **must** be a fold trigger.
        :type block: QTextBlock

        :raise: `ValueError` if the text block is not a fold trigger.
        """
        if not TextBlockHelper.is_fold_trigger(block):
            raise ValueError('Not a fold trigger')
        self._trigger = block
コード例 #28
0
ファイル: folding.py プロジェクト: burrbull/spyder
    def __init__(self, block):
        """
        Create a fold-able region from a fold trigger block.

        :param block: The block **must** be a fold trigger.
        :type block: QTextBlock

        :raise: `ValueError` if the text block is not a fold trigger.
        """
        if not TextBlockHelper.is_fold_trigger(block):
            raise ValueError('Not a fold trigger')
        self._trigger = block
コード例 #29
0
    def _highlight_block(self, block):
        """
        Highlights the current fold scope.

        :param block: Block that starts the current fold scope.
        """
        scope = FoldScope(block)
        if (self._current_scope is None
                or self._current_scope.get_range() != scope.get_range()):
            self._current_scope = scope
            self._clear_scope_decos()
            # highlight current scope with darker or lighter color
            start, end = scope.get_range()
            if not TextBlockHelper.is_collapsed(block):
                self._decorate_block(start, end)
コード例 #30
0
ファイル: indentationguides.py プロジェクト: burrbull/spyder
    def paintEvent(self, event):
        """Override Qt method."""
        painter = QPainter(self)

        color = QColor(self.color)
        color.setAlphaF(.5)
        painter.setPen(color)

        for top, line_number, block in self.editor.visible_blocks:
            bottom = top + int(self.editor.blockBoundingRect(block).height())

            indentation = TextBlockHelper.get_fold_lvl(block)

            for i in range(1, indentation):
                x = self.editor.fontMetrics().width(i * self.i_width * '9')
                painter.drawLine(x, top, x, bottom)
コード例 #31
0
    def toggle_fold_trigger(self, block):
        """
        Toggle a fold trigger block (expand or collapse it).

        :param block: The QTextBlock to expand/collapse
        """
        if not TextBlockHelper.is_fold_trigger(block):
            return
        region = FoldScope(block)
        if region.collapsed:
            region.unfold()
            if self._mouse_over_line is not None:
                self._decorate_block(*region.get_range())
        else:
            region.fold()
            self._clear_scope_decos()
        self._refresh_editor_and_scrollbars()
        self.trigger_state_changed.emit(region._trigger, region.collapsed)
コード例 #32
0
class TestFoldScopeHelper(object):

    test_case = """# -*- coding: utf-8 -*-
def my_add():
    a = 1
    b = 2
    return a + b
"""

    doc = QTextDocument(test_case)
    sh = PythonSH(doc, color_scheme='Spyder')
    sh.fold_detector = IndentFoldDetector()
    sh.rehighlightBlock(doc.firstBlock())
    block = doc.firstBlock()
    block = block.next()
    TextBlockHelper.set_fold_trigger(block, True)
    fold_scope = FoldScope(block)
    oed = block.userData().oedata

    def test_fold_scope_helper(self):
        fsh = cfd.FoldScopeHelper(None, None)
        assert isinstance(fsh, cfd.FoldScopeHelper)

    def test_fold_scope_helper_str(self):
        fsh = cfd.FoldScopeHelper(self.fold_scope, self.oed)
        assert "my_add" in str(fsh)

    def test_fold_scope_helper_str_with_parents(self):
        fsh = cfd.FoldScopeHelper(self.fold_scope, self.oed)
        fsh.parents = ["fake parent list!"]
        assert "parents:" in str(fsh)

    def test_fold_scope_helper_repr(self):
        fsh = cfd.FoldScopeHelper(self.fold_scope, self.oed)
        assert "(at 0x" in repr(fsh)

    def test_fold_scope_helper_properties(self):
        fsh = cfd.FoldScopeHelper(self.fold_scope, self.oed)
        assert fsh.range == (1, 4)
        assert fsh.start_line == 1
        assert fsh.end_line == 4
        assert fsh.name == "my_add"
        assert fsh.line == 1
        assert fsh.def_type == OED.FUNCTION_TOKEN
コード例 #33
0
def _get_fold_levels(editor):
    """
    Return a list of all the class/function definition ranges.

    Parameters
    ----------
    editor : :class:`spyder.plugins.editor.widgets.codeeditor.CodeEditor`

    Returns
    -------
    folds : list of :class:`FoldScopeHelper`
        A list of all the class or function defintion fold points.
    """
    block = editor.document().firstBlock()
    oed = editor.get_outlineexplorer_data()

    folds = []
    parents = []
    prev = None

    while block.isValid():
        if TextBlockHelper.is_fold_trigger(block):
            try:
                data = oed[block.firstLineNumber()]

                if data.def_type in (OED.CLASS, OED.FUNCTION):
                    fsh = FoldScopeHelper(FoldScope(block), data)

                    # Determine the parents of the item using a stack.
                    _adjust_parent_stack(fsh, prev, parents)

                    # Update the parents of this FoldScopeHelper item
                    fsh.parents = copy.copy(parents)
                    folds.append(fsh)
                    prev = fsh
            except KeyError:
                pass

        block = block.next()

    return folds
コード例 #34
0
def _get_fold_levels(editor):
    """
    Return a list of all the class/function definition ranges.

    Parameters
    ----------
    editor : :class:`spyder.plugins.editor.widgets.codeeditor.CodeEditor`

    Returns
    -------
    folds : list of :class:`FoldScopeHelper`
        A list of all the class or function defintion fold points.
    """
    block = editor.document().firstBlock()
    oed = editor.get_outlineexplorer_data()

    folds = []
    parents = []
    prev = None

    while block.isValid():
        if TextBlockHelper.is_fold_trigger(block):
            try:
                data = oed[block.firstLineNumber()]

                if data.def_type in (OED.CLASS, OED.FUNCTION):
                    fsh = FoldScopeHelper(FoldScope(block), data)

                    # Determine the parents of the item using a stack.
                    _adjust_parent_stack(fsh, prev, parents)

                    # Update the parents of this FoldScopeHelper item
                    fsh.parents = copy.copy(parents)
                    folds.append(fsh)
                    prev = fsh
            except KeyError:
                pass

        block = block.next()

    return folds
コード例 #35
0
    def _highlight_caret_scope(self):
        """
        Highlight the scope of the current caret position.

        This get called only if :attr:`
        spyder.widgets.panels.FoldingPanel.highlight_care_scope` is True.
        """
        cursor = self.editor.textCursor()
        block_nbr = cursor.blockNumber()
        if self._block_nbr != block_nbr:
            block = FoldScope.find_parent_scope(
                self.editor.textCursor().block())
            try:
                s = FoldScope(block)
            except ValueError:
                self._clear_scope_decos()
            else:
                self._mouse_over_line = block.blockNumber()
                if TextBlockHelper.is_fold_trigger(block):
                    self._highlight_block(block)
        self._block_nbr = block_nbr
コード例 #36
0
ファイル: folding.py プロジェクト: zhuyuuc/spyder
    def detect_fold_level(self, prev_block, block):
        """
        Detects fold level by looking at the block indentation.

        :param prev_block: previous text block
        :param block: current block to highlight
        """
        text = block.text()
        prev_lvl = TextBlockHelper().get_fold_lvl(prev_block)
        # round down to previous indentation guide to ensure contiguous block
        # fold level evolution.
        indent_len = 0
        if (prev_lvl and prev_block is not None
                and not self.editor.is_comment(prev_block)):
            # ignore commented lines (could have arbitary indentation)
            prev_text = prev_block.text()
            indent_len = (len(prev_text) - len(prev_text.lstrip())) // prev_lvl
        if indent_len == 0:
            indent_len = len(self.editor.indent_chars)

        return (len(text) - len(text.lstrip())) // indent_len
コード例 #37
0
    def mouseMoveEvent(self, event):
        """
        Detect mouser over indicator and highlight the current scope in the
        editor (up and down decoration arround the foldable text when the mouse
        is over an indicator).

        :param event: event
        """
        super(FoldingPanel, self).mouseMoveEvent(event)
        th = TextHelper(self.editor)
        line = th.line_nbr_from_position(event.pos().y())
        if line >= 0:
            block = FoldScope.find_parent_scope(
                self.editor.document().findBlockByNumber(line - 1))
            if TextBlockHelper.is_fold_trigger(block):
                if self._mouse_over_line is None:
                    # mouse enter fold scope
                    QApplication.setOverrideCursor(
                        QCursor(Qt.PointingHandCursor))
                if self._mouse_over_line != block.blockNumber() and \
                        self._mouse_over_line is not None:
                    # fold scope changed, a previous block was highlighter so
                    # we quickly update our highlighting
                    self._mouse_over_line = block.blockNumber()
                    self._highlight_block(block)
                else:
                    # same fold scope, request highlight
                    self._mouse_over_line = block.blockNumber()
                    self._highlight_runner.request_job(self._highlight_block,
                                                       block)
                self._highight_block = block
            else:
                # no fold scope to highlight, cancel any pending requests
                self._highlight_runner.cancel_requests()
                self._mouse_over_line = None
                QApplication.restoreOverrideCursor()
            self.repaint()
コード例 #38
0
ファイル: folding.py プロジェクト: burrbull/spyder
    def process_block(self, current_block, previous_block, text):
        """
        Processes a block and setup its folding info.

        This method call ``detect_fold_level`` and handles most of the tricky
        corner cases so that all you have to do is focus on getting the proper
        fold level foreach meaningful block, skipping the blank ones.

        :param current_block: current block to process
        :param previous_block: previous block
        :param text: current block text
        """
        prev_fold_level = TextBlockHelper.get_fold_lvl(previous_block)
        if text.strip() == '' or self.editor.is_comment(current_block):
            # blank or comment line always have the same level
            # as the previous line
            fold_level = prev_fold_level
        else:
            fold_level = self.detect_fold_level(
                previous_block, current_block)
            if fold_level > self.limit:
                fold_level = self.limit

        prev_fold_level = TextBlockHelper.get_fold_lvl(previous_block)

        if fold_level > prev_fold_level:
            # apply on previous blank or comment lines
            block = current_block.previous()
            while block.isValid() and (block.text().strip() == ''
                                       or self.editor.is_comment(block)):
                TextBlockHelper.set_fold_lvl(block, fold_level)
                block = block.previous()
            TextBlockHelper.set_fold_trigger(
                block, True)

        # update block fold level
        if text.strip() and not self.editor.is_comment(previous_block):
            TextBlockHelper.set_fold_trigger(
                previous_block, fold_level > prev_fold_level)
        TextBlockHelper.set_fold_lvl(current_block, fold_level)

        # user pressed enter at the beginning of a fold trigger line
        # the previous blank or comment line will keep the trigger state
        # and the new line (which actually contains the trigger) must use
        # the prev state (and prev state must then be reset).
        prev = current_block.previous()  # real prev block (may be blank)
        if (prev and prev.isValid() and
            (prev.text().strip() == '' or self.editor.is_comment(prev)) and
                TextBlockHelper.is_fold_trigger(prev)):
            # prev line has the correct trigger fold state
            TextBlockHelper.set_collapsed(
                current_block, TextBlockHelper.is_collapsed(
                    prev))
            # make empty or comment line not a trigger
            TextBlockHelper.set_fold_trigger(prev, False)
            TextBlockHelper.set_collapsed(prev, False)
コード例 #39
0
ファイル: folding.py プロジェクト: burrbull/spyder
 def trigger_level(self):
     """
     Returns the fold level of the block trigger.
     :return:
     """
     return TextBlockHelper.get_fold_lvl(self._trigger)
コード例 #40
0
 def collapsed(self):
     """Returns True if the block is collasped, False if it is expanded."""
     return TextBlockHelper.is_collapsed(self._trigger)
コード例 #41
0
ファイル: folding.py プロジェクト: burrbull/spyder
 def collapsed(self):
     """Returns True if the block is collasped, False if it is expanded."""
     return TextBlockHelper.is_collapsed(self._trigger)
コード例 #42
0
 def trigger_level(self):
     """
     Returns the fold level of the block trigger.
     :return:
     """
     return TextBlockHelper.get_fold_lvl(self._trigger)
コード例 #43
0
ファイル: folding.py プロジェクト: xiaomailong/spyder
    def process_block(self, current_block, previous_block, text):
        """
        Processes a block and setup its folding info.

        This method call ``detect_fold_level`` and handles most of the tricky
        corner cases so that all you have to do is focus on getting the proper
        fold level foreach meaningful block, skipping the blank ones.

        :param current_block: current block to process
        :param previous_block: previous block
        :param text: current block text
        """
        prev_fold_level = TextBlockHelper.get_fold_lvl(previous_block)
        if text.strip() == '' or self.editor.is_comment(current_block):
            # blank or comment line always have the same level
            # as the previous line
            fold_level = prev_fold_level
        else:
            fold_level = self.detect_fold_level(previous_block, current_block)
            if fold_level > self.limit:
                fold_level = self.limit

        prev_fold_level = TextBlockHelper.get_fold_lvl(previous_block)

        if fold_level > prev_fold_level:
            # apply on previous blank or comment lines
            block = current_block.previous()
            while block.isValid() and (block.text().strip() == ''
                                       or self.editor.is_comment(block)):
                TextBlockHelper.set_fold_lvl(block, fold_level)
                block = block.previous()
            TextBlockHelper.set_fold_trigger(block, True)

        # update block fold level
        if text.strip() and not self.editor.is_comment(previous_block):
            TextBlockHelper.set_fold_trigger(previous_block,
                                             fold_level > prev_fold_level)
        TextBlockHelper.set_fold_lvl(current_block, fold_level)

        # user pressed enter at the beginning of a fold trigger line
        # the previous blank or comment line will keep the trigger state
        # and the new line (which actually contains the trigger) must use
        # the prev state (and prev state must then be reset).
        prev = current_block.previous()  # real prev block (may be blank)
        if (prev and prev.isValid()
                and (prev.text().strip() == '' or self.editor.is_comment(prev))
                and TextBlockHelper.is_fold_trigger(prev)):
            # prev line has the correct trigger fold state
            TextBlockHelper.set_collapsed(current_block,
                                          TextBlockHelper.is_collapsed(prev))
            # make empty or comment line not a trigger
            TextBlockHelper.set_fold_trigger(prev, False)
            TextBlockHelper.set_collapsed(prev, False)