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 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
+ ```
@@ -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
+ ```
@@ -5,7 +5,7 @@ with open('README.md', encoding='utf-8') as readme:
5
5
 
6
6
  setup(
7
7
  name='txtwrap',
8
- version='1.0.0',
8
+ version='1.1.0',
9
9
  description='A simple text wrapping tool.',
10
10
  long_description=long_description,
11
11
  long_description_content_type='text/markdown',
@@ -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.0.0'
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
- preserve_empty: bool = True
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]]: A list of tuples containing the position and
229
- content of each line.
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
- for line in wrap(text, width, lambda s : sizefunc(s)[0], method, preserve_empty):
241
-
242
- width_line, height_line = sizefunc(line)
243
-
244
- if alignment == 'left':
245
- wrapped.append((0, offset_y, line))
246
-
247
- elif alignment == 'center':
248
- wrapped.append(((width - width_line) / 2, offset_y, line))
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
- elif alignment == 'right':
251
- wrapped.append((width - width_line, offset_y, line))
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
- elif alignment == 'fill':
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
- wrapped.append((offset_x, offset_y, w))
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
- raise ValueError(
272
- f"{alignment=} is invalid, must be 'left', 'center', 'right', or 'fill'"
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
- offset_y += height_line + linegap
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
- return wrapped
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
- return current_char + placeholder
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