|
42 | 42 | import base64
|
43 | 43 | import glob
|
44 | 44 | import hashlib
|
45 |
| -import itertools |
46 | 45 | import os
|
47 | 46 | import sys
|
48 |
| -import textwrap |
49 | 47 | import time
|
50 | 48 |
|
51 | 49 | from blurb._template import (
|
52 | 50 | next_filename_unsanitize_sections, sanitize_section,
|
53 |
| - sanitize_section_legacy, sections, unsanitize_section, |
| 51 | + sanitize_section_legacy, sections, |
54 | 52 | )
|
55 | 53 |
|
56 |
| -def textwrap_body(body, *, subsequent_indent=''): |
57 |
| - """ |
58 |
| - Accepts either a string or an iterable of strings. |
59 |
| - (Iterable is assumed to be individual lines.) |
60 |
| - Returns a string. |
61 |
| - """ |
62 |
| - if isinstance(body, str): |
63 |
| - text = body |
64 |
| - else: |
65 |
| - text = "\n".join(body).rstrip() |
66 |
| - |
67 |
| - # textwrap merges paragraphs, ARGH |
68 |
| - |
69 |
| - # step 1: remove trailing whitespace from individual lines |
70 |
| - # (this means that empty lines will just have \n, no invisible whitespace) |
71 |
| - lines = [] |
72 |
| - for line in text.split("\n"): |
73 |
| - lines.append(line.rstrip()) |
74 |
| - text = "\n".join(lines) |
75 |
| - # step 2: break into paragraphs and wrap those |
76 |
| - paragraphs = text.split("\n\n") |
77 |
| - paragraphs2 = [] |
78 |
| - kwargs = {'break_long_words': False, 'break_on_hyphens': False} |
79 |
| - if subsequent_indent: |
80 |
| - kwargs['subsequent_indent'] = subsequent_indent |
81 |
| - dont_reflow = False |
82 |
| - for paragraph in paragraphs: |
83 |
| - # don't reflow bulleted / numbered lists |
84 |
| - dont_reflow = dont_reflow or paragraph.startswith(("* ", "1. ", "#. ")) |
85 |
| - if dont_reflow: |
86 |
| - initial = kwargs.get("initial_indent", "") |
87 |
| - subsequent = kwargs.get("subsequent_indent", "") |
88 |
| - if initial or subsequent: |
89 |
| - lines = [line.rstrip() for line in paragraph.split("\n")] |
90 |
| - indents = itertools.chain( |
91 |
| - itertools.repeat(initial, 1), |
92 |
| - itertools.repeat(subsequent), |
93 |
| - ) |
94 |
| - lines = [indent + line for indent, line in zip(indents, lines)] |
95 |
| - paragraph = "\n".join(lines) |
96 |
| - paragraphs2.append(paragraph) |
97 |
| - else: |
98 |
| - # Why do we reflow the text twice? Because it can actually change |
99 |
| - # between the first and second reflows, and we want the text to |
100 |
| - # be stable. The problem is that textwrap.wrap is deliberately |
101 |
| - # dumb about how many spaces follow a period in prose. |
102 |
| - # |
103 |
| - # We're reflowing at 76 columns, but let's pretend it's 30 for |
104 |
| - # illustration purposes. If we give textwrap.wrap the following |
105 |
| - # text--ignore the line of 30 dashes, that's just to help you |
106 |
| - # with visualization: |
107 |
| - # |
108 |
| - # ------------------------------ |
109 |
| - # xxxx xxxx xxxx xxxx xxxx. xxxx |
110 |
| - # |
111 |
| - # The first textwrap.wrap will return this: |
112 |
| - # "xxxx xxxx xxxx xxxx xxxx.\nxxxx" |
113 |
| - # |
114 |
| - # If we reflow it again, textwrap will rejoin the lines, but |
115 |
| - # only with one space after the period! So this time it'll |
116 |
| - # all fit on one line, behold: |
117 |
| - # ------------------------------ |
118 |
| - # xxxx xxxx xxxx xxxx xxxx. xxxx |
119 |
| - # and so it now returns: |
120 |
| - # "xxxx xxxx xxxx xxxx xxxx. xxxx" |
121 |
| - # |
122 |
| - # textwrap.wrap supports trying to add two spaces after a peroid: |
123 |
| - # https://docs.python.org/3/library/textwrap.html#textwrap.TextWrapper.fix_sentence_endings |
124 |
| - # But it doesn't work all that well, because it's not smart enough |
125 |
| - # to do a really good job. |
126 |
| - # |
127 |
| - # Since blurbs are eventually turned into ReST and rendered anyway, |
128 |
| - # and since the Zen says "In the face of ambiguity, refuse the |
129 |
| - # temptation to guess", I don't sweat it. I run textwrap.wrap |
130 |
| - # twice, so it's stable, and this means occasionally it'll |
131 |
| - # convert two spaces to one space, no big deal. |
132 |
| - |
133 |
| - paragraph = "\n".join(textwrap.wrap(paragraph.strip(), width=76, **kwargs)).rstrip() |
134 |
| - paragraph = "\n".join(textwrap.wrap(paragraph.strip(), width=76, **kwargs)).rstrip() |
135 |
| - paragraphs2.append(paragraph) |
136 |
| - # don't reflow literal code blocks (I hope) |
137 |
| - dont_reflow = paragraph.endswith("::") |
138 |
| - if subsequent_indent: |
139 |
| - kwargs['initial_indent'] = subsequent_indent |
140 |
| - text = "\n\n".join(paragraphs2).rstrip() |
141 |
| - if not text.endswith("\n"): |
142 |
| - text += "\n" |
143 |
| - return text |
144 |
| - |
145 | 54 | def sortable_datetime():
|
146 | 55 | return time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
147 | 56 |
|
|
0 commit comments