def _code_is_ready_for_submission(self, source, tail=""): # Ready to submit if ends with empty line # or is complete single-line code if tail.strip() != "": return False # First check if it has unclosed parens, unclosed string or ending with : or \ parser = roughparse.RoughParser(self.indentwidth, self.tabwidth) parser.set_str(source.rstrip() + "\n") if (parser.get_continuation_type() != roughparse.C_NONE or parser.is_block_opener()): return False # Multiline compound statements need to end with empty line to be considered # complete. lines = source.splitlines() # strip starting empty and comment lines while (len(lines) > 0 and (lines[0].strip().startswith("#") or lines[0].strip() == "")): lines.pop(0) compound_keywords = [ "if", "while", "for", "with", "try", "def", "class", "async", "await" ] if len(lines) > 0: first_word = lines[0].strip().split()[0] if (first_word in compound_keywords and not source.replace( " ", "").replace("\t", "").endswith("\n\n")): # last line is not empty return False return True
def perform_return(self, event): # copied from idlelib.EditorWindow (Python 3.4.2) # slightly modified # pylint: disable=lost-exception text = event.widget assert text is self try: # delete selection first, last = text.get_selection_indices() if first and last: text.delete(first, last) text.mark_set("insert", first) # Strip whitespace after insert point # (ie. don't carry whitespace from the right of the cursor over to the new line) while text.get("insert") in [" ", "\t"]: text.delete("insert") left_part = text.get("insert linestart", "insert") # locate first non-white character i = 0 n = len(left_part) while i < n and left_part[i] in " \t": i = i + 1 # is it only whitespace? if i == n: # start the new line with the same whitespace text.insert("insert", "\n" + left_part) return "break" # Turned out the left part contains visible chars # Remember the indent indent = left_part[:i] # Strip whitespace before insert point # (ie. after inserting the linebreak this line doesn't have trailing whitespace) while text.get("insert-1c", "insert") in [" ", "\t"]: text.delete("insert-1c", "insert") # start new line text.insert("insert", "\n") # adjust indentation for continuations and block # open/close first need to find the last stmt lno = tktextext.index2line(text.index("insert")) y = roughparse.RoughParser(text.indent_width, text.tabwidth) for context in roughparse.NUM_CONTEXT_LINES: startat = max(lno - context, 1) startatindex = repr(startat) + ".0" rawtext = text.get(startatindex, "insert") y.set_str(rawtext) bod = y.find_good_parse_start( False, roughparse._build_char_in_string_func(startatindex) ) if bod is not None or startat == 1: break y.set_lo(bod or 0) c = y.get_continuation_type() if c != roughparse.C_NONE: # The current stmt hasn't ended yet. if c == roughparse.C_STRING_FIRST_LINE: # after the first line of a string; do not indent at all pass elif c == roughparse.C_STRING_NEXT_LINES: # inside a string which started before this line; # just mimic the current indent text.insert("insert", indent) elif c == roughparse.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 text._reindent_to(y.compute_bracket_indent()) elif c == roughparse.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: text.insert("insert", indent) else: text._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() text.insert("insert", indent) if y.is_block_opener(): text.perform_smart_tab(event) elif indent and y.is_block_closer(): text.perform_smart_backspace(event) return "break" finally: text.see("insert") text.event_generate("<<NewLine>>") return "break"
def patched_perform_return(self, event): # copied from idlelib.EditorWindow (Python 3.4.2) # slightly modified text = event.widget assert text is self first, last = text.get_selection_indices() try: if first and last: text.delete(first, last) text.mark_set("insert", first) line = text.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 text.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: text.delete("insert - %d chars" % i, "insert") # strip whitespace after insert point while text.get("insert") in " \t": text.delete("insert") # start new line text.insert("insert", '\n') # adjust indentation for continuations and block # open/close first need to find the last stmt lno = tktextext.index2line(text.index('insert')) y = roughparse.RoughParser(text.indentwidth, text.tabwidth) for context in roughparse.NUM_CONTEXT_LINES: startat = max(lno - context, 1) startatindex = repr(startat) + ".0" rawtext = text.get(startatindex, "insert") y.set_str(rawtext) bod = y.find_good_parse_start( False, roughparse._build_char_in_string_func(startatindex)) if bod is not None or startat == 1: break y.set_lo(bod or 0) c = y.get_continuation_type() if c != roughparse.C_NONE: # The current stmt hasn't ended yet. if c == roughparse.C_STRING_FIRST_LINE: # after the first line of a string; do not indent at all pass elif c == roughparse.C_STRING_NEXT_LINES: # inside a string which started before this line; # just mimic the current indent text.insert("insert", indent) elif c == roughparse.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 text._reindent_to(y.compute_bracket_indent()) elif c == roughparse.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: text.insert("insert", indent) else: text._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() text.insert("insert", indent) if y.is_block_opener(): text.perform_smart_tab(event) elif indent and y.is_block_closer(): text.perform_smart_backspace(event) return "break" finally: text.see("insert") text.event_generate("<<NewLine>>")