예제 #1
0
 def smart_indent_event(self, event):
     tracing.user_is_typing()
     first, last = self.get_selection_indices()
     self.undo_block_start()
     try:
         if first and last:
             if index2line(first) != index2line(last):
                 return self.indent_region_event(event)
             self.send_deletion(first, last)
             self.delete(first, last)
             self.mark_set("insert", first)
         prefix = self.get("insert linestart", "insert")
         raw, effective = classifyws(prefix, self.tabwidth)
         if raw == len(prefix):
             # only whitespace to the left
             self.reindent_to(effective + self.indentwidth)
         else:
             # tab to the next 'stop' within or to right of line's self:
             if self.usetabs:
                 pad = '\t'
             else:
                 effective = len(prefix.expandtabs(self.tabwidth))
                 n = self.indentwidth
                 pad = ' ' * (n - effective % n)
             self.insert("insert", pad)
         self.see("insert")
         return "break"
     finally:
         self.undo_block_stop()
예제 #2
0
    def smart_backspace_event(self, event):
        tracing.user_is_typing()
        self.typed_char = False
        if self.old_line is None:
            self.old_line = self.create_line(self.get_current_line_number())

        first, last = self.get_selection_indices()
        if first and last:
            self.send_deletion(first, last)
            self.delete(first, last)
            self.mark_set("insert", first)
            return "break"
        # Delete whitespace left, until hitting a real char or closest
        # preceding virtual tab stop.
        chars = self.get("insert linestart", "insert")
        if chars == '':
            if self.compare("insert", ">", "1.0"):
                # easy: delete preceding newline
                self.send_update_changed_line(force_sending=True)
                self.reset_line()
                self.delete("insert-1c")
            else:
                self.bell()  # at start of buffer
            return "break"
        if chars[-1] not in " \t":
            # easy: delete preceding real char
            self.delete("insert-1c")
            return "break"
        # Ick.  It may require *inserting* spaces if we back up over a
        # tab character!  This is written to be clear, not fast.
        tabwidth = self.tabwidth
        have = len(chars.expandtabs(tabwidth))
        assert have > 0
        want = ((have - 1) // self.indentwidth) * self.indentwidth
        # Debug prompt is multilined....
        if self.context_use_ps1:
            last_line_of_prompt = sys.ps1.split('\n')[-1]
        else:
            last_line_of_prompt = ''
        ncharsdeleted = 0
        while 1:
            if chars == last_line_of_prompt:
                break
            chars = chars[:-1]
            ncharsdeleted = ncharsdeleted + 1
            have = len(chars.expandtabs(tabwidth))
            if have <= want or chars[-1] not in " \t":
                break
        self.undo_block_start()
        self.delete("insert-%dc" % ncharsdeleted, "insert")
        if have < want:
            self.insert("insert", ' ' * (want - have))
        self.undo_block_stop()
        return "break"
예제 #3
0
    def keypress_event(self, event):
        """Used to check if user typed a keyword, deleted some selection
        and to initialize old_line to check if user modified an instruction"""
        tracing.user_is_typing()

        keypress_is_char = len(event.char) >= 1
        keypress_is_separator = keypress_is_char and event.char.isalnum(
        ) is False
        first, last = self.get_selection_indices()
        if self.typed_char and (keypress_is_separator
                                or event.keysym == "space"):
            self.send_keyword(self.index("insert"))
        else:
            self.typed_char = keypress_is_char

        if keypress_is_char and first and last:
            self.send_deletion(first, last)

        if self.old_line is None:
            self.old_line = self.create_line(self.get_current_line_number())
예제 #4
0
    def newline_and_indent_event(self, event):
        tracing.user_is_typing()
        if self.old_line is None:
            self.old_line = self.create_line(self.get_current_line_number())

        # Trace last word if it's a keyword
        if self.typed_char:
            cursor = self.index("insert")
            self.send_keyword(cursor)
            self.typed_char = False

        first, last = self.get_selection_indices()
        self.undo_block_start()
        try:
            if first and last:
                self.send_deletion(first, last)
                self.delete(first, last)
                self.mark_set("insert", first)
            line = self.get("insert linestart", "insert")
            i, n = 0, len(line)
            while i < n and line[i] in " \t":
                i = i + 1
            if i == n:
                # the cursor is in or at leading indentation in a continuation
                # line; just inject an empty line at the start
                self.insert("insert linestart", '\n')
                return "break"
            indent = line[:i]
            # strip whitespace before insert point unless it's in the prompt
            i = 0
            last_line_of_prompt = sys.ps1.split('\n')[-1]
            while line and line[-1] in " \t" and line != last_line_of_prompt:
                line = line[:-1]
                i = i + 1
            if i:
                self.delete("insert - %d chars" % i, "insert")
            # strip whitespace after insert point
            while self.get("insert") in " \t":
                self.delete("insert")
            # start new line
            self.insert("insert", '\n')

            # adjust indentation for continuations and block
            # open/close first need to find the last stmt
            lno = index2line(self.index('insert'))
            y = PyParse.Parser(self.indentwidth, self.tabwidth)
            if not self.context_use_ps1:
                for context in self.num_context_lines:
                    startat = max(lno - context, 1)
                    startatindex = repr(startat) + ".0"
                    rawtext = self.get(startatindex, "insert")
                    y.set_str(rawtext)
                    bod = y.find_good_parse_start(
                        self.context_use_ps1,
                        self._build_char_in_string_func(startatindex))
                    if bod is not None or startat == 1:
                        break
                y.set_lo(bod or 0)
            else:
                r = self.tag_prevrange("console", "insert")
                if r:
                    startatindex = r[1]
                else:
                    startatindex = "1.0"
                rawtext = self.get(startatindex, "insert")
                y.set_str(rawtext)
                y.set_lo(0)

            c = y.get_continuation_type()
            if c != PyParse.C_NONE:
                # The current stmt hasn't ended yet.
                if c == PyParse.C_STRING_FIRST_LINE:
                    # after the first line of a string; do not indent at all
                    pass
                elif c == PyParse.C_STRING_NEXT_LINES:
                    # inside a string which started before this line;
                    # just mimic the current indent
                    self.insert("insert", indent)
                elif c == PyParse.C_BRACKET:
                    # line up with the first (if any) element of the
                    # last open bracket structure; else indent one
                    # level beyond the indent of the line with the
                    # last open bracket
                    self.reindent_to(y.compute_bracket_indent())
                elif c == PyParse.C_BACKSLASH:
                    # if more than one line in this stmt already, just
                    # mimic the current indent; else if initial line
                    # has a start on an assignment stmt, indent to
                    # beyond leftmost =; else to beyond first chunk of
                    # non-whitespace on initial line
                    if y.get_num_lines_in_stmt() > 1:
                        self.insert("insert", indent)
                    else:
                        self.reindent_to(y.compute_backslash_indent())
                else:
                    assert 0, "bogus continuation type %r" % (c, )
                return "break"

            # This line starts a brand new stmt; indent relative to
            # indentation of initial line of closest preceding
            # interesting stmt.
            indent = y.get_base_indent_string()
            self.insert("insert", indent)
            if y.is_block_opener():
                self.smart_indent_event(event)
            elif indent and y.is_block_closer():
                self.smart_backspace_event(event)
            return "break"
        finally:
            self.see("insert")
            self.undo_block_stop()
            self.send_update_changed_line(newline=True)