symbian-qemu-0.9.1-12/python-2.6.1/Lib/idlelib/FormatParagraph.py
changeset 1 2fb8b9db1c86
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/python-2.6.1/Lib/idlelib/FormatParagraph.py	Fri Jul 31 15:01:17 2009 +0100
@@ -0,0 +1,149 @@
+# Extension to format a paragraph
+
+# Does basic, standard text formatting, and also understands Python
+# comment blocks.  Thus, for editing Python source code, this
+# extension is really only suitable for reformatting these comment
+# blocks or triple-quoted strings.
+
+# Known problems with comment reformatting:
+# * If there is a selection marked, and the first line of the
+#   selection is not complete, the block will probably not be detected
+#   as comments, and will have the normal "text formatting" rules
+#   applied.
+# * If a comment block has leading whitespace that mixes tabs and
+#   spaces, they will not be considered part of the same block.
+# * Fancy comments, like this bulleted list, arent handled :-)
+
+import re
+from configHandler import idleConf
+
+class FormatParagraph:
+
+    menudefs = [
+        ('format', [   # /s/edit/format   dscherer@cmu.edu
+            ('Format Paragraph', '<<format-paragraph>>'),
+         ])
+    ]
+
+    def __init__(self, editwin):
+        self.editwin = editwin
+
+    def close(self):
+        self.editwin = None
+
+    def format_paragraph_event(self, event):
+        maxformatwidth = int(idleConf.GetOption('main','FormatParagraph','paragraph'))
+        text = self.editwin.text
+        first, last = self.editwin.get_selection_indices()
+        if first and last:
+            data = text.get(first, last)
+            comment_header = ''
+        else:
+            first, last, comment_header, data = \
+                    find_paragraph(text, text.index("insert"))
+        if comment_header:
+            # Reformat the comment lines - convert to text sans header.
+            lines = data.split("\n")
+            lines = map(lambda st, l=len(comment_header): st[l:], lines)
+            data = "\n".join(lines)
+            # Reformat to maxformatwidth chars or a 20 char width, whichever is greater.
+            format_width = max(maxformatwidth - len(comment_header), 20)
+            newdata = reformat_paragraph(data, format_width)
+            # re-split and re-insert the comment header.
+            newdata = newdata.split("\n")
+            # If the block ends in a \n, we dont want the comment
+            # prefix inserted after it. (Im not sure it makes sense to
+            # reformat a comment block that isnt made of complete
+            # lines, but whatever!)  Can't think of a clean soltution,
+            # so we hack away
+            block_suffix = ""
+            if not newdata[-1]:
+                block_suffix = "\n"
+                newdata = newdata[:-1]
+            builder = lambda item, prefix=comment_header: prefix+item
+            newdata = '\n'.join(map(builder, newdata)) + block_suffix
+        else:
+            # Just a normal text format
+            newdata = reformat_paragraph(data, maxformatwidth)
+        text.tag_remove("sel", "1.0", "end")
+        if newdata != data:
+            text.mark_set("insert", first)
+            text.undo_block_start()
+            text.delete(first, last)
+            text.insert(first, newdata)
+            text.undo_block_stop()
+        else:
+            text.mark_set("insert", last)
+        text.see("insert")
+        return "break"
+
+def find_paragraph(text, mark):
+    lineno, col = map(int, mark.split("."))
+    line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
+    while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line):
+        lineno = lineno + 1
+        line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
+    first_lineno = lineno
+    comment_header = get_comment_header(line)
+    comment_header_len = len(comment_header)
+    while get_comment_header(line)==comment_header and \
+              not is_all_white(line[comment_header_len:]):
+        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 lineno > 0 and \
+              get_comment_header(line)==comment_header and \
+              not is_all_white(line[comment_header_len:]):
+        lineno = lineno - 1
+        line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
+    first = "%d.0" % (lineno+1)
+    return first, last, comment_header, text.get(first, last)
+
+def reformat_paragraph(data, limit):
+    lines = data.split("\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((partial + word).expandtabs()) > limit and \
+               partial != indent1:
+                new.append(partial.rstrip())
+                partial = indent2
+            partial = partial + word + " "
+            if j+1 < len(words) and words[j+1] != " ":
+                partial = partial + " "
+        i = i+1
+    new.append(partial.rstrip())
+    # XXX Should reformat remaining paragraphs as well
+    new.extend(lines[i:])
+    return "\n".join(new)
+
+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()
+
+def get_comment_header(line):
+    m = re.match(r"^(\s*#*)", line)
+    if m is None: return ""
+    return m.group(1)