示例#1
0
    def _insert_snippet_at_node(self, leaf, snippet, new_node,
                                line, column):
        self.redo_stack = []
        value = leaf.value
        leaf_position = leaf.position
        if len(leaf_position) == 1:
            x, y = leaf_position[0]
            leaf_position = [(x, y), (x, y + 1)]

        leaf_start, leaf_end = leaf_position
        leaf_index = leaf.index_in_parent
        placeholder = snippet.placeholder
        text_tokens = list(placeholder.tokens)
        first_tokens = text_tokens[:leaf_index]
        second_tokens = text_tokens[leaf_index + 1:]
        if leaf_start == (line, column):
            single_token = False
            if len(text_tokens) == 1:
                possible_snippet = new_node.tokens[0]
                single_token = True
                if isinstance(possible_snippet, nodes.SnippetASTNode):
                    # Placeholder replacement
                    first_tokens = (
                        list(possible_snippet.placeholder.tokens) +
                        list(new_node.tokens[1:])
                    )
                    second_tokens = []
                else:
                    first_tokens = list(new_node.tokens)
                    second_tokens = []
            if not single_token:
                if isinstance(new_node, nodes.TextNode):
                    first_tokens += list(new_node.tokens)
                else:
                    first_tokens.append(new_node)
                if not new_node.text().startswith(value):
                    first_tokens.append(leaf)
        elif leaf_end == (line, column):
            first_tokens.append(leaf)
            first_tokens.append(new_node)
        else:
            _, start_pos = leaf_start
            diff = column - start_pos

            first_part = value[:diff]
            second_part = value[diff:]
            first_node = nodes.LeafNode(leaf.name, first_part)
            second_node = nodes.LeafNode(leaf.name, second_part)
            first_tokens.append(first_node)
            first_tokens.append(new_node)
            first_tokens.append(second_node)
        text_tokens = first_tokens + second_tokens
        placeholder.tokens = text_tokens
示例#2
0
 def _remove_selection(self, selection_start, selection_end):
     start_node, _, _ = self._find_node_by_position(*selection_start)
     end_node, _, _ = self._find_node_by_position(*selection_end)
     ancestor = self._find_lowest_common_ancestor(start_node, end_node)
     if ancestor is None:
         self.reset()
         return
     poly = self._region_to_polygon(selection_start, selection_end)
     bboxes = [sum(segment, tuple()) for segment in poly]
     for segment in poly:
         (_, start_column), (_, end_column) = segment
         bbox = sum(segment, tuple())
         nodes_spanned = list(self.index.intersection(bbox))
         current_position = start_column
         for node_id in nodes_spanned:
             _, node = self.node_position[node_id]
             if node.to_delete:
                 continue
             if current_position >= end_column:
                 break
             node_position = node.position
             if isinstance(node, nodes.SnippetASTNode):
                 if len(node_position) == 1:
                     node_position = node_position[0]
                     node_start, node_end = node_position[0]
                     if node_position == segment:
                         node.placeholder.delete()
                         node.placeholder = nodes.TextNode(nodes.LeafNode())
                     elif node_start == current_position:
                         if node_end <= end_column:
                             node.delete()
                             node_parent = node.parent
                             parent_tokens = list(
                                 node_parent.tokens)
                             parent_tokens.pop(node.index_in_parent)
                             node_parent.tokens = parent_tokens
                             snippet_number = node.number
                             diff = 0
                             for num in self.snippets_map:
                                 if num > snippet_number:
                                     snippet = self.snippets_map[num]
                                     snippet.number = snippet_number - diff
                                     diff += 1
             elif isinstance(node, nodes.TextNode):
                 if len(node_position) == 1:
                     (node_start, node_end) = node_position[0][0]
                     if node_start == current_position:
                         if node_end <= end_column:
                             node.delete()
                             current_position = node_end
                             if node.parent is not None:
                                 node_parent = node.parent
                                 if isinstance(node_parent, nodes.TextNode):
                                     parent_tokens = list(
                                         node.parent.tokens)
                                     parent_tokens.pop(node.index_in_parent)
                                     node_parent.tokens = parent_tokens
             elif isinstance(node, nodes.LeafNode):
                 if len(node_position) == 1:
                     leaf_line, leaf_col = node_position[0]
                     node_position = (
                         (leaf_line, leaf_col), (leaf_line, leaf_col + 1))
                 (_, node_start), (_, node_end) = node_position
                 if current_position == node_start:
                     if node_end <= end_column:
                         node_parent = node.parent
                         parent_tokens = list(node_parent.tokens)
                         parent_tokens.pop(node.index_in_parent)
                         node_parent.tokens = parent_tokens
                         current_position = node_end
                     else:
                         diff = end_column - node_end
                         node_value = node.value
                         node.value = node_value[diff:]
                         current_position = node_start + diff
                 elif node_start < current_position:
                     start_diff = current_position - node_start
                     end_diff = end_column - node_end
                     node_value = node.value
                     node.value = (node_value[:start_diff] +
                                   node_value[end_diff:])
                     current_position = (
                         current_position + (end_diff - start_diff))
     self._update_ast()
