-
Notifications
You must be signed in to change notification settings - Fork 8
/
wrap.py
97 lines (77 loc) · 2.84 KB
/
wrap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import sys
import textwrap
import unicodedata
from itertools import groupby
east_asian_widths = {
'W': 2, # Wide
'F': 2, # Full-width (wide)
'Na': 1, # Narrow
'H': 1, # Half-width (narrow)
'N': 1, # Neutral (not East Asian, treated as narrow)
'A': 1 # Ambiguous (s/b wide in East Asian context, narrow otherwise, but that doesn't work)
}
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)