|
import sys |
|
import textwrap |
|
import unicodedata |
|
from itertools import groupby |
|
|
|
east_asian_widths = { |
|
'W': 2, |
|
'F': 2, |
|
'Na': 1, |
|
'H': 1, |
|
'N': 1, |
|
'A': 1 |
|
} |
|
|
|
def column_width(text): |
|
if isinstance(text, str) and sys.version_info < (3,0): |
|
return len(text) |
|
combining_correction = sum([-1 for c in text if unicodedata.combining(c)]) |
|
try: |
|
width = sum([east_asian_widths[unicodedata.east_asian_width(c)] for c in text]) |
|
except AttributeError: |
|
width = len(text) |
|
return width + combining_correction |
|
|
|
class TextWrapper(textwrap.TextWrapper): |
|
def _wrap_chunks(self, chunks): |
|
lines = [] |
|
|
|
chunks.reverse() |
|
|
|
while chunks: |
|
cur_line = [] |
|
cur_len = 0 |
|
|
|
if lines: |
|
indent = self.subsequent_indent |
|
else: |
|
indent = self.initial_indent |
|
|
|
width = self.width - column_width(indent) |
|
|
|
if self.drop_whitespace and chunks[-1].strip() == '' and lines: |
|
del chunks[-1] |
|
|
|
while chunks: |
|
l = column_width(chunks[-1]) |
|
|
|
if cur_len + l <= width: |
|
cur_line.append(chunks.pop()) |
|
cur_len += l |
|
|
|
else: |
|
break |
|
|
|
if chunks and column_width(chunks[-1]) > width: |
|
self._handle_long_word(chunks, cur_line, cur_len, width) |
|
|
|
if self.drop_whitespace and cur_line and cur_line[-1].strip() == '': |
|
del cur_line[-1] |
|
|
|
if cur_line: |
|
lines.append(indent + ''.join(cur_line)) |
|
|
|
return lines |
|
|
|
def _break_word(self, word, space_left): |
|
total = 0 |
|
for i,c in enumerate(word): |
|
total += column_width(c) |
|
if total > space_left: |
|
return word[:i-1], word[i-1:] |
|
return word, '' |
|
|
|
def _split(self, text): |
|
split = lambda t: textwrap.TextWrapper._split(self, t) |
|
chunks = [] |
|
for chunk in split(text): |
|
for w, g in groupby(chunk, column_width): |
|
if w == 1: |
|
chunks.extend(split(''.join(g))) |
|
else: |
|
chunks.extend(list(g)) |
|
return chunks |
|
|
|
def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): |
|
space_left = max(width - cur_len, 1) |
|
if self.break_long_words: |
|
l, r = self._break_word(reversed_chunks[-1], space_left) |
|
cur_line.append(l) |
|
reversed_chunks[-1] = r |
|
|
|
elif not cur_line: |
|
cur_line.append(reversed_chunks.pop()) |
|
|
|
def fw_wrap(text,width=50): |
|
w = TextWrapper(width=width) |
|
return w.wrap(text) |