示例#3
0
    def insert_text(self, text, line, column):
        has_selected_text = self.editor.has_selected_text()
        start, end = self.editor.get_selection_start_end()
        if has_selected_text:
            self._remove_selection(start, end)
            line, column = start
        node, snippet, text_node = self._find_node_by_position(line, column)
        if node is None:
            self.reset()
            return
        tokens = tokenize(text)
        token_nodes = [nodes.LeafNode(t.token, t.value) for t in tokens]
        for token in token_nodes:
            token.compute_position((line, column))
        if node.name == 'EPSILON':
            new_text_node = nodes.TextNode(*token_nodes)
            snippet.placeholder = new_text_node
            return
        position = node.position
        if len(position) == 1:
            x, y = position[0]
            position = ((x, y), (x, y + 1))
        leaf_start, leaf_end = position
        node_index = node.index_in_parent
        text_node_tokens = list(text_node.tokens)

        if (line, column) == leaf_start:
            left_offset = 0
            right_offset = 0
            first_token = token_nodes[0]
            last_token = token_nodes[-1]
            if node_index > 0 and len(text_node_tokens) > 1:
                previous_node = text_node_tokens[node_index - 1]
                if first_token.mark_for_position:
                    if first_token.name in MERGE_ALLOWED:
                        if first_token.name == previous_node.name:
                            left_offset = 1
                            first_token.value = (
                                previous_node.value + first_token.value)
            if last_token.mark_for_position:
                if last_token.name in MERGE_ALLOWED:
                    if last_token.name == node.name:
                        right_offset = 1
                        last_token.value = (
                            last_token.value + node.value)
            text_node_tokens = (
                text_node_tokens[:node_index - left_offset] +
                token_nodes +
                text_node_tokens[node_index + right_offset:]
            )
        elif (line, column) == leaf_end:
            left_offset = -1
            right_offset = 1
            first_token = token_nodes[0]
            last_token = token_nodes[-1]
            if node_index >= 1 and node_index < len(text_node_tokens) - 1:
                next_node = text_node_tokens[node_index + 1]
                if last_token.mark_for_position:
                    if last_token.name in MERGE_ALLOWED:
                        if last_token.name == next_node.name:
                            right_offset = 2
                            last_token.value = (
                                last_token.value + next_node.value)

            if first_token.mark_for_position:
                if first_token.name in MERGE_ALLOWED:
                    if first_token.name == node.name:
                        left_offset = 0
                        first_token.value = (
                            node.value + first_token.value)

            text_node_tokens = (
                text_node_tokens[:node_index - left_offset] +
                token_nodes +
                text_node_tokens[node_index + right_offset:]
            )
        else:
            _, start_pos = leaf_start
            diff = column - start_pos
            value = node.value
            first_tokens = text_node_tokens[:node_index]
            second_tokens = text_node_tokens[node_index + 1:]
            first_part = value[:diff]
            second_part = value[diff:]
            first_token = token_nodes[0]
            last_token = token_nodes[-1]
            left_merge = False
            if first_token.mark_for_position:
                if first_token.name in MERGE_ALLOWED:
                    if first_token == node.name:
                        left_merge = True
                        first_token.value = first_part + first_token.value
            if not left_merge:
                first_tokens.append(nodes.LeafNode(node.name, first_part))

            right_merge = False
            if last_token.mark_for_position:
                if last_token.name in MERGE_ALLOWED:
                    if last_token == node.name:
                        right_merge = True
                        last_token.value = last_token.value + second_part
            if not right_merge:
                second_tokens.insert(0, nodes.LeafNode(node.name, second_part))

            text_node_tokens = first_tokens + token_nodes + second_tokens

        text_node.tokens = text_node_tokens
示例#4
0
    def _delete_token(self, node, text_node, line, column):
        node_position = node.position
        text_node_tokens = list(text_node.tokens)
        node_index = node.index_in_parent
        if len(node_position) == 1:
            # Single character removal
            if node_index > 0 and node_index + 1 < len(text_node_tokens):
                left_node = text_node_tokens[node_index - 1]
                right_node = text_node_tokens[node_index + 1]
                offset = 1
                if left_node.mark_for_position:
                    if not isinstance(left_node, nodes.LeafNode):
                        self.reset()
                        return
                    if left_node.name in MERGE_ALLOWED:
                        if left_node.name == right_node.name:
                            left_node.value = (
                                left_node.value + right_node.value)
                            offset = 2
                text_node_tokens = (
                    text_node_tokens[:node_index] +
                    text_node_tokens[node_index + offset:]
                )
            else:
                text_node_tokens.pop(node_index)
        else:
            node_start, node_end = node_position
            if node_start == (line, column):
                previous_token = text_node_tokens[node_index - 1]
                previous_value = previous_token.value
                previous_value = previous_value[:-1]
                merge = True
                diff = 0
                if len(previous_value) == 0:
                    if node_index - 2 > 0:
                        previous_token = text_node_tokens[node_index - 2]
                    else:
                        merge = False
                    text_node_tokens.pop(node_index - 1)
                    diff = 1
                else:
                    previous_token.value = previous_value

                if merge:
                    if node.mark_for_position:
                        if node.name in MERGE_ALLOWED:
                            if node.name == previous_token.name:
                                previous_token.value = (
                                    previous_token.value + node.value)
                                text_node_tokens.pop(node_index - diff)
            elif node_end == (line, column):
                node_value = node.value
                node_value = node_value[:-1]
                if len(node_value) == 0:
                    text_node_tokens.pop(node_index)
                else:
                    node.value = node_value
            else:
                x, y = node_start
                diff = column - y
                node_value = node.value
                node_value = node_value[:diff] + node_value[diff + 1:]
                node.value = node_value
        if len(text_node_tokens) == 0:
            text_node_tokens = [nodes.LeafNode()]
        text_node.tokens = text_node_tokens