mirror of
https://github.com/python/cpython.git
synced 2024-11-25 10:54:51 +08:00
b76922a7be
svn+ssh://pythondev@svn.python.org/python/trunk ........ r59455 | guido.van.rossum | 2007-12-10 21:42:53 +0100 (Mon, 10 Dec 2007) | 2 lines Remove a 2.2-ism. ........ r59459 | christian.heimes | 2007-12-10 23:28:56 +0100 (Mon, 10 Dec 2007) | 4 lines Backport of r59456:59458 from py3k to trunk Issue #1580: New free format floating point representation based on "Floating-Point Printer Sample Code", by Robert G. Burger. For example repr(11./5) now returns '2.2' instead of '2.2000000000000002'. Thanks to noam for the patch! I had to modify doubledigits.c slightly to support X64 and IA64 machines on Windows. I also added the new file to the three project files. ........ r59460 | guido.van.rossum | 2007-12-11 00:00:12 +0100 (Tue, 11 Dec 2007) | 4 lines Patch #1643738 by Ulisses Furquim -- make the is_tripped variable in signalmodule.c more robust. Includes Martin von Loewis's suggestion to set is_tripped after .tripped. ........ r59463 | kurt.kaiser | 2007-12-11 01:04:57 +0100 (Tue, 11 Dec 2007) | 2 lines format_paragraph_event wasn't returning 'break' ........ r59464 | christian.heimes | 2007-12-11 01:54:34 +0100 (Tue, 11 Dec 2007) | 3 lines The new float repr causes too much trouble and pain. I'm disabling the feature until we have sorted out the issues on all machines. 64bit machines seem to have issues and Guido has reported even worse. Guido: It's pretty bad actually -- repr(1e5) comes out as '1.0'... Ditto for repr(1eN) for most N... Both in 2.6 and in 3.0... ........
150 lines
5.6 KiB
Python
150 lines
5.6 KiB
Python
# 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 idlelib.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)
|