diff options
-rw-r--r-- | Tools/idle/FormatParagraph.py | 101 | ||||
-rw-r--r-- | Tools/idle/extend.py | 1 |
2 files changed, 102 insertions, 0 deletions
diff --git a/Tools/idle/FormatParagraph.py b/Tools/idle/FormatParagraph.py new file mode 100644 index 0000000..729ec93 --- /dev/null +++ b/Tools/idle/FormatParagraph.py @@ -0,0 +1,101 @@ +# Extension to format a paragraph + +import string +import re + +class FormatParagraph: + + menudefs = [ + ('edit', [ + ('Format Paragraph', '<<format-paragraph>>'), + ]) + ] + + keydefs = { + '<<format-paragraph>>': ['<Alt-q>'], + } + + def __init__(self, editwin): + self.editwin = editwin + + def format_paragraph_event(self, event): + text = self.editwin.text + try: + first = text.index("sel.first") + last = text.index("sel.last") + except TclError: + first = last = None + if first and last: + data = text.get(first, last) + else: + first, last, data = find_paragraph(text, text.index("insert")) + newdata = reformat_paragraph(data) + text.tag_remove("sel", "1.0", "end") + if newdata != data: + text.mark_set("insert", first) + text.delete(first, last) + text.insert(first, newdata) + else: + text.mark_set("insert", last) + text.see("insert") + +def find_paragraph(text, mark): + lineno, col = map(int, string.split(mark, ".")) + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + while is_all_white(line): + lineno = lineno + 1 + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + first_lineno = lineno + while not is_all_white(line): + lineno = lineno + 1 + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + last = "%d.0" % lineno + # Search back to beginning of paragraph + lineno = first_lineno - 1 + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + while not is_all_white(line): + lineno = lineno - 1 + line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno) + first = "%d.0" % (lineno+1) + return first, last, text.get(first, last) + +def reformat_paragraph(data, limit=72): + lines = string.split(data, "\n") + i = 0 + n = len(lines) + while i < n and is_all_white(lines[i]): + i = i+1 + if i >= n: + return data + indent1 = get_indent(lines[i]) + if i+1 < n and not is_all_white(lines[i+1]): + indent2 = get_indent(lines[i+1]) + else: + indent2 = indent1 + new = lines[:i] + partial = indent1 + while i < n and not is_all_white(lines[i]): + # XXX Should take double space after period (etc.) into account + words = re.split("(\s+)", lines[i]) + for j in range(0, len(words), 2): + word = words[j] + if not word: + continue # Can happen when line ends in whitespace + if len(string.expandtabs(partial + word)) > limit and \ + partial != indent1: + new.append(string.rstrip(partial)) + partial = indent2 + partial = partial + word + " " + if j+1 < len(words) and words[j+1] != " ": + partial = partial + " " + i = i+1 + new.append(string.rstrip(partial)) + # XXX Should reformat remaining paragraphs as well + new.extend(lines[i:]) + return string.join(new, "\n") + +def is_all_white(line): + return re.match(r"^\s*$", line) is not None + +def get_indent(line): + return re.match(r"^(\s*)", line).group() diff --git a/Tools/idle/extend.py b/Tools/idle/extend.py index 7d8117d..58bc95f 100644 --- a/Tools/idle/extend.py +++ b/Tools/idle/extend.py @@ -5,5 +5,6 @@ standard = [ "SearchBinding", "AutoIndent", "AutoExpand", + "FormatParagraph", "ZoomHeight", ] |