txtwrap 1.0.0__tar.gz → 1.1.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-1.1.0/PKG-INFO +132 -0
- txtwrap-1.1.0/README.md +118 -0
- {txtwrap-1.0.0 → txtwrap-1.1.0}/setup.py +1 -1
- {txtwrap-1.0.0 → txtwrap-1.1.0}/txtwrap/__init__.py +4 -2
- txtwrap-1.1.0/txtwrap/__main__.py +82 -0
- {txtwrap-1.0.0 → txtwrap-1.1.0}/txtwrap/txtwrap.py +234 -26
- txtwrap-1.1.0/txtwrap.egg-info/PKG-INFO +132 -0
- txtwrap-1.0.0/PKG-INFO +0 -33
- txtwrap-1.0.0/README.md +0 -19
- txtwrap-1.0.0/txtwrap/__main__.py +0 -105
- txtwrap-1.0.0/txtwrap.egg-info/PKG-INFO +0 -33
- {txtwrap-1.0.0 → txtwrap-1.1.0}/MANIFEST.in +0 -0
- {txtwrap-1.0.0 → txtwrap-1.1.0}/setup.cfg +0 -0
- {txtwrap-1.0.0 → txtwrap-1.1.0}/txtwrap.egg-info/SOURCES.txt +0 -0
- {txtwrap-1.0.0 → txtwrap-1.1.0}/txtwrap.egg-info/dependency_links.txt +0 -0
- {txtwrap-1.0.0 → txtwrap-1.1.0}/txtwrap.egg-info/top_level.txt +0 -0
txtwrap-1.1.0/PKG-INFO
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: txtwrap
|
3
|
+
Version: 1.1.0
|
4
|
+
Summary: A simple text wrapping tool.
|
5
|
+
Author: azzammuhyala
|
6
|
+
License: MIT
|
7
|
+
Keywords: wrap,wrapper,wrapping,wrapping tool,text wrap,text wrapper,simple wrap,align,aligner,aligning
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
10
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
12
|
+
Requires-Python: >=3.8
|
13
|
+
Description-Content-Type: text/markdown
|
14
|
+
|
15
|
+
# TxTWrap🔡
|
16
|
+
A tool for wrapping a text.🔨
|
17
|
+
|
18
|
+
> **⚠️All documents are in the each module.⚠️**
|
19
|
+
|
20
|
+
All constants and functions❕:
|
21
|
+
- `LOREM_IPSUM_W`
|
22
|
+
- `LOREM_IPSUM_S`
|
23
|
+
- `LOREM_IPSUM_P`
|
24
|
+
- `mono`
|
25
|
+
- `word`
|
26
|
+
- `wrap`
|
27
|
+
- `align` (Updated!)
|
28
|
+
- `fillstr` (New!)
|
29
|
+
- `printwrap` (New!)
|
30
|
+
- `shorten` (Updated!)
|
31
|
+
|
32
|
+
Mod `python -m txtwrap` Commands❗:
|
33
|
+
```shell
|
34
|
+
python -m txtwrap --help
|
35
|
+
```
|
36
|
+
|
37
|
+
Examples❓:
|
38
|
+
## Render a wrap text in PyGame🎮
|
39
|
+
```py
|
40
|
+
from typing import Literal, Optional
|
41
|
+
from txtwrap import align, LOREM_IPSUM_P
|
42
|
+
import pygame
|
43
|
+
|
44
|
+
def render_wrap(
|
45
|
+
|
46
|
+
font: pygame.font.Font,
|
47
|
+
text: str,
|
48
|
+
width: int,
|
49
|
+
antialias: bool,
|
50
|
+
color: pygame.Color,
|
51
|
+
background: Optional[pygame.Color] = None,
|
52
|
+
linegap: int = 0,
|
53
|
+
alignment: Literal['left', 'center', 'right', 'fill'] = 'left',
|
54
|
+
method: Literal['word', 'mono'] = 'word',
|
55
|
+
use_max_width: bool = True,
|
56
|
+
preserve_empty: bool = True
|
57
|
+
|
58
|
+
) -> pygame.Surface:
|
59
|
+
|
60
|
+
# Only supports in txtwrap 1.1.0+
|
61
|
+
align_info = align(
|
62
|
+
text=text,
|
63
|
+
width=width,
|
64
|
+
linegap=linegap,
|
65
|
+
sizefunc=font.size,
|
66
|
+
method=method,
|
67
|
+
alignment=alignment,
|
68
|
+
use_max_width=use_max_width,
|
69
|
+
preserve_empty=preserve_empty,
|
70
|
+
return_details=True
|
71
|
+
)
|
72
|
+
|
73
|
+
surface = pygame.Surface(align_info['size'], pygame.SRCALPHA)
|
74
|
+
|
75
|
+
if background is not None:
|
76
|
+
surface.fill(background)
|
77
|
+
|
78
|
+
for x, y, text in align_info['aligned']:
|
79
|
+
surface.blit(font.render(text, antialias, color), (x, y))
|
80
|
+
|
81
|
+
return surface
|
82
|
+
|
83
|
+
# Example usage:
|
84
|
+
pygame.init()
|
85
|
+
pygame.display.set_caption("Lorem Ipsum")
|
86
|
+
|
87
|
+
running = True
|
88
|
+
screen = pygame.display.set_mode((600, 510))
|
89
|
+
clock = pygame.time.Clock()
|
90
|
+
surface = render_wrap(
|
91
|
+
font=pygame.font.Font(None, 20),
|
92
|
+
text=LOREM_IPSUM_P,
|
93
|
+
width=screen.get_width(),
|
94
|
+
antialias=True,
|
95
|
+
color='#ffffff',
|
96
|
+
background='#303030',
|
97
|
+
alignment='fill'
|
98
|
+
)
|
99
|
+
|
100
|
+
while running:
|
101
|
+
for event in pygame.event.get():
|
102
|
+
if event.type == pygame.QUIT:
|
103
|
+
running = False
|
104
|
+
screen.fill('#000000')
|
105
|
+
screen.blit(surface, (0, 0))
|
106
|
+
pygame.display.flip()
|
107
|
+
clock.tick(60)
|
108
|
+
```
|
109
|
+
|
110
|
+
## Print a wrap text to terminal🔡
|
111
|
+
```py
|
112
|
+
from txtwrap import printwrap, LOREM_IPSUM_W
|
113
|
+
|
114
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='left')
|
115
|
+
print('=' * 20)
|
116
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='center')
|
117
|
+
print('=' * 20)
|
118
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='right')
|
119
|
+
print('=' * 20)
|
120
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='fill')
|
121
|
+
```
|
122
|
+
|
123
|
+
## Short a long text🔤
|
124
|
+
```py
|
125
|
+
from txtwrap import shorten, LOREM_IPSUM_S
|
126
|
+
|
127
|
+
short_lorem = shorten(LOREM_IPSUM_S, width=20, placeholder='…')
|
128
|
+
test = shorten(' Helllo, \t\r\n World!! \f', width=20, placeholder='…', strip_space=True)
|
129
|
+
|
130
|
+
print(short_lorem)
|
131
|
+
print(test)
|
132
|
+
```
|
txtwrap-1.1.0/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# TxTWrap🔡
|
2
|
+
A tool for wrapping a text.🔨
|
3
|
+
|
4
|
+
> **⚠️All documents are in the each module.⚠️**
|
5
|
+
|
6
|
+
All constants and functions❕:
|
7
|
+
- `LOREM_IPSUM_W`
|
8
|
+
- `LOREM_IPSUM_S`
|
9
|
+
- `LOREM_IPSUM_P`
|
10
|
+
- `mono`
|
11
|
+
- `word`
|
12
|
+
- `wrap`
|
13
|
+
- `align` (Updated!)
|
14
|
+
- `fillstr` (New!)
|
15
|
+
- `printwrap` (New!)
|
16
|
+
- `shorten` (Updated!)
|
17
|
+
|
18
|
+
Mod `python -m txtwrap` Commands❗:
|
19
|
+
```shell
|
20
|
+
python -m txtwrap --help
|
21
|
+
```
|
22
|
+
|
23
|
+
Examples❓:
|
24
|
+
## Render a wrap text in PyGame🎮
|
25
|
+
```py
|
26
|
+
from typing import Literal, Optional
|
27
|
+
from txtwrap import align, LOREM_IPSUM_P
|
28
|
+
import pygame
|
29
|
+
|
30
|
+
def render_wrap(
|
31
|
+
|
32
|
+
font: pygame.font.Font,
|
33
|
+
text: str,
|
34
|
+
width: int,
|
35
|
+
antialias: bool,
|
36
|
+
color: pygame.Color,
|
37
|
+
background: Optional[pygame.Color] = None,
|
38
|
+
linegap: int = 0,
|
39
|
+
alignment: Literal['left', 'center', 'right', 'fill'] = 'left',
|
40
|
+
method: Literal['word', 'mono'] = 'word',
|
41
|
+
use_max_width: bool = True,
|
42
|
+
preserve_empty: bool = True
|
43
|
+
|
44
|
+
) -> pygame.Surface:
|
45
|
+
|
46
|
+
# Only supports in txtwrap 1.1.0+
|
47
|
+
align_info = align(
|
48
|
+
text=text,
|
49
|
+
width=width,
|
50
|
+
linegap=linegap,
|
51
|
+
sizefunc=font.size,
|
52
|
+
method=method,
|
53
|
+
alignment=alignment,
|
54
|
+
use_max_width=use_max_width,
|
55
|
+
preserve_empty=preserve_empty,
|
56
|
+
return_details=True
|
57
|
+
)
|
58
|
+
|
59
|
+
surface = pygame.Surface(align_info['size'], pygame.SRCALPHA)
|
60
|
+
|
61
|
+
if background is not None:
|
62
|
+
surface.fill(background)
|
63
|
+
|
64
|
+
for x, y, text in align_info['aligned']:
|
65
|
+
surface.blit(font.render(text, antialias, color), (x, y))
|
66
|
+
|
67
|
+
return surface
|
68
|
+
|
69
|
+
# Example usage:
|
70
|
+
pygame.init()
|
71
|
+
pygame.display.set_caption("Lorem Ipsum")
|
72
|
+
|
73
|
+
running = True
|
74
|
+
screen = pygame.display.set_mode((600, 510))
|
75
|
+
clock = pygame.time.Clock()
|
76
|
+
surface = render_wrap(
|
77
|
+
font=pygame.font.Font(None, 20),
|
78
|
+
text=LOREM_IPSUM_P,
|
79
|
+
width=screen.get_width(),
|
80
|
+
antialias=True,
|
81
|
+
color='#ffffff',
|
82
|
+
background='#303030',
|
83
|
+
alignment='fill'
|
84
|
+
)
|
85
|
+
|
86
|
+
while running:
|
87
|
+
for event in pygame.event.get():
|
88
|
+
if event.type == pygame.QUIT:
|
89
|
+
running = False
|
90
|
+
screen.fill('#000000')
|
91
|
+
screen.blit(surface, (0, 0))
|
92
|
+
pygame.display.flip()
|
93
|
+
clock.tick(60)
|
94
|
+
```
|
95
|
+
|
96
|
+
## Print a wrap text to terminal🔡
|
97
|
+
```py
|
98
|
+
from txtwrap import printwrap, LOREM_IPSUM_W
|
99
|
+
|
100
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='left')
|
101
|
+
print('=' * 20)
|
102
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='center')
|
103
|
+
print('=' * 20)
|
104
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='right')
|
105
|
+
print('=' * 20)
|
106
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='fill')
|
107
|
+
```
|
108
|
+
|
109
|
+
## Short a long text🔤
|
110
|
+
```py
|
111
|
+
from txtwrap import shorten, LOREM_IPSUM_S
|
112
|
+
|
113
|
+
short_lorem = shorten(LOREM_IPSUM_S, width=20, placeholder='…')
|
114
|
+
test = shorten(' Helllo, \t\r\n World!! \f', width=20, placeholder='…', strip_space=True)
|
115
|
+
|
116
|
+
print(short_lorem)
|
117
|
+
print(test)
|
118
|
+
```
|
@@ -6,11 +6,11 @@ A simple text wrapping tool
|
|
6
6
|
|
7
7
|
from .txtwrap import (
|
8
8
|
LOREM_IPSUM_W, LOREM_IPSUM_S, LOREM_IPSUM_P,
|
9
|
-
mono, word, wrap, align,
|
9
|
+
mono, word, wrap, align, fillstr, printwrap,
|
10
10
|
shorten
|
11
11
|
)
|
12
12
|
|
13
|
-
__version__ = '1.
|
13
|
+
__version__ = '1.1.0'
|
14
14
|
__license__ = 'MIT'
|
15
15
|
__author__ = 'Azzam Muhyala'
|
16
16
|
__all__ = [
|
@@ -21,5 +21,7 @@ __all__ = [
|
|
21
21
|
'word',
|
22
22
|
'wrap',
|
23
23
|
'align',
|
24
|
+
'fillstr',
|
25
|
+
'printwrap',
|
24
26
|
'shorten'
|
25
27
|
]
|
@@ -0,0 +1,82 @@
|
|
1
|
+
from argparse import ArgumentParser
|
2
|
+
from txtwrap import printwrap, shorten
|
3
|
+
|
4
|
+
parser = ArgumentParser(
|
5
|
+
description='Command-line tool for wrapping, aligning, or shortening text.'
|
6
|
+
)
|
7
|
+
|
8
|
+
parser.add_argument(
|
9
|
+
'text',
|
10
|
+
type=str,
|
11
|
+
help='Text to be wrapped, aligned, or shorted'
|
12
|
+
)
|
13
|
+
|
14
|
+
parser.add_argument(
|
15
|
+
'-f', '--fill',
|
16
|
+
type=str,
|
17
|
+
default=' ',
|
18
|
+
metavar='<str 1 length>',
|
19
|
+
help='Fill character (default: space)'
|
20
|
+
)
|
21
|
+
|
22
|
+
parser.add_argument(
|
23
|
+
'-w', '--width',
|
24
|
+
type=int,
|
25
|
+
default=None,
|
26
|
+
metavar='<number>',
|
27
|
+
help='Width of the text wrapping (default: current width terminal or 70)'
|
28
|
+
)
|
29
|
+
|
30
|
+
parser.add_argument(
|
31
|
+
'-m', '--method',
|
32
|
+
type=str,
|
33
|
+
choices={'word', 'mono', 'shorten'},
|
34
|
+
default='word',
|
35
|
+
metavar='{word|mono|shorten}',
|
36
|
+
help='Method to be applied to the text (default: word)'
|
37
|
+
)
|
38
|
+
|
39
|
+
parser.add_argument(
|
40
|
+
'-a', '--alignment',
|
41
|
+
type=str,
|
42
|
+
choices={'left', 'center', 'right', 'fill'},
|
43
|
+
default='left',
|
44
|
+
metavar='{left|center|right|fill}',
|
45
|
+
help='Alignment of the text (default: left)'
|
46
|
+
)
|
47
|
+
|
48
|
+
parser.add_argument(
|
49
|
+
'-n', '--neglect-empty',
|
50
|
+
action='store_false',
|
51
|
+
help='Neglect empty lines in the text'
|
52
|
+
)
|
53
|
+
|
54
|
+
parser.add_argument(
|
55
|
+
'-s', '--start',
|
56
|
+
type=int,
|
57
|
+
default=0,
|
58
|
+
metavar='<number>',
|
59
|
+
help='start index of the text to be shorten (default: 0)'
|
60
|
+
)
|
61
|
+
|
62
|
+
parser.add_argument(
|
63
|
+
'-p', '--placeholder',
|
64
|
+
type=str,
|
65
|
+
default='...',
|
66
|
+
metavar='<str>',
|
67
|
+
help='Placeholder to be used when shortening the text (default: ...)'
|
68
|
+
)
|
69
|
+
|
70
|
+
args = parser.parse_args()
|
71
|
+
|
72
|
+
if args.method == 'shorten':
|
73
|
+
print(shorten(args.text, args.width, args.start, placeholder=args.placeholder))
|
74
|
+
else:
|
75
|
+
printwrap(
|
76
|
+
args.text,
|
77
|
+
fill=args.fill,
|
78
|
+
width=args.width,
|
79
|
+
method=args.method,
|
80
|
+
alignment=args.alignment,
|
81
|
+
preserve_empty=args.neglect_empty
|
82
|
+
)
|
@@ -1,4 +1,5 @@
|
|
1
|
-
from typing import Callable, List, Literal, Tuple, Union
|
1
|
+
from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union
|
2
|
+
from os import get_terminal_size
|
2
3
|
from re import compile
|
3
4
|
|
4
5
|
hyphenated_regex = compile(r'(?<=-)(?=(?!-).)')
|
@@ -197,9 +198,12 @@ def align(
|
|
197
198
|
sizefunc: Callable[[str], Tuple[Union[int, float], Union[int, float]]] = lambda s : (len(s), 1),
|
198
199
|
method: Literal['mono', 'word'] = 'word',
|
199
200
|
alignment: Literal['left', 'center', 'right', 'fill'] = 'left',
|
200
|
-
|
201
|
+
use_max_width: bool = True,
|
202
|
+
preserve_empty: bool = True,
|
203
|
+
return_details: bool = False
|
201
204
|
|
202
|
-
) -> List[Tuple[Union[int, float], Union[int, float], str]
|
205
|
+
) -> List[Union[Tuple[Union[int, float], Union[int, float], str],
|
206
|
+
Dict[Literal['aligned', 'wrapped', 'size'], Any]]]:
|
203
207
|
|
204
208
|
"""
|
205
209
|
Wraps and aligns text within a specified width and yields the position and content of each line.
|
@@ -222,11 +226,21 @@ def align(
|
|
222
226
|
'left', 'center', 'right',
|
223
227
|
or 'fill'.
|
224
228
|
Defaults to 'left'.
|
229
|
+
use_max_width (bool, optional): Whether to use the maximum width of the wrapped text.
|
230
|
+
Defaults to True.
|
225
231
|
preserve_empty (bool, optional): Whether to preserve empty lines. Defaults to True.
|
232
|
+
return_details (bool, optional): Whether to return the aligned text, wrapped text,
|
233
|
+
the maximum width, and the maximum height.
|
234
|
+
Defaults to False.
|
226
235
|
|
227
236
|
Returns:
|
228
|
-
list[tuple[int | float, int | float, str]
|
229
|
-
|
237
|
+
list[tuple[int | float, int | float, str] |
|
238
|
+
dict[Literal['aligned', 'wrapped', 'size'], Any]]: A list of tuples containing the
|
239
|
+
position and content of each line.
|
240
|
+
If return_details, a dictionary
|
241
|
+
containing the wrapped text,
|
242
|
+
the maximum width, and
|
243
|
+
the maximum height is returned.
|
230
244
|
"""
|
231
245
|
|
232
246
|
assert isinstance(linegap, (int, float)), "linegap must be an integer or float"
|
@@ -234,23 +248,44 @@ def align(
|
|
234
248
|
|
235
249
|
assert linegap >= 0, "linegap must be equal to or greater than 0"
|
236
250
|
|
237
|
-
wrapped = []
|
251
|
+
wrapped = wrap(text, width, lambda s : sizefunc(s)[0], method, preserve_empty)
|
252
|
+
size_wrapped = {i: sizefunc(line) for i, line in enumerate(wrapped)}
|
253
|
+
aligned_positions = []
|
238
254
|
offset_y = 0
|
239
255
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
256
|
+
if use_max_width:
|
257
|
+
max_width = max(x for x, _ in size_wrapped.values())
|
258
|
+
|
259
|
+
inforesult = {
|
260
|
+
'aligned': aligned_positions,
|
261
|
+
'wrapped': wrapped
|
262
|
+
}
|
263
|
+
|
264
|
+
if alignment == 'left':
|
265
|
+
for i, line in enumerate(wrapped):
|
266
|
+
_, height_line = size_wrapped[i]
|
267
|
+
aligned_positions.append((0, offset_y, line))
|
268
|
+
offset_y += height_line + linegap
|
269
|
+
|
270
|
+
elif alignment == 'center':
|
271
|
+
for i, line in enumerate(wrapped):
|
272
|
+
width_line, height_line = size_wrapped[i]
|
273
|
+
aligned_positions.append(
|
274
|
+
(((max_width if use_max_width else width) - width_line) / 2, offset_y, line)
|
275
|
+
)
|
276
|
+
offset_y += height_line + linegap
|
249
277
|
|
250
|
-
|
251
|
-
|
278
|
+
elif alignment == 'right':
|
279
|
+
for i, line in enumerate(wrapped):
|
280
|
+
width_line, height_line = size_wrapped[i]
|
281
|
+
aligned_positions.append(
|
282
|
+
((max_width if use_max_width else width) - width_line, offset_y, line)
|
283
|
+
)
|
284
|
+
offset_y += height_line + linegap
|
252
285
|
|
253
|
-
|
286
|
+
elif alignment == 'fill':
|
287
|
+
for i, line in enumerate(wrapped):
|
288
|
+
_, height_line = size_wrapped[i]
|
254
289
|
offset_x = 0
|
255
290
|
words = line.split()
|
256
291
|
total_words = len(words)
|
@@ -264,17 +299,180 @@ def align(
|
|
264
299
|
space_between_words = extra_space
|
265
300
|
|
266
301
|
for i, w in enumerate(words):
|
267
|
-
|
302
|
+
aligned_positions.append((offset_x, offset_y, w))
|
268
303
|
offset_x += widths[i] + space_between_words
|
269
304
|
|
305
|
+
offset_y += height_line + linegap
|
306
|
+
|
307
|
+
else:
|
308
|
+
raise ValueError(f"{alignment=} is invalid, must be 'left', 'center', 'right', or 'fill'")
|
309
|
+
|
310
|
+
if return_details:
|
311
|
+
if alignment == 'fill':
|
312
|
+
if text and len(wrapped) == 1 and ' ' not in wrapped[0]:
|
313
|
+
size_width = size_wrapped[0][0]
|
314
|
+
elif text:
|
315
|
+
size_width = width
|
316
|
+
else:
|
317
|
+
size_width = 0
|
270
318
|
else:
|
271
|
-
|
272
|
-
|
273
|
-
|
319
|
+
size_width = max_width if use_max_width else width
|
320
|
+
|
321
|
+
inforesult['size'] = (size_width, offset_y - linegap)
|
322
|
+
|
323
|
+
return inforesult
|
324
|
+
|
325
|
+
return aligned_positions
|
326
|
+
|
327
|
+
def fillstr(
|
328
|
+
|
329
|
+
text: str,
|
330
|
+
width: Union[int, float] = 70,
|
331
|
+
fill: str = ' ',
|
332
|
+
lenfunc: Callable[[str], Union[int, float]] = len,
|
333
|
+
method: Literal['mono', 'word'] = 'word',
|
334
|
+
alignment: Union[Callable[[str], str], Literal['left', 'center', 'right', 'fill']] = 'left',
|
335
|
+
preserve_empty: bool = True
|
336
|
+
|
337
|
+
) -> str:
|
338
|
+
|
339
|
+
"""
|
340
|
+
String formats a given text to fit within a specified width, using various alignment methods.
|
274
341
|
|
275
|
-
|
342
|
+
Parameters:
|
343
|
+
text (str): The text to be formatted.
|
344
|
+
width (Union[int, float], optional): The width of the formatted text. Defaults to 70.
|
345
|
+
fill (str, optional): The character used to fill the space. Must be a single character.
|
346
|
+
Defaults to ' '.
|
347
|
+
lenfunc (Callable[[str], Union[int, float]], optional): A function to calculate the
|
348
|
+
length of a string. Defaults to len.
|
349
|
+
method (Literal['mono', 'word'], optional): The method to use for wrapping.
|
350
|
+
'mono' for character-based wrapping, 'word'
|
351
|
+
for word-based wrapping. Defaults to 'word'.
|
352
|
+
alignment (Union[Callable[[str], str],
|
353
|
+
Literal['left', 'center', 'right', 'fill']], optional): The alignment of the
|
354
|
+
text. 'left', 'center',
|
355
|
+
'right', or 'fill'.
|
356
|
+
Defaults to 'left'.
|
357
|
+
preserve_empty (bool, optional): Whether to preserve empty lines. Defaults to True.
|
358
|
+
|
359
|
+
Returns:
|
360
|
+
str: The formatted text.
|
361
|
+
"""
|
276
362
|
|
277
|
-
|
363
|
+
assert isinstance(fill, str), "fill must be a string"
|
364
|
+
assert len(fill) == 1, "fill must be a single character"
|
365
|
+
|
366
|
+
wrapped = wrap(text, width, lenfunc, method, preserve_empty)
|
367
|
+
justified_lines = ''
|
368
|
+
|
369
|
+
if callable(alignment):
|
370
|
+
return '\n'.join(alignment(line) for line in wrapped)
|
371
|
+
|
372
|
+
elif alignment == 'left':
|
373
|
+
for line in wrapped:
|
374
|
+
justified_lines += line + fill * (width - lenfunc(line)) + '\n'
|
375
|
+
|
376
|
+
elif alignment == 'center':
|
377
|
+
for line in wrapped:
|
378
|
+
extra_space = width - lenfunc(line)
|
379
|
+
left_space = extra_space // 2
|
380
|
+
justified_lines += fill * left_space + line + fill * (extra_space - left_space) + '\n'
|
381
|
+
|
382
|
+
elif alignment == 'right':
|
383
|
+
for line in wrapped:
|
384
|
+
justified_lines += fill * (width - lenfunc(line)) + line + '\n'
|
385
|
+
|
386
|
+
elif alignment == 'fill':
|
387
|
+
for line in wrapped:
|
388
|
+
words = line.split()
|
389
|
+
total_words = len(words)
|
390
|
+
total_words_width = sum(lenfunc(w) for w in words)
|
391
|
+
extra_space = width - total_words_width
|
392
|
+
|
393
|
+
if total_words > 1:
|
394
|
+
space_between_words = extra_space // (total_words - 1)
|
395
|
+
extra_padding = extra_space % (total_words - 1)
|
396
|
+
else:
|
397
|
+
space_between_words = extra_space
|
398
|
+
extra_padding = 0
|
399
|
+
|
400
|
+
justified_line = ''
|
401
|
+
for i, word in enumerate(words):
|
402
|
+
justified_line += word
|
403
|
+
if i < total_words - 1:
|
404
|
+
justified_line += fill * (space_between_words + (1 if i < extra_padding else 0))
|
405
|
+
|
406
|
+
justified_lines += justified_line + '\n'
|
407
|
+
|
408
|
+
else:
|
409
|
+
raise ValueError(
|
410
|
+
f"{alignment=} is invalid, must be 'left', 'center', 'right', 'fill' or "
|
411
|
+
'a callable function'
|
412
|
+
)
|
413
|
+
|
414
|
+
return justified_lines[:-1]
|
415
|
+
|
416
|
+
def printwrap(
|
417
|
+
|
418
|
+
*values: object,
|
419
|
+
sep: Optional[str] = ' ',
|
420
|
+
end: Optional[str] = '\n',
|
421
|
+
fill: str = ' ',
|
422
|
+
width: Optional[int] = None,
|
423
|
+
lenfunc: Callable[[str], Union[int, float]] = len,
|
424
|
+
method: Literal['word', 'mono'] = 'word',
|
425
|
+
alignment: Union[Callable[[str], str], Literal['left', 'center', 'right', 'fill']] = 'left',
|
426
|
+
file: Optional[object] = None,
|
427
|
+
flush: bool = False,
|
428
|
+
preserve_empty: bool = True
|
429
|
+
|
430
|
+
) -> None:
|
431
|
+
|
432
|
+
"""
|
433
|
+
Print the given values with word wrapping and alignment.
|
434
|
+
|
435
|
+
Parameters:
|
436
|
+
*values (object): Values to be printed.
|
437
|
+
sep (Optional[str]): Separator between values. Default to ' '.
|
438
|
+
end (Optional[str]): String appended after the last value. Default to '\\n'.
|
439
|
+
fill (str): Fill character for padding. Default to ' '.
|
440
|
+
width (Optional[int]): Width of the output. If None, it tries to use the terminal width or
|
441
|
+
defaults to 70.
|
442
|
+
lenfunc (Callable[[str], Union[int, float]]): Function to calculate the length of a string.
|
443
|
+
Default is len.
|
444
|
+
method (Literal['word', 'mono']): The method to use for wrapping. 'mono' for character-based
|
445
|
+
wrapping, 'word' for word-based wrapping.
|
446
|
+
Defaults to 'word'.
|
447
|
+
alignment (Union[Callable[[str], str],
|
448
|
+
Literal['left', 'center', 'right', 'fill']]): Alignment of the text.
|
449
|
+
Default is 'left'.
|
450
|
+
file (Optional[object]): A file-like object (stream) to write the output to.
|
451
|
+
Default is None, which means sys.stdout.
|
452
|
+
flush (bool): Whether to forcibly flush the stream. Default is False.
|
453
|
+
preserve_empty (bool, optional): Whether to preserve empty lines. Defaults to True.
|
454
|
+
"""
|
455
|
+
|
456
|
+
if width is None:
|
457
|
+
try:
|
458
|
+
width = get_terminal_size().columns
|
459
|
+
except:
|
460
|
+
width = 70
|
461
|
+
|
462
|
+
print(
|
463
|
+
fillstr(
|
464
|
+
(' ' if sep is None else sep).join(map(str, values)),
|
465
|
+
width,
|
466
|
+
fill,
|
467
|
+
lenfunc,
|
468
|
+
method,
|
469
|
+
alignment,
|
470
|
+
preserve_empty
|
471
|
+
),
|
472
|
+
end=end,
|
473
|
+
file=file,
|
474
|
+
flush=flush
|
475
|
+
)
|
278
476
|
|
279
477
|
def shorten(
|
280
478
|
|
@@ -282,7 +480,8 @@ def shorten(
|
|
282
480
|
width: Union[int, float] = 70,
|
283
481
|
start: int = 0,
|
284
482
|
lenfunc: Callable[[str], Union[int, float]] = len,
|
285
|
-
placeholder: str = '...'
|
483
|
+
placeholder: str = '...',
|
484
|
+
strip_space: bool = True
|
286
485
|
|
287
486
|
) -> str:
|
288
487
|
|
@@ -297,6 +496,7 @@ def shorten(
|
|
297
496
|
the length of a string. Defaults to len.
|
298
497
|
placeholder (str, optional): The placeholder to append to the shortened text.
|
299
498
|
Defaults to '...'.
|
499
|
+
strip_space (bool, optional): Whether to strip extra spaces in the text. Defaults to True.
|
300
500
|
|
301
501
|
Returns:
|
302
502
|
str: The shortened text with the placeholder appended if necessary.
|
@@ -311,8 +511,13 @@ def shorten(
|
|
311
511
|
assert width >= lenfunc(placeholder), "width must be greater than length of the placeholder"
|
312
512
|
assert start >= 0, "start must be equal to or greater than 0"
|
313
513
|
|
514
|
+
if strip_space:
|
515
|
+
text = ' '.join(text.split())
|
516
|
+
|
314
517
|
if start == 0:
|
315
518
|
current_char = ''
|
519
|
+
elif start >= len(text):
|
520
|
+
return ''
|
316
521
|
else:
|
317
522
|
current_char = placeholder
|
318
523
|
|
@@ -320,6 +525,9 @@ def shorten(
|
|
320
525
|
if lenfunc(current_char + char + placeholder) <= width:
|
321
526
|
current_char += char
|
322
527
|
else:
|
323
|
-
|
528
|
+
current_char += placeholder
|
529
|
+
if lenfunc(current_char) > width:
|
530
|
+
return placeholder
|
531
|
+
return current_char
|
324
532
|
|
325
533
|
return current_char
|
@@ -0,0 +1,132 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: txtwrap
|
3
|
+
Version: 1.1.0
|
4
|
+
Summary: A simple text wrapping tool.
|
5
|
+
Author: azzammuhyala
|
6
|
+
License: MIT
|
7
|
+
Keywords: wrap,wrapper,wrapping,wrapping tool,text wrap,text wrapper,simple wrap,align,aligner,aligning
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
10
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
12
|
+
Requires-Python: >=3.8
|
13
|
+
Description-Content-Type: text/markdown
|
14
|
+
|
15
|
+
# TxTWrap🔡
|
16
|
+
A tool for wrapping a text.🔨
|
17
|
+
|
18
|
+
> **⚠️All documents are in the each module.⚠️**
|
19
|
+
|
20
|
+
All constants and functions❕:
|
21
|
+
- `LOREM_IPSUM_W`
|
22
|
+
- `LOREM_IPSUM_S`
|
23
|
+
- `LOREM_IPSUM_P`
|
24
|
+
- `mono`
|
25
|
+
- `word`
|
26
|
+
- `wrap`
|
27
|
+
- `align` (Updated!)
|
28
|
+
- `fillstr` (New!)
|
29
|
+
- `printwrap` (New!)
|
30
|
+
- `shorten` (Updated!)
|
31
|
+
|
32
|
+
Mod `python -m txtwrap` Commands❗:
|
33
|
+
```shell
|
34
|
+
python -m txtwrap --help
|
35
|
+
```
|
36
|
+
|
37
|
+
Examples❓:
|
38
|
+
## Render a wrap text in PyGame🎮
|
39
|
+
```py
|
40
|
+
from typing import Literal, Optional
|
41
|
+
from txtwrap import align, LOREM_IPSUM_P
|
42
|
+
import pygame
|
43
|
+
|
44
|
+
def render_wrap(
|
45
|
+
|
46
|
+
font: pygame.font.Font,
|
47
|
+
text: str,
|
48
|
+
width: int,
|
49
|
+
antialias: bool,
|
50
|
+
color: pygame.Color,
|
51
|
+
background: Optional[pygame.Color] = None,
|
52
|
+
linegap: int = 0,
|
53
|
+
alignment: Literal['left', 'center', 'right', 'fill'] = 'left',
|
54
|
+
method: Literal['word', 'mono'] = 'word',
|
55
|
+
use_max_width: bool = True,
|
56
|
+
preserve_empty: bool = True
|
57
|
+
|
58
|
+
) -> pygame.Surface:
|
59
|
+
|
60
|
+
# Only supports in txtwrap 1.1.0+
|
61
|
+
align_info = align(
|
62
|
+
text=text,
|
63
|
+
width=width,
|
64
|
+
linegap=linegap,
|
65
|
+
sizefunc=font.size,
|
66
|
+
method=method,
|
67
|
+
alignment=alignment,
|
68
|
+
use_max_width=use_max_width,
|
69
|
+
preserve_empty=preserve_empty,
|
70
|
+
return_details=True
|
71
|
+
)
|
72
|
+
|
73
|
+
surface = pygame.Surface(align_info['size'], pygame.SRCALPHA)
|
74
|
+
|
75
|
+
if background is not None:
|
76
|
+
surface.fill(background)
|
77
|
+
|
78
|
+
for x, y, text in align_info['aligned']:
|
79
|
+
surface.blit(font.render(text, antialias, color), (x, y))
|
80
|
+
|
81
|
+
return surface
|
82
|
+
|
83
|
+
# Example usage:
|
84
|
+
pygame.init()
|
85
|
+
pygame.display.set_caption("Lorem Ipsum")
|
86
|
+
|
87
|
+
running = True
|
88
|
+
screen = pygame.display.set_mode((600, 510))
|
89
|
+
clock = pygame.time.Clock()
|
90
|
+
surface = render_wrap(
|
91
|
+
font=pygame.font.Font(None, 20),
|
92
|
+
text=LOREM_IPSUM_P,
|
93
|
+
width=screen.get_width(),
|
94
|
+
antialias=True,
|
95
|
+
color='#ffffff',
|
96
|
+
background='#303030',
|
97
|
+
alignment='fill'
|
98
|
+
)
|
99
|
+
|
100
|
+
while running:
|
101
|
+
for event in pygame.event.get():
|
102
|
+
if event.type == pygame.QUIT:
|
103
|
+
running = False
|
104
|
+
screen.fill('#000000')
|
105
|
+
screen.blit(surface, (0, 0))
|
106
|
+
pygame.display.flip()
|
107
|
+
clock.tick(60)
|
108
|
+
```
|
109
|
+
|
110
|
+
## Print a wrap text to terminal🔡
|
111
|
+
```py
|
112
|
+
from txtwrap import printwrap, LOREM_IPSUM_W
|
113
|
+
|
114
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='left')
|
115
|
+
print('=' * 20)
|
116
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='center')
|
117
|
+
print('=' * 20)
|
118
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='right')
|
119
|
+
print('=' * 20)
|
120
|
+
printwrap(LOREM_IPSUM_W, width=20, alignment='fill')
|
121
|
+
```
|
122
|
+
|
123
|
+
## Short a long text🔤
|
124
|
+
```py
|
125
|
+
from txtwrap import shorten, LOREM_IPSUM_S
|
126
|
+
|
127
|
+
short_lorem = shorten(LOREM_IPSUM_S, width=20, placeholder='…')
|
128
|
+
test = shorten(' Helllo, \t\r\n World!! \f', width=20, placeholder='…', strip_space=True)
|
129
|
+
|
130
|
+
print(short_lorem)
|
131
|
+
print(test)
|
132
|
+
```
|
txtwrap-1.0.0/PKG-INFO
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: txtwrap
|
3
|
-
Version: 1.0.0
|
4
|
-
Summary: A simple text wrapping tool.
|
5
|
-
Author: azzammuhyala
|
6
|
-
License: MIT
|
7
|
-
Keywords: wrap,wrapper,wrapping,wrapping tool,text wrap,text wrapper,simple wrap,align,aligner,aligning
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Programming Language :: Python :: 3.8
|
10
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
12
|
-
Requires-Python: >=3.8
|
13
|
-
Description-Content-Type: text/markdown
|
14
|
-
|
15
|
-
# TxTWrap 🔤
|
16
|
-
A tool for wrapping a text.🔨
|
17
|
-
|
18
|
-
> **⚠️All documents are in the each module.⚠️**
|
19
|
-
|
20
|
-
All constants and functions❕:
|
21
|
-
- `LOREM_IPSUM_W`
|
22
|
-
- `LOREM_IPSUM_S`
|
23
|
-
- `LOREM_IPSUM_P`
|
24
|
-
- `mono`
|
25
|
-
- `word`
|
26
|
-
- `wrap`
|
27
|
-
- `align`
|
28
|
-
- `shorten`
|
29
|
-
|
30
|
-
Mod `python -m txtwrap` Commands❗:
|
31
|
-
```shell
|
32
|
-
python -m txtwrap --help
|
33
|
-
```
|
txtwrap-1.0.0/README.md
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# TxTWrap 🔤
|
2
|
-
A tool for wrapping a text.🔨
|
3
|
-
|
4
|
-
> **⚠️All documents are in the each module.⚠️**
|
5
|
-
|
6
|
-
All constants and functions❕:
|
7
|
-
- `LOREM_IPSUM_W`
|
8
|
-
- `LOREM_IPSUM_S`
|
9
|
-
- `LOREM_IPSUM_P`
|
10
|
-
- `mono`
|
11
|
-
- `word`
|
12
|
-
- `wrap`
|
13
|
-
- `align`
|
14
|
-
- `shorten`
|
15
|
-
|
16
|
-
Mod `python -m txtwrap` Commands❗:
|
17
|
-
```shell
|
18
|
-
python -m txtwrap --help
|
19
|
-
```
|
@@ -1,105 +0,0 @@
|
|
1
|
-
from argparse import ArgumentParser
|
2
|
-
from os import get_terminal_size
|
3
|
-
from txtwrap import wrap, shorten
|
4
|
-
|
5
|
-
parser = ArgumentParser(
|
6
|
-
description='Command-line tool for wrapping, aligning, or shortening text.'
|
7
|
-
)
|
8
|
-
|
9
|
-
parser.add_argument(
|
10
|
-
'text',
|
11
|
-
type=str,
|
12
|
-
help='Text to be wrapped, aligned, or shorted'
|
13
|
-
)
|
14
|
-
|
15
|
-
try:
|
16
|
-
width = get_terminal_size()[0]
|
17
|
-
except:
|
18
|
-
width = 70
|
19
|
-
|
20
|
-
parser.add_argument(
|
21
|
-
'-w', '--width',
|
22
|
-
type=int,
|
23
|
-
default=width,
|
24
|
-
metavar='<number>',
|
25
|
-
help='Width of the text wrapping (default: current width terminal or 70)'
|
26
|
-
)
|
27
|
-
|
28
|
-
parser.add_argument(
|
29
|
-
'-m', '--method',
|
30
|
-
type=str,
|
31
|
-
choices={'word', 'mono', 'shorten'},
|
32
|
-
default='word',
|
33
|
-
metavar='{word|mono|shorten}',
|
34
|
-
help='Method to be applied to the text (default: word)'
|
35
|
-
)
|
36
|
-
|
37
|
-
parser.add_argument(
|
38
|
-
'-a', '--alignment',
|
39
|
-
type=str,
|
40
|
-
choices={'left', 'center', 'right', 'fill'},
|
41
|
-
default='left',
|
42
|
-
metavar='{left|center|right|fill}',
|
43
|
-
help='Alignment of the text (default: left)'
|
44
|
-
)
|
45
|
-
|
46
|
-
parser.add_argument(
|
47
|
-
'-ne', '--neglect-empty',
|
48
|
-
action='store_false',
|
49
|
-
help='Neglect empty lines in the text'
|
50
|
-
)
|
51
|
-
|
52
|
-
parser.add_argument(
|
53
|
-
'-s', '--start',
|
54
|
-
type=int,
|
55
|
-
default=0,
|
56
|
-
metavar='<number>',
|
57
|
-
help='start index of the text to be shorten (default: 0)'
|
58
|
-
)
|
59
|
-
|
60
|
-
parser.add_argument(
|
61
|
-
'-ph', '--placeholder',
|
62
|
-
type=str,
|
63
|
-
default='...',
|
64
|
-
metavar='<str>',
|
65
|
-
help='Placeholder to be used when shortening the text (default: ...)'
|
66
|
-
)
|
67
|
-
|
68
|
-
args = parser.parse_args()
|
69
|
-
|
70
|
-
if args.method == 'shorten':
|
71
|
-
print(shorten(args.text, args.width, args.start, placeholder=args.placeholder))
|
72
|
-
else:
|
73
|
-
wrapped = wrap(args.text, args.width, method=args.method, preserve_empty=args.neglect_empty)
|
74
|
-
|
75
|
-
if args.alignment == 'left':
|
76
|
-
print('\n'.join(wrapped))
|
77
|
-
elif args.alignment == 'center':
|
78
|
-
print('\n'.join(line.center(args.width) for line in wrapped))
|
79
|
-
elif args.alignment == 'right':
|
80
|
-
print('\n'.join(line.rjust(args.width) for line in wrapped))
|
81
|
-
elif args.alignment == 'fill':
|
82
|
-
justified_lines = ''
|
83
|
-
|
84
|
-
for line in wrapped:
|
85
|
-
words = line.split()
|
86
|
-
total_words = len(words)
|
87
|
-
total_words_width = sum(len(w) for w in words)
|
88
|
-
extra_space = args.width - total_words_width
|
89
|
-
|
90
|
-
if total_words > 1:
|
91
|
-
space_between_words = extra_space // (total_words - 1)
|
92
|
-
extra_padding = extra_space % (total_words - 1)
|
93
|
-
else:
|
94
|
-
space_between_words = extra_space
|
95
|
-
extra_padding = 0
|
96
|
-
|
97
|
-
justified_line = ''
|
98
|
-
for i, word in enumerate(words):
|
99
|
-
justified_line += word
|
100
|
-
if i < total_words - 1:
|
101
|
-
justified_line += ' ' * (space_between_words + (1 if i < extra_padding else 0))
|
102
|
-
|
103
|
-
justified_lines += justified_line + '\n'
|
104
|
-
|
105
|
-
print(justified_lines, end='')
|
@@ -1,33 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: txtwrap
|
3
|
-
Version: 1.0.0
|
4
|
-
Summary: A simple text wrapping tool.
|
5
|
-
Author: azzammuhyala
|
6
|
-
License: MIT
|
7
|
-
Keywords: wrap,wrapper,wrapping,wrapping tool,text wrap,text wrapper,simple wrap,align,aligner,aligning
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Programming Language :: Python :: 3.8
|
10
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
12
|
-
Requires-Python: >=3.8
|
13
|
-
Description-Content-Type: text/markdown
|
14
|
-
|
15
|
-
# TxTWrap 🔤
|
16
|
-
A tool for wrapping a text.🔨
|
17
|
-
|
18
|
-
> **⚠️All documents are in the each module.⚠️**
|
19
|
-
|
20
|
-
All constants and functions❕:
|
21
|
-
- `LOREM_IPSUM_W`
|
22
|
-
- `LOREM_IPSUM_S`
|
23
|
-
- `LOREM_IPSUM_P`
|
24
|
-
- `mono`
|
25
|
-
- `word`
|
26
|
-
- `wrap`
|
27
|
-
- `align`
|
28
|
-
- `shorten`
|
29
|
-
|
30
|
-
Mod `python -m txtwrap` Commands❗:
|
31
|
-
```shell
|
32
|
-
python -m txtwrap --help
|
33
|
-
```
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|