txtwrap 2.2.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- txtwrap-2.3.0/PKG-INFO +360 -0
- txtwrap-2.3.0/README.md +345 -0
- {txtwrap-2.2.0 → txtwrap-2.3.0}/setup.py +3 -5
- {txtwrap-2.2.0 → txtwrap-2.3.0}/txtwrap/__init__.py +3 -7
- {txtwrap-2.2.0 → txtwrap-2.3.0}/txtwrap/__init__.pyi +47 -113
- txtwrap-2.3.0/txtwrap/_txtwrap.py +630 -0
- txtwrap-2.3.0/txtwrap.egg-info/PKG-INFO +360 -0
- {txtwrap-2.2.0 → txtwrap-2.3.0}/txtwrap.egg-info/SOURCES.txt +1 -1
- txtwrap-2.2.0/PKG-INFO +0 -545
- txtwrap-2.2.0/README.md +0 -529
- txtwrap-2.2.0/txtwrap/txtwrap.py +0 -950
- txtwrap-2.2.0/txtwrap.egg-info/PKG-INFO +0 -545
- {txtwrap-2.2.0 → txtwrap-2.3.0}/MANIFEST.in +0 -0
- {txtwrap-2.2.0 → txtwrap-2.3.0}/setup.cfg +0 -0
- {txtwrap-2.2.0 → txtwrap-2.3.0}/txtwrap.egg-info/dependency_links.txt +0 -0
- {txtwrap-2.2.0 → txtwrap-2.3.0}/txtwrap.egg-info/top_level.txt +0 -0
txtwrap-2.3.0/PKG-INFO
ADDED
@@ -0,0 +1,360 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: txtwrap
|
3
|
+
Version: 2.3.0
|
4
|
+
Summary: A tool for wrapping and filling text.
|
5
|
+
Home-page: https://github.com/azzammuhyala/txtwrap
|
6
|
+
Author: azzammuhyala
|
7
|
+
Author-email: azzammuhyala@gmail.com
|
8
|
+
License: MIT
|
9
|
+
Keywords: wrap,wrapper,wrapping,wrapped,text wrap,text wrapper,text wrapping,text wrapped
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
11
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
13
|
+
Requires-Python: >=3.3
|
14
|
+
Description-Content-Type: text/markdown
|
15
|
+
|
16
|
+
# TxTWrap🔡
|
17
|
+
A tool for wrapping and filling text.🔨
|
18
|
+
|
19
|
+
- `LOREM_IPSUM_WORDS`
|
20
|
+
- `LOREM_IPSUM_SENTENCES`
|
21
|
+
- `LOREM_IPSUM_PARAGRAPHS`
|
22
|
+
- `TextWrapper` (✅ Updated)
|
23
|
+
- `sanitize` (➕ New)
|
24
|
+
- `wrap` (✅ Updated)
|
25
|
+
- `align` (✅ Updated)
|
26
|
+
- `fillstr` (✅ Updated)
|
27
|
+
- `printwrap` (✅ Updated)
|
28
|
+
- `shorten` (✅ Updated)
|
29
|
+
|
30
|
+
# Documents📄
|
31
|
+
This module is inspired by the [`textwrap`](https://docs.python.org/3/library/textwrap.html) module, which provides
|
32
|
+
several useful functions, along with the [`TextWrapper`](#textwrapper), class that handles all available functions.
|
33
|
+
|
34
|
+
The difference between [`txtwrap`](https://pypi.org/project/txtwrap) and
|
35
|
+
[`textwrap`](https://docs.python.org/3/library/textwrap.html) is that this module is designed not only for wrapping and
|
36
|
+
filling monospace fonts but also for other font types, such as Arial, Times New Roman, and more.
|
37
|
+
|
38
|
+
<h1></h1>
|
39
|
+
|
40
|
+
```py
|
41
|
+
LOREM_IPSUM_WORDS
|
42
|
+
LOREM_IPSUM_SENTENCES
|
43
|
+
LOREM_IPSUM_PARAGRAPHS
|
44
|
+
```
|
45
|
+
A collection of words, sentences, and paragraphs that can be used as examples.
|
46
|
+
- `LOREM_IPSUM_WORDS` contains a short Lorem Ipsum sentence.
|
47
|
+
- `LOREM_IPSUM_SENTENCES` contains a slightly longer paragraph.
|
48
|
+
- `LOREM_IPSUM_PARAGRAPHS` contains several longer paragraphs.
|
49
|
+
|
50
|
+
<h1></h1>
|
51
|
+
|
52
|
+
## `TextWrapper`
|
53
|
+
```py
|
54
|
+
class TextWrapper:
|
55
|
+
def __init__(
|
56
|
+
self,
|
57
|
+
width: Union[int, float] = 70,
|
58
|
+
line_padding: Union[int, float] = 0,
|
59
|
+
method: Literal['mono', 'word'] = 'word',
|
60
|
+
alignment: Literal['left', 'center', 'right', 'fill', 'fill-left', 'fill-center', 'fill-right'] = 'left',
|
61
|
+
placeholder: str = '...',
|
62
|
+
fillchar: str = ' ',
|
63
|
+
separator: Optional[Union[str, Iterable[str]]] = None,
|
64
|
+
max_lines: Optional[int] = None,
|
65
|
+
preserve_empty: bool = True,
|
66
|
+
minimum_width: bool = True,
|
67
|
+
justify_last_line: bool = False,
|
68
|
+
break_on_hyphens: bool = True,
|
69
|
+
sizefunc: Optional[Callable[[str], Union[Tuple[Union[int, float], Union[int, float]], int, float]]] = None,
|
70
|
+
) -> None
|
71
|
+
```
|
72
|
+
A class that handles all functions available in this module. Each keyword argument corresponds to its attribute.
|
73
|
+
For example:
|
74
|
+
```py
|
75
|
+
wrapper = TextWrapper(width=100)
|
76
|
+
```
|
77
|
+
is equivalent to:
|
78
|
+
```py
|
79
|
+
wrapper = TextWrapper()
|
80
|
+
wrapper.width = 100
|
81
|
+
```
|
82
|
+
You can reuse [`TextWrapper`](#textwrapper) multiple times or modify its options by assigning new values to its
|
83
|
+
attributes. However, it is recommended not to reuse [`TextWrapper`](#textwrapper) too frequently inside a specific loop,
|
84
|
+
as each attribute has type checking, which may reduce performance.
|
85
|
+
|
86
|
+
<h1></h1>
|
87
|
+
|
88
|
+
### Attributes of [`TextWrapper`](#textwrapper):
|
89
|
+
|
90
|
+
<h1></h1>
|
91
|
+
|
92
|
+
#### **`width`**
|
93
|
+
(Default: `70`) The maximum line length for wrapped text.
|
94
|
+
|
95
|
+
<h1></h1>
|
96
|
+
|
97
|
+
#### **`line_padding`**
|
98
|
+
(Default: `0`) The spacing between wrapped lines.
|
99
|
+
|
100
|
+
<h1></h1>
|
101
|
+
|
102
|
+
#### **`method`**
|
103
|
+
(Default: `'word'`) The wrapping method. Available options: `'mono'` and `'word'`.
|
104
|
+
- `'mono'` method wraps text character by character.
|
105
|
+
- `'word'` method wraps text word by word.
|
106
|
+
|
107
|
+
<h1></h1>
|
108
|
+
|
109
|
+
#### **`alignment`**
|
110
|
+
(Default: `'left'`) The alignment of the wrapped text. Available options: `'left'`, `'center'`, `'right'`,
|
111
|
+
(`'fill'` or `'fill-left'`), `'fill-center'`, and `'fill-right'`.
|
112
|
+
- `'left'`: Aligns text to the start of the line.
|
113
|
+
- `'center'`: Centers text within the line.
|
114
|
+
- `'right'`: Aligns text to the end of the line.
|
115
|
+
- `'fill'` or `'fill-left'`: Justifies text across the width but aligns single-word lines or the last line
|
116
|
+
(if [`justify_last_line`](#justify_last_line) is `False`) to the left.
|
117
|
+
- `'fill-center'` and `'fill-right'` work the same way as `'fill-left'`, aligning text according to their respective
|
118
|
+
names.
|
119
|
+
|
120
|
+
<h1></h1>
|
121
|
+
|
122
|
+
#### **`placeholder`**
|
123
|
+
(Default: `'...'`) The ellipsis used for truncating long lines.
|
124
|
+
|
125
|
+
<h1></h1>
|
126
|
+
|
127
|
+
#### **`fillchar`**
|
128
|
+
(Default: `' '`) The character used for padding.
|
129
|
+
|
130
|
+
<h1></h1>
|
131
|
+
|
132
|
+
#### **`separator`**
|
133
|
+
(Default: `None`) The character used to separate words.
|
134
|
+
- `None`: Uses whitespace as the separator.
|
135
|
+
- `str`: Uses the specified character.
|
136
|
+
- `Iterable`: Uses multiple specified characters.
|
137
|
+
|
138
|
+
<h1></h1>
|
139
|
+
|
140
|
+
#### **`max_lines`**
|
141
|
+
(Default: `None`) The maximum number of wrapped lines.
|
142
|
+
- `None`: No limit on the number of wrapped lines.
|
143
|
+
- `int`: Limits the number of wrapped lines to the specified value. (Ensure that [`width`](#width) is not smaller than
|
144
|
+
the length of [`placeholder`](#placeholder)).
|
145
|
+
|
146
|
+
<h1></h1>
|
147
|
+
|
148
|
+
#### **`preserve_empty`**
|
149
|
+
(Default: `True`) Retains empty lines in the wrapped text.
|
150
|
+
|
151
|
+
<h1></h1>
|
152
|
+
|
153
|
+
#### **`minimum_width`**
|
154
|
+
(Default: `True`) Uses the minimum required line width. Some wrapped lines may be shorter than the specified width, so
|
155
|
+
enabling this attribute removes unnecessary empty space.
|
156
|
+
|
157
|
+
<h1></h1>
|
158
|
+
|
159
|
+
#### **`justify_last_line`**
|
160
|
+
(Default: `False`) Determines whether the last line should also be justified
|
161
|
+
(applies only to `fill-...` alignments).
|
162
|
+
|
163
|
+
<h1></h1>
|
164
|
+
|
165
|
+
#### **`break_on_hyphens`**
|
166
|
+
(Default: `True`) Breaks words at hyphens (-). Example `'self-organization'` becomes `'self-'` and `'organization'`.
|
167
|
+
|
168
|
+
<h1></h1>
|
169
|
+
|
170
|
+
#### **`sizefunc`**
|
171
|
+
(Default: `None`) A function used to calculate the width and height or only the width of each string.
|
172
|
+
|
173
|
+
If the function calculates both width and height, it must return a tuple containing two values:
|
174
|
+
- The width and height of the string.
|
175
|
+
- Both values must be of type `int` or `float`.
|
176
|
+
|
177
|
+
If the function calculates only the width, it must return a single value of type `int` or `float`.
|
178
|
+
|
179
|
+
<h1></h1>
|
180
|
+
|
181
|
+
### Methods of [`TextWrapper`](#textwrapper):
|
182
|
+
|
183
|
+
<h1></h1>
|
184
|
+
|
185
|
+
#### **`copy`**
|
186
|
+
Creates and returns a copy of the [`TextWrapper`](#textwrapper) object.
|
187
|
+
|
188
|
+
<h1></h1>
|
189
|
+
|
190
|
+
#### **`sanitize(text)`**
|
191
|
+
Removes excessive characters from [`separator`](#separator) and replaces them with the [`fillchar`](#fillchar)
|
192
|
+
character.
|
193
|
+
|
194
|
+
For example:
|
195
|
+
```py
|
196
|
+
>>> TextWrapper().sanitize("\tHello World! ")
|
197
|
+
'Hello World!'
|
198
|
+
```
|
199
|
+
|
200
|
+
<h1></h1>
|
201
|
+
|
202
|
+
#### **`wrap(text, return_details=False)`**
|
203
|
+
Returns a list of wrapped text strings. If `return_details=True`, returns a dictionary containing:
|
204
|
+
- `'wrapped'`: A list of wrapped text fragments.
|
205
|
+
- `'indiced'`: A set of indices marking line breaks (starting from `0`, like programming indices).
|
206
|
+
|
207
|
+
For example:
|
208
|
+
```py
|
209
|
+
>>> TextWrapper(width=15).wrap(LOREM_IPSUM_WORDS)
|
210
|
+
['Lorem ipsum', 'odor amet,', 'consectetuer', 'adipiscing', 'elit.']
|
211
|
+
>>> TextWrapper(width=15).wrap(LOREM_IPSUM_WORDS, return_details=True)
|
212
|
+
{'wrapped': ['Lorem ipsum', 'odor amet,', 'consectetuer', 'adipiscing', 'elit.'], 'indiced': {4}}
|
213
|
+
```
|
214
|
+
|
215
|
+
<h1></h1>
|
216
|
+
|
217
|
+
#### **`align(text, return_details=False)`**
|
218
|
+
Returns a list of tuples, where each tuple contains `(x, y, text)`, representing the wrapped text along with its
|
219
|
+
coordinates.
|
220
|
+
> Note: [`sizefunc`](#sizefunc) must return both width and height.
|
221
|
+
|
222
|
+
If `return_details=True`, returns a dictionary containing:
|
223
|
+
- `'aligned'`: A list of wrapped text with coordinate data.
|
224
|
+
- `'wrapped'`: The result from wrap.
|
225
|
+
- `'indiced'`: The indices of line breaks.
|
226
|
+
- `'size'`: The calculated text size.
|
227
|
+
|
228
|
+
For example:
|
229
|
+
```py
|
230
|
+
>>> TextWrapper(width=20).align(LOREM_IPSUM_WORDS)
|
231
|
+
[(0, 0, 'Lorem ipsum odor'), (0, 1, 'amet, consectetuer'), (0, 2, 'adipiscing elit.')]
|
232
|
+
>>> TextWrapper(width=20).align(LOREM_IPSUM_WORDS, return_details=True)
|
233
|
+
{'aligned': [(0, 0, 'Lorem ipsum odor'), (0, 1, 'amet, consectetuer'), (0, 2, 'adipiscing elit.')], 'wrapped': [
|
234
|
+
'Lorem ipsum odor', 'amet, consectetuer', 'adipiscing elit.'], 'indiced': {2}, 'size': (18, 3)}
|
235
|
+
```
|
236
|
+
|
237
|
+
<h1></h1>
|
238
|
+
|
239
|
+
#### **`fillstr(text)`**
|
240
|
+
Returns a string with wrapped text formatted for monospace fonts.
|
241
|
+
> Note: [`width`](#width), [`line_padding`](#line_padding), and the output of [`sizefunc`](#sizefunc) must return `int`,
|
242
|
+
not `float`!
|
243
|
+
|
244
|
+
For example:
|
245
|
+
```py
|
246
|
+
>>> s = TextWrapper(width=20).fillstr(LOREM_IPSUM_WORDS)
|
247
|
+
>>> s
|
248
|
+
'Lorem ipsum odor \namet, consectetuer\nadipiscing elit. '
|
249
|
+
>>> print(s)
|
250
|
+
Lorem ipsum odor
|
251
|
+
amet, consectetuer
|
252
|
+
adipiscing elit.
|
253
|
+
```
|
254
|
+
|
255
|
+
<h1></h1>
|
256
|
+
|
257
|
+
#### **`shorten(text)`**
|
258
|
+
Returns a truncated string if its length exceeds [`width`](#width), appending [`placeholder`](#placeholder) at the end
|
259
|
+
if truncated.
|
260
|
+
|
261
|
+
For example:
|
262
|
+
```py
|
263
|
+
>>> TextWrapper(width=20).shorten(LOREM_IPSUM_WORDS)
|
264
|
+
'Lorem ipsum odor...'
|
265
|
+
```
|
266
|
+
|
267
|
+
<h1></h1>
|
268
|
+
|
269
|
+
# Another examples❓
|
270
|
+
|
271
|
+
## Render a wrap text in PyGame🎮
|
272
|
+
```py
|
273
|
+
from typing import Literal, Optional
|
274
|
+
from txtwrap import align, LOREM_IPSUM_PARAGRAPHS
|
275
|
+
import pygame
|
276
|
+
|
277
|
+
def render_wrap(
|
278
|
+
|
279
|
+
font: pygame.Font,
|
280
|
+
text: str,
|
281
|
+
width: int,
|
282
|
+
antialias: bool,
|
283
|
+
color: pygame.Color,
|
284
|
+
background: Optional[pygame.Color] = None,
|
285
|
+
line_padding: int = 0,
|
286
|
+
method: Literal['word', 'mono'] = 'word',
|
287
|
+
alignment: Literal['left', 'center', 'right', 'fill', 'fill-left', 'fill-center', 'fill-right'] = 'left',
|
288
|
+
placeholder: str = '...',
|
289
|
+
max_lines: Optional[int] = None,
|
290
|
+
preserve_empty: bool = True,
|
291
|
+
minimum_width: bool = True,
|
292
|
+
justify_last_line: bool = False,
|
293
|
+
break_on_hyphens: bool = True
|
294
|
+
|
295
|
+
) -> pygame.Surface:
|
296
|
+
|
297
|
+
align_info = align(
|
298
|
+
text=text,
|
299
|
+
width=width,
|
300
|
+
line_padding=line_padding,
|
301
|
+
method=method,
|
302
|
+
alignment=alignment,
|
303
|
+
placeholder=placeholder,
|
304
|
+
max_lines=max_lines,
|
305
|
+
preserve_empty=preserve_empty,
|
306
|
+
minimum_width=minimum_width,
|
307
|
+
justify_last_line=justify_last_line,
|
308
|
+
break_on_hyphens=break_on_hyphens,
|
309
|
+
return_details=True,
|
310
|
+
sizefunc=font.size
|
311
|
+
)
|
312
|
+
|
313
|
+
surface = pygame.Surface(align_info['size'], pygame.SRCALPHA)
|
314
|
+
|
315
|
+
if background is not None:
|
316
|
+
surface.fill(background)
|
317
|
+
|
318
|
+
for x, y, text in align_info['aligned']:
|
319
|
+
surface.blit(font.render(text, antialias, color), (x, y))
|
320
|
+
|
321
|
+
return surface
|
322
|
+
|
323
|
+
# Example usage:
|
324
|
+
pygame.init()
|
325
|
+
pygame.display.set_caption("Lorem Ipsum")
|
326
|
+
|
327
|
+
running = True
|
328
|
+
width, height = 800, 600
|
329
|
+
screen = pygame.display.set_mode((width, height))
|
330
|
+
clock = pygame.time.Clock()
|
331
|
+
|
332
|
+
surface = render_wrap(
|
333
|
+
font=pygame.font.SysFont('Arial', 18),
|
334
|
+
text=LOREM_IPSUM_PARAGRAPHS,
|
335
|
+
width=width,
|
336
|
+
antialias=True,
|
337
|
+
color='#ffffff',
|
338
|
+
background='#303030',
|
339
|
+
alignment='fill'
|
340
|
+
)
|
341
|
+
|
342
|
+
width_surface, height_surface = surface.get_size()
|
343
|
+
pos = ((width - width_surface) / 2, (height - height_surface) / 2)
|
344
|
+
|
345
|
+
while running:
|
346
|
+
for event in pygame.event.get():
|
347
|
+
if event.type == pygame.QUIT:
|
348
|
+
running = False
|
349
|
+
screen.fill('#000000')
|
350
|
+
screen.blit(surface, pos)
|
351
|
+
pygame.display.flip()
|
352
|
+
clock.tick(60)
|
353
|
+
```
|
354
|
+
|
355
|
+
## Short a long text🔤
|
356
|
+
```py
|
357
|
+
from txtwrap import shorten, LOREM_IPSUM_SENTENCES
|
358
|
+
|
359
|
+
print(shorten(LOREM_IPSUM_SENTENCES, width=50, placeholder='…'))
|
360
|
+
```
|
txtwrap-2.3.0/README.md
ADDED
@@ -0,0 +1,345 @@
|
|
1
|
+
# TxTWrap🔡
|
2
|
+
A tool for wrapping and filling text.🔨
|
3
|
+
|
4
|
+
- `LOREM_IPSUM_WORDS`
|
5
|
+
- `LOREM_IPSUM_SENTENCES`
|
6
|
+
- `LOREM_IPSUM_PARAGRAPHS`
|
7
|
+
- `TextWrapper` (✅ Updated)
|
8
|
+
- `sanitize` (➕ New)
|
9
|
+
- `wrap` (✅ Updated)
|
10
|
+
- `align` (✅ Updated)
|
11
|
+
- `fillstr` (✅ Updated)
|
12
|
+
- `printwrap` (✅ Updated)
|
13
|
+
- `shorten` (✅ Updated)
|
14
|
+
|
15
|
+
# Documents📄
|
16
|
+
This module is inspired by the [`textwrap`](https://docs.python.org/3/library/textwrap.html) module, which provides
|
17
|
+
several useful functions, along with the [`TextWrapper`](#textwrapper), class that handles all available functions.
|
18
|
+
|
19
|
+
The difference between [`txtwrap`](https://pypi.org/project/txtwrap) and
|
20
|
+
[`textwrap`](https://docs.python.org/3/library/textwrap.html) is that this module is designed not only for wrapping and
|
21
|
+
filling monospace fonts but also for other font types, such as Arial, Times New Roman, and more.
|
22
|
+
|
23
|
+
<h1></h1>
|
24
|
+
|
25
|
+
```py
|
26
|
+
LOREM_IPSUM_WORDS
|
27
|
+
LOREM_IPSUM_SENTENCES
|
28
|
+
LOREM_IPSUM_PARAGRAPHS
|
29
|
+
```
|
30
|
+
A collection of words, sentences, and paragraphs that can be used as examples.
|
31
|
+
- `LOREM_IPSUM_WORDS` contains a short Lorem Ipsum sentence.
|
32
|
+
- `LOREM_IPSUM_SENTENCES` contains a slightly longer paragraph.
|
33
|
+
- `LOREM_IPSUM_PARAGRAPHS` contains several longer paragraphs.
|
34
|
+
|
35
|
+
<h1></h1>
|
36
|
+
|
37
|
+
## `TextWrapper`
|
38
|
+
```py
|
39
|
+
class TextWrapper:
|
40
|
+
def __init__(
|
41
|
+
self,
|
42
|
+
width: Union[int, float] = 70,
|
43
|
+
line_padding: Union[int, float] = 0,
|
44
|
+
method: Literal['mono', 'word'] = 'word',
|
45
|
+
alignment: Literal['left', 'center', 'right', 'fill', 'fill-left', 'fill-center', 'fill-right'] = 'left',
|
46
|
+
placeholder: str = '...',
|
47
|
+
fillchar: str = ' ',
|
48
|
+
separator: Optional[Union[str, Iterable[str]]] = None,
|
49
|
+
max_lines: Optional[int] = None,
|
50
|
+
preserve_empty: bool = True,
|
51
|
+
minimum_width: bool = True,
|
52
|
+
justify_last_line: bool = False,
|
53
|
+
break_on_hyphens: bool = True,
|
54
|
+
sizefunc: Optional[Callable[[str], Union[Tuple[Union[int, float], Union[int, float]], int, float]]] = None,
|
55
|
+
) -> None
|
56
|
+
```
|
57
|
+
A class that handles all functions available in this module. Each keyword argument corresponds to its attribute.
|
58
|
+
For example:
|
59
|
+
```py
|
60
|
+
wrapper = TextWrapper(width=100)
|
61
|
+
```
|
62
|
+
is equivalent to:
|
63
|
+
```py
|
64
|
+
wrapper = TextWrapper()
|
65
|
+
wrapper.width = 100
|
66
|
+
```
|
67
|
+
You can reuse [`TextWrapper`](#textwrapper) multiple times or modify its options by assigning new values to its
|
68
|
+
attributes. However, it is recommended not to reuse [`TextWrapper`](#textwrapper) too frequently inside a specific loop,
|
69
|
+
as each attribute has type checking, which may reduce performance.
|
70
|
+
|
71
|
+
<h1></h1>
|
72
|
+
|
73
|
+
### Attributes of [`TextWrapper`](#textwrapper):
|
74
|
+
|
75
|
+
<h1></h1>
|
76
|
+
|
77
|
+
#### **`width`**
|
78
|
+
(Default: `70`) The maximum line length for wrapped text.
|
79
|
+
|
80
|
+
<h1></h1>
|
81
|
+
|
82
|
+
#### **`line_padding`**
|
83
|
+
(Default: `0`) The spacing between wrapped lines.
|
84
|
+
|
85
|
+
<h1></h1>
|
86
|
+
|
87
|
+
#### **`method`**
|
88
|
+
(Default: `'word'`) The wrapping method. Available options: `'mono'` and `'word'`.
|
89
|
+
- `'mono'` method wraps text character by character.
|
90
|
+
- `'word'` method wraps text word by word.
|
91
|
+
|
92
|
+
<h1></h1>
|
93
|
+
|
94
|
+
#### **`alignment`**
|
95
|
+
(Default: `'left'`) The alignment of the wrapped text. Available options: `'left'`, `'center'`, `'right'`,
|
96
|
+
(`'fill'` or `'fill-left'`), `'fill-center'`, and `'fill-right'`.
|
97
|
+
- `'left'`: Aligns text to the start of the line.
|
98
|
+
- `'center'`: Centers text within the line.
|
99
|
+
- `'right'`: Aligns text to the end of the line.
|
100
|
+
- `'fill'` or `'fill-left'`: Justifies text across the width but aligns single-word lines or the last line
|
101
|
+
(if [`justify_last_line`](#justify_last_line) is `False`) to the left.
|
102
|
+
- `'fill-center'` and `'fill-right'` work the same way as `'fill-left'`, aligning text according to their respective
|
103
|
+
names.
|
104
|
+
|
105
|
+
<h1></h1>
|
106
|
+
|
107
|
+
#### **`placeholder`**
|
108
|
+
(Default: `'...'`) The ellipsis used for truncating long lines.
|
109
|
+
|
110
|
+
<h1></h1>
|
111
|
+
|
112
|
+
#### **`fillchar`**
|
113
|
+
(Default: `' '`) The character used for padding.
|
114
|
+
|
115
|
+
<h1></h1>
|
116
|
+
|
117
|
+
#### **`separator`**
|
118
|
+
(Default: `None`) The character used to separate words.
|
119
|
+
- `None`: Uses whitespace as the separator.
|
120
|
+
- `str`: Uses the specified character.
|
121
|
+
- `Iterable`: Uses multiple specified characters.
|
122
|
+
|
123
|
+
<h1></h1>
|
124
|
+
|
125
|
+
#### **`max_lines`**
|
126
|
+
(Default: `None`) The maximum number of wrapped lines.
|
127
|
+
- `None`: No limit on the number of wrapped lines.
|
128
|
+
- `int`: Limits the number of wrapped lines to the specified value. (Ensure that [`width`](#width) is not smaller than
|
129
|
+
the length of [`placeholder`](#placeholder)).
|
130
|
+
|
131
|
+
<h1></h1>
|
132
|
+
|
133
|
+
#### **`preserve_empty`**
|
134
|
+
(Default: `True`) Retains empty lines in the wrapped text.
|
135
|
+
|
136
|
+
<h1></h1>
|
137
|
+
|
138
|
+
#### **`minimum_width`**
|
139
|
+
(Default: `True`) Uses the minimum required line width. Some wrapped lines may be shorter than the specified width, so
|
140
|
+
enabling this attribute removes unnecessary empty space.
|
141
|
+
|
142
|
+
<h1></h1>
|
143
|
+
|
144
|
+
#### **`justify_last_line`**
|
145
|
+
(Default: `False`) Determines whether the last line should also be justified
|
146
|
+
(applies only to `fill-...` alignments).
|
147
|
+
|
148
|
+
<h1></h1>
|
149
|
+
|
150
|
+
#### **`break_on_hyphens`**
|
151
|
+
(Default: `True`) Breaks words at hyphens (-). Example `'self-organization'` becomes `'self-'` and `'organization'`.
|
152
|
+
|
153
|
+
<h1></h1>
|
154
|
+
|
155
|
+
#### **`sizefunc`**
|
156
|
+
(Default: `None`) A function used to calculate the width and height or only the width of each string.
|
157
|
+
|
158
|
+
If the function calculates both width and height, it must return a tuple containing two values:
|
159
|
+
- The width and height of the string.
|
160
|
+
- Both values must be of type `int` or `float`.
|
161
|
+
|
162
|
+
If the function calculates only the width, it must return a single value of type `int` or `float`.
|
163
|
+
|
164
|
+
<h1></h1>
|
165
|
+
|
166
|
+
### Methods of [`TextWrapper`](#textwrapper):
|
167
|
+
|
168
|
+
<h1></h1>
|
169
|
+
|
170
|
+
#### **`copy`**
|
171
|
+
Creates and returns a copy of the [`TextWrapper`](#textwrapper) object.
|
172
|
+
|
173
|
+
<h1></h1>
|
174
|
+
|
175
|
+
#### **`sanitize(text)`**
|
176
|
+
Removes excessive characters from [`separator`](#separator) and replaces them with the [`fillchar`](#fillchar)
|
177
|
+
character.
|
178
|
+
|
179
|
+
For example:
|
180
|
+
```py
|
181
|
+
>>> TextWrapper().sanitize("\tHello World! ")
|
182
|
+
'Hello World!'
|
183
|
+
```
|
184
|
+
|
185
|
+
<h1></h1>
|
186
|
+
|
187
|
+
#### **`wrap(text, return_details=False)`**
|
188
|
+
Returns a list of wrapped text strings. If `return_details=True`, returns a dictionary containing:
|
189
|
+
- `'wrapped'`: A list of wrapped text fragments.
|
190
|
+
- `'indiced'`: A set of indices marking line breaks (starting from `0`, like programming indices).
|
191
|
+
|
192
|
+
For example:
|
193
|
+
```py
|
194
|
+
>>> TextWrapper(width=15).wrap(LOREM_IPSUM_WORDS)
|
195
|
+
['Lorem ipsum', 'odor amet,', 'consectetuer', 'adipiscing', 'elit.']
|
196
|
+
>>> TextWrapper(width=15).wrap(LOREM_IPSUM_WORDS, return_details=True)
|
197
|
+
{'wrapped': ['Lorem ipsum', 'odor amet,', 'consectetuer', 'adipiscing', 'elit.'], 'indiced': {4}}
|
198
|
+
```
|
199
|
+
|
200
|
+
<h1></h1>
|
201
|
+
|
202
|
+
#### **`align(text, return_details=False)`**
|
203
|
+
Returns a list of tuples, where each tuple contains `(x, y, text)`, representing the wrapped text along with its
|
204
|
+
coordinates.
|
205
|
+
> Note: [`sizefunc`](#sizefunc) must return both width and height.
|
206
|
+
|
207
|
+
If `return_details=True`, returns a dictionary containing:
|
208
|
+
- `'aligned'`: A list of wrapped text with coordinate data.
|
209
|
+
- `'wrapped'`: The result from wrap.
|
210
|
+
- `'indiced'`: The indices of line breaks.
|
211
|
+
- `'size'`: The calculated text size.
|
212
|
+
|
213
|
+
For example:
|
214
|
+
```py
|
215
|
+
>>> TextWrapper(width=20).align(LOREM_IPSUM_WORDS)
|
216
|
+
[(0, 0, 'Lorem ipsum odor'), (0, 1, 'amet, consectetuer'), (0, 2, 'adipiscing elit.')]
|
217
|
+
>>> TextWrapper(width=20).align(LOREM_IPSUM_WORDS, return_details=True)
|
218
|
+
{'aligned': [(0, 0, 'Lorem ipsum odor'), (0, 1, 'amet, consectetuer'), (0, 2, 'adipiscing elit.')], 'wrapped': [
|
219
|
+
'Lorem ipsum odor', 'amet, consectetuer', 'adipiscing elit.'], 'indiced': {2}, 'size': (18, 3)}
|
220
|
+
```
|
221
|
+
|
222
|
+
<h1></h1>
|
223
|
+
|
224
|
+
#### **`fillstr(text)`**
|
225
|
+
Returns a string with wrapped text formatted for monospace fonts.
|
226
|
+
> Note: [`width`](#width), [`line_padding`](#line_padding), and the output of [`sizefunc`](#sizefunc) must return `int`,
|
227
|
+
not `float`!
|
228
|
+
|
229
|
+
For example:
|
230
|
+
```py
|
231
|
+
>>> s = TextWrapper(width=20).fillstr(LOREM_IPSUM_WORDS)
|
232
|
+
>>> s
|
233
|
+
'Lorem ipsum odor \namet, consectetuer\nadipiscing elit. '
|
234
|
+
>>> print(s)
|
235
|
+
Lorem ipsum odor
|
236
|
+
amet, consectetuer
|
237
|
+
adipiscing elit.
|
238
|
+
```
|
239
|
+
|
240
|
+
<h1></h1>
|
241
|
+
|
242
|
+
#### **`shorten(text)`**
|
243
|
+
Returns a truncated string if its length exceeds [`width`](#width), appending [`placeholder`](#placeholder) at the end
|
244
|
+
if truncated.
|
245
|
+
|
246
|
+
For example:
|
247
|
+
```py
|
248
|
+
>>> TextWrapper(width=20).shorten(LOREM_IPSUM_WORDS)
|
249
|
+
'Lorem ipsum odor...'
|
250
|
+
```
|
251
|
+
|
252
|
+
<h1></h1>
|
253
|
+
|
254
|
+
# Another examples❓
|
255
|
+
|
256
|
+
## Render a wrap text in PyGame🎮
|
257
|
+
```py
|
258
|
+
from typing import Literal, Optional
|
259
|
+
from txtwrap import align, LOREM_IPSUM_PARAGRAPHS
|
260
|
+
import pygame
|
261
|
+
|
262
|
+
def render_wrap(
|
263
|
+
|
264
|
+
font: pygame.Font,
|
265
|
+
text: str,
|
266
|
+
width: int,
|
267
|
+
antialias: bool,
|
268
|
+
color: pygame.Color,
|
269
|
+
background: Optional[pygame.Color] = None,
|
270
|
+
line_padding: int = 0,
|
271
|
+
method: Literal['word', 'mono'] = 'word',
|
272
|
+
alignment: Literal['left', 'center', 'right', 'fill', 'fill-left', 'fill-center', 'fill-right'] = 'left',
|
273
|
+
placeholder: str = '...',
|
274
|
+
max_lines: Optional[int] = None,
|
275
|
+
preserve_empty: bool = True,
|
276
|
+
minimum_width: bool = True,
|
277
|
+
justify_last_line: bool = False,
|
278
|
+
break_on_hyphens: bool = True
|
279
|
+
|
280
|
+
) -> pygame.Surface:
|
281
|
+
|
282
|
+
align_info = align(
|
283
|
+
text=text,
|
284
|
+
width=width,
|
285
|
+
line_padding=line_padding,
|
286
|
+
method=method,
|
287
|
+
alignment=alignment,
|
288
|
+
placeholder=placeholder,
|
289
|
+
max_lines=max_lines,
|
290
|
+
preserve_empty=preserve_empty,
|
291
|
+
minimum_width=minimum_width,
|
292
|
+
justify_last_line=justify_last_line,
|
293
|
+
break_on_hyphens=break_on_hyphens,
|
294
|
+
return_details=True,
|
295
|
+
sizefunc=font.size
|
296
|
+
)
|
297
|
+
|
298
|
+
surface = pygame.Surface(align_info['size'], pygame.SRCALPHA)
|
299
|
+
|
300
|
+
if background is not None:
|
301
|
+
surface.fill(background)
|
302
|
+
|
303
|
+
for x, y, text in align_info['aligned']:
|
304
|
+
surface.blit(font.render(text, antialias, color), (x, y))
|
305
|
+
|
306
|
+
return surface
|
307
|
+
|
308
|
+
# Example usage:
|
309
|
+
pygame.init()
|
310
|
+
pygame.display.set_caption("Lorem Ipsum")
|
311
|
+
|
312
|
+
running = True
|
313
|
+
width, height = 800, 600
|
314
|
+
screen = pygame.display.set_mode((width, height))
|
315
|
+
clock = pygame.time.Clock()
|
316
|
+
|
317
|
+
surface = render_wrap(
|
318
|
+
font=pygame.font.SysFont('Arial', 18),
|
319
|
+
text=LOREM_IPSUM_PARAGRAPHS,
|
320
|
+
width=width,
|
321
|
+
antialias=True,
|
322
|
+
color='#ffffff',
|
323
|
+
background='#303030',
|
324
|
+
alignment='fill'
|
325
|
+
)
|
326
|
+
|
327
|
+
width_surface, height_surface = surface.get_size()
|
328
|
+
pos = ((width - width_surface) / 2, (height - height_surface) / 2)
|
329
|
+
|
330
|
+
while running:
|
331
|
+
for event in pygame.event.get():
|
332
|
+
if event.type == pygame.QUIT:
|
333
|
+
running = False
|
334
|
+
screen.fill('#000000')
|
335
|
+
screen.blit(surface, pos)
|
336
|
+
pygame.display.flip()
|
337
|
+
clock.tick(60)
|
338
|
+
```
|
339
|
+
|
340
|
+
## Short a long text🔤
|
341
|
+
```py
|
342
|
+
from txtwrap import shorten, LOREM_IPSUM_SENTENCES
|
343
|
+
|
344
|
+
print(shorten(LOREM_IPSUM_SENTENCES, width=50, placeholder='…'))
|
345
|
+
```
|