summaryrefslogtreecommitdiff
path: root/django/utils/text.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/utils/text.py')
-rw-r--r--django/utils/text.py43
1 files changed, 23 insertions, 20 deletions
diff --git a/django/utils/text.py b/django/utils/text.py
index df6e1d0c46..68eb713026 100644
--- a/django/utils/text.py
+++ b/django/utils/text.py
@@ -34,30 +34,33 @@ re_camel_case = re.compile(r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))')
def wrap(text, width):
"""
- A word-wrap function that preserves existing line breaks and most spaces in
- the text. Expects that existing line breaks are posix newlines.
+ A word-wrap function that preserves existing line breaks. Expects that
+ existing line breaks are posix newlines.
+
+ All white space is preserved except added line breaks consume the space on
+ which they break the line.
+
+ Long words are not wrapped, so the output text may have lines longer than
+ ``width``.
"""
text = force_text(text)
def _generator():
- it = iter(text.split(' '))
- word = next(it)
- yield word
- pos = len(word) - word.rfind('\n') - 1
- for word in it:
- if "\n" in word:
- lines = word.split('\n')
- else:
- lines = (word,)
- pos += len(lines[0]) + 1
- if pos > width:
- yield '\n'
- pos = len(lines[-1])
- else:
- yield ' '
- if len(lines) > 1:
- pos = len(lines[-1])
- yield word
+ for line in text.splitlines(True): # True keeps trailing linebreaks
+ max_width = min((line.endswith('\n') and width + 1 or width), width)
+ while len(line) > max_width:
+ space = line[:max_width + 1].rfind(' ') + 1
+ if space == 0:
+ space = line.find(' ') + 1
+ if space == 0:
+ yield line
+ line = ''
+ break
+ yield '%s\n' % line[:space - 1]
+ line = line[space:]
+ max_width = min((line.endswith('\n') and width + 1 or width), width)
+ if line:
+ yield line
return ''.join(_generator())
wrap = allow_lazy(wrap, six.text_type)