Add new extension to reformat a (text) paragraph.
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 @@
"SearchBinding",
"AutoIndent",
"AutoExpand",
+ "FormatParagraph",
"ZoomHeight",
]