"""Format a paragraph, comment block, or selection to a max width.Does basic, standard text formatting, and also understands Pythoncomment blocks. Thus, for editing Python source code, thisextension is really only suitable for reformatting these commentblocks or triple-quoted strings.Known problems with comment reformatting:* If there is a selection marked, and the first line of theselection is not complete, the block will probably not be detectedas comments, and will have the normal "text formatting" rulesapplied.* If a comment block has leading whitespace that mixes tabs andspaces, they will not be considered part of the same block.* Fancy comments, like this bulleted list, aren't handled :-)"""import refrom idlelib.config import idleConfclass FormatParagraph:def __init__(self, editwin):self.editwin = editwin@classmethoddef reload(cls):cls.max_width = idleConf.GetOption('extensions', 'FormatParagraph','max-width', type='int', default=72)def close(self):self.editwin = Nonedef format_paragraph_event(self, event, limit=None):"""Formats paragraph to a max width specified in idleConf.If text is selected, format_paragraph_event will start breaking linesat the max width, starting from the beginning selection.If no text is selected, format_paragraph_event uses the currentcursor location to determine the paragraph (lines of text surroundedby blank lines) and formats it.The length limit parameter is for testing with a known value."""limit = self.max_width if limit is None else limittext = self.editwin.textfirst, last = self.editwin.get_selection_indices()if first and last:data = text.get(first, last)comment_header = get_comment_header(data)else:first, last, comment_header, data = \find_paragraph(text, text.index("insert"))if comment_header:newdata = reformat_comment(data, limit, comment_header)else:newdata = reformat_paragraph(data, limit)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"FormatParagraph.reload()def find_paragraph(text, mark):"""Returns the start/stop indices enclosing the paragraph that mark is in.Also returns the comment format string, if any, and paragraph of textbetween the start/stop indices."""lineno, col = map(int, mark.split("."))line = text.get("%d.0" % lineno, "%d.end" % lineno)# Look for start of next paragraph if the index passed in is a blank linewhile text.compare("%d.0" % lineno, "<", "end") and is_all_white(line):lineno = lineno + 1line = text.get("%d.0" % lineno, "%d.end" % lineno)first_lineno = linenocomment_header = get_comment_header(line)comment_header_len = len(comment_header)# Once start line found, search for end of paragraph (a blank line)while get_comment_header(line)==comment_header and \not is_all_white(line[comment_header_len:]):lineno = lineno + 1line = text.get("%d.0" % lineno, "%d.end" % lineno)last = "%d.0" % lineno# Search back to beginning of paragraph (first blank line before)lineno = first_lineno - 1line = text.get("%d.0" % lineno, "%d.end" % lineno)while lineno > 0 and \get_comment_header(line)==comment_header and \not is_all_white(line[comment_header_len:]):lineno = lineno - 1line = text.get("%d.0" % lineno, "%d.end" % lineno)first = "%d.0" % (lineno+1)return first, last, comment_header, text.get(first, last)# This should perhaps be replaced with textwrap.wrapdef reformat_paragraph(data, limit):"""Return data reformatted to specified width (limit)."""lines = data.split("\n")i = 0n = len(lines)while i < n and is_all_white(lines[i]):i = i+1if i >= n:return dataindent1 = get_indent(lines[i])if i+1 < n and not is_all_white(lines[i+1]):indent2 = get_indent(lines[i+1])else:indent2 = indent1new = lines[:i]partial = indent1while i < n and not is_all_white(lines[i]):# XXX Should take double space after period (etc.) into accountwords = re.split(r"(\s+)", lines[i])for j in range(0, len(words), 2):word = words[j]if not word:continue # Can happen when line ends in whitespaceif len((partial + word).expandtabs()) > limit and \partial != indent1:new.append(partial.rstrip())partial = indent2partial = partial + word + " "if j+1 < len(words) and words[j+1] != " ":partial = partial + " "i = i+1new.append(partial.rstrip())# XXX Should reformat remaining paragraphs as wellnew.extend(lines[i:])return "\n".join(new)def reformat_comment(data, limit, comment_header):"""Return data reformatted to specified width with comment header."""# Remove header from the comment lineslc = len(comment_header)data = "\n".join(line[lc:] for line in data.split("\n"))# Reformat to maxformatwidth chars or a 20 char width,# whichever is greater.format_width = max(limit - 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 don't want the comment prefix# inserted after it. (Im not sure it makes sense to reformat a# comment block that is not made of complete lines, but whatever!)# Can't think of a clean solution, so we hack awayblock_suffix = ""if not newdata[-1]:block_suffix = "\n"newdata = newdata[:-1]return '\n'.join(comment_header+line for line in newdata) + block_suffixdef is_all_white(line):"""Return True if line is empty or all whitespace."""return re.match(r"^\s*$", line) is not Nonedef get_indent(line):"""Return the initial space or tab indent of line."""return re.match(r"^([ \t]*)", line).group()def get_comment_header(line):"""Return string with leading whitespace and '#' from line or ''.A null return indicates that the line is not a comment line. A non-null return, such as ' #', will be used to find the other lines ofa comment block with the same indent."""m = re.match(r"^([ \t]*#*)", line)if m is None: return ""return m.group(1)if __name__ == "__main__":from unittest import mainmain('idlelib.idle_test.test_paragraph', verbosity=2, exit=False)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。