Skip to content

Commit 7b569a5

Browse files
authored
Make wrapping respect non-breaking spaces (#1780)
Non-breaking space and Narrow non-breaking space will not permit line breaks during text rewrapping. GG1 respects NBS, but not NNBS. GG2 now respects both. Also respect Figure Space Since Figure Space is used, e.g. for space in phone numbers, it too is normally thought of as non-breaking.
1 parent 1d96396 commit 7b569a5

1 file changed

Lines changed: 15 additions & 2 deletions

File tree

src/guiguts/maintext.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
INDEX_NEXT_LINE_MARK = "IndexLineStart"
4646
WRAP_END_MARK = "WrapSectionEnd"
4747
PAGEMARK_PIN = "\x7f" # Temp char to pin page mark locations
48+
# Temp chars to replace non-breaking space are from Unicode Private Use Area,
49+
# so we know they won't appear in any of our books
50+
NBS_DICT = {"\xa0": "\ue123", "\u2007": "\ue124", "\u202f": "\ue125"}
4851
PAGEMARK_PREFIX = "Pg"
4952
REPLACE_END_MARK = "ReplaceEnd"
5053
SELECTION_MARK_START = "SelectionMarkStart"
@@ -3570,25 +3573,35 @@ def wrap_paragraph(
35703573
wrap_params: Wrapping parameters.
35713574
wrapper: TextWrapper object to perform the wrapping - re-used for efficiency.
35723575
"""
3576+
35733577
if paragraph.startswith(" *" * 5):
35743578
return
35753579
# Remove leading/trailing space
35763580
paragraph = paragraph.strip()
3577-
# Replace all multiple whitespace with single space
3578-
paragraph = re.sub(r"\s+", " ", paragraph)
3581+
# Replace all multiple space/newline with single space
3582+
paragraph = re.sub(r"[\n ]+", " ", paragraph)
35793583
# Don't want pagemark pins to trap spaces around them, so...
35803584
# Remove space between pagemark pins
35813585
paragraph = re.sub(rf"(?<={PAGEMARK_PIN}) (?={PAGEMARK_PIN})", "", paragraph)
35823586
# Remove space after pagemark pins if space (or linestart) before
35833587
paragraph = re.sub(rf"(( |^){PAGEMARK_PIN}+) ", r"\1", paragraph)
35843588
# Remove space before pagemark pins if space (or lineend) after
35853589
paragraph = re.sub(rf" ({PAGEMARK_PIN}+( |$)) ", r"\1", paragraph)
3590+
# Convert non-breaking spaces to temporary non-space characters
3591+
# to stop the wrapper from putting a break there
3592+
for nbs, temp in NBS_DICT.items():
3593+
paragraph = paragraph.replace(nbs, temp)
35863594

35873595
wrapper.width = wrap_params.right
35883596
wrapper.initial_indent = wrap_params.first * " "
35893597
wrapper.subsequent_indent = wrap_params.left * " "
35903598

35913599
wrapped = wrapper.fill(paragraph)
3600+
3601+
# Restore non-breaking spaces
3602+
for nbs, temp in NBS_DICT.items():
3603+
wrapped = wrapped.replace(temp, nbs)
3604+
35923605
self.delete(paragraph_start, paragraph_end)
35933606
self.insert(paragraph_start, wrapped + "\n")
35943607

0 commit comments

Comments
 (0)