Skip to content

Commit e5d6d88

Browse files
committed
_find_width_index and _handle_long_word change
1 parent 68e8098 commit e5d6d88

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

Lib/test/test_textwrap.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,5 +1118,18 @@ def test_shorten_placeholder(self):
11181118
text_len=self.text_len)
11191119

11201120

1121+
class ZeroWidthTestCase(BaseTestCase):
1122+
def text_len(self, text):
1123+
return sum(
1124+
0 if c == 'Q' else 1
1125+
for c in text
1126+
)
1127+
1128+
def test_zero_width_text_len(self):
1129+
1130+
text = "0QQ1234QQ56789"
1131+
self.check_wrap(text, 6, ["0QQ1234QQ5", "6789"], text_len=self.text_len)
1132+
1133+
11211134
if __name__ == '__main__':
11221135
unittest.main()

Lib/textwrap.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,23 @@ def _fix_sentence_endings(self, chunks):
199199
else:
200200
i += 1
201201

202+
def _find_width_index(self, text, width):
203+
"""_find_width_index(text : string, width: int)
204+
205+
Find at which index the text has the required width.
206+
"""
207+
# In most cases text_len will just use the number of characters, so this heuristic prevents calculating width
208+
# for each character
209+
if self.text_len(text[:width]) == width:
210+
# For character widths greater than one, width can be more than the number of characters
211+
return min(width, len(text))
212+
cur_text = ''
213+
for i, c in enumerate(text):
214+
cur_text += c
215+
cur_width = self.text_len(cur_text)
216+
if cur_width >= width:
217+
return i+1
218+
202219
def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
203220
"""_handle_long_word(chunks : [string],
204221
cur_line : [string],
@@ -217,12 +234,12 @@ def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
217234
# If we're allowed to break long words, then do so: put as much
218235
# of the next chunk onto the current line as will fit.
219236
if self.break_long_words:
220-
end = space_left
221237
chunk = reversed_chunks[-1]
238+
end = self._find_width_index(chunk, space_left)
222239
if self.break_on_hyphens and self.text_len(chunk) > space_left:
223240
# break after last hyphen, but only if there are
224241
# non-hyphens before it
225-
hyphen = chunk.rfind('-', 0, space_left)
242+
hyphen = chunk.rfind('-', 0, end)
226243
if hyphen > 0 and any(c != '-' for c in chunk[:hyphen]):
227244
end = hyphen + 1
228245
cur_line.append(chunk[:end])

0 commit comments

Comments
 (0)