txtwrap 1.1.1__tar.gz → 1.2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: txtwrap
3
- Version: 1.1.1
3
+ Version: 1.2.0
4
4
  Summary: A simple text wrapping tool.
5
5
  Author: azzammuhyala
6
6
  License: MIT
@@ -18,16 +18,18 @@ A tool for wrapping a text.🔨
18
18
  > **⚠️All documents are in the each module.⚠️**
19
19
 
20
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`
29
- - `printwrap`
30
- - `shorten`
21
+ - `LOREM_IPSUM_WORDS` (same as `LOREM_IPSUM_W`)
22
+ - `LOREM_IPSUM_SENTENCES` (same as `LOREM_IPSUM_S`)
23
+ - `LOREM_IPSUM_PARAGRAPHS` (same as `LOREM_IPSUM_P`)
24
+ - `mono` (Fixed)
25
+ - `word` (Fixed)
26
+ - `wrap` (Fixed)
27
+ - `align` (Updated)
28
+ - `fillstr` (Updated)
29
+ - `printwrap` (Updated)
30
+ - `indent` (New)
31
+ - `dedent` (New)
32
+ - `shorten` (Fixed)
31
33
 
32
34
  Mod `python -m txtwrap` Commands❗:
33
35
  ```shell
@@ -38,7 +40,7 @@ Examples❓:
38
40
  ## Render a wrap text in PyGame🎮
39
41
  ```py
40
42
  from typing import Literal, Optional
41
- from txtwrap import align, LOREM_IPSUM_P
43
+ from txtwrap import align, LOREM_IPSUM_PARAGRAPHS
42
44
  import pygame
43
45
 
44
46
  def render_wrap(
@@ -57,9 +59,8 @@ def render_wrap(
57
59
 
58
60
  ) -> pygame.Surface:
59
61
 
60
- # Only supports in txtwrap 1.1.1+
61
62
  align_info = align(
62
- text=text,
63
+ text_or_wrapped=str(text),
63
64
  width=width,
64
65
  linegap=linegap,
65
66
  sizefunc=font.size,
@@ -90,7 +91,7 @@ screen = pygame.display.set_mode((wscrn, hscrn))
90
91
  clock = pygame.time.Clock()
91
92
  surface = render_wrap(
92
93
  font=pygame.font.Font(None, 20),
93
- text=LOREM_IPSUM_P,
94
+ text=LOREM_IPSUM_PARAGRAPHS,
94
95
  width=wscrn,
95
96
  antialias=True,
96
97
  color='#ffffff',
@@ -113,24 +114,22 @@ while running:
113
114
 
114
115
  ## Print a wrap text to terminal🔡
115
116
  ```py
116
- # Only supports in txtwrap 1.1.0+
117
- from txtwrap import printwrap, LOREM_IPSUM_W
117
+ from txtwrap import printwrap, LOREM_IPSUM_WORDS
118
118
 
119
- printwrap(LOREM_IPSUM_W, width=20, alignment='left')
119
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='left')
120
120
  print('=' * 20)
121
- printwrap(LOREM_IPSUM_W, width=20, alignment='center')
121
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='center')
122
122
  print('=' * 20)
123
- printwrap(LOREM_IPSUM_W, width=20, alignment='right')
123
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='right')
124
124
  print('=' * 20)
125
- printwrap(LOREM_IPSUM_W, width=20, alignment='fill')
125
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='fill')
126
126
  ```
127
127
 
128
128
  ## Short a long text🔤
129
129
  ```py
130
- from txtwrap import shorten, LOREM_IPSUM_S
130
+ from txtwrap import shorten, LOREM_IPSUM_SENTENCES
131
131
 
132
- short_lorem = shorten(LOREM_IPSUM_S, width=20, placeholder='…')
133
- # Only supports in txtwrap 1.1.0+
132
+ short_lorem = shorten(LOREM_IPSUM_SENTENCES, width=20, placeholder='…')
134
133
  test = shorten(' Helllo, \t\r\n World!! \f', width=20, placeholder='…', strip_space=True)
135
134
 
136
135
  print(short_lorem)
@@ -143,18 +142,17 @@ print(test)
143
142
 
144
143
  from re import compile
145
144
  from random import randint
146
- from txtwrap import printwrap, LOREM_IPSUM_P
145
+ from txtwrap import printwrap, LOREM_IPSUM_PARAGRAPHS
147
146
 
148
147
  # Set the text to be printed here
149
- text = LOREM_IPSUM_P
148
+ text = LOREM_IPSUM_PARAGRAPHS
150
149
 
151
- remove_ansi_regex = compile(r'\x1b\[[0-9;]*[mK]').sub
150
+ remove_ansi_regex = compile(r'\x1b\[(K|.*?m)').sub
152
151
 
153
152
  def ralen(s: str) -> int:
154
153
  return len(remove_ansi_regex('', s))
155
154
 
156
155
  while True:
157
- # Only supports in txtwrap 1.1.0+
158
156
  printwrap(
159
157
  ''.join(f'\x1b[{randint(31, 36)}m{char}' for char in text) + '\x1b[0m',
160
158
  end='\x1b[H\x1b[J',
@@ -4,16 +4,18 @@ A tool for wrapping a text.🔨
4
4
  > **⚠️All documents are in the each module.⚠️**
5
5
 
6
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`
15
- - `printwrap`
16
- - `shorten`
7
+ - `LOREM_IPSUM_WORDS` (same as `LOREM_IPSUM_W`)
8
+ - `LOREM_IPSUM_SENTENCES` (same as `LOREM_IPSUM_S`)
9
+ - `LOREM_IPSUM_PARAGRAPHS` (same as `LOREM_IPSUM_P`)
10
+ - `mono` (Fixed)
11
+ - `word` (Fixed)
12
+ - `wrap` (Fixed)
13
+ - `align` (Updated)
14
+ - `fillstr` (Updated)
15
+ - `printwrap` (Updated)
16
+ - `indent` (New)
17
+ - `dedent` (New)
18
+ - `shorten` (Fixed)
17
19
 
18
20
  Mod `python -m txtwrap` Commands❗:
19
21
  ```shell
@@ -24,7 +26,7 @@ Examples❓:
24
26
  ## Render a wrap text in PyGame🎮
25
27
  ```py
26
28
  from typing import Literal, Optional
27
- from txtwrap import align, LOREM_IPSUM_P
29
+ from txtwrap import align, LOREM_IPSUM_PARAGRAPHS
28
30
  import pygame
29
31
 
30
32
  def render_wrap(
@@ -43,9 +45,8 @@ def render_wrap(
43
45
 
44
46
  ) -> pygame.Surface:
45
47
 
46
- # Only supports in txtwrap 1.1.1+
47
48
  align_info = align(
48
- text=text,
49
+ text_or_wrapped=str(text),
49
50
  width=width,
50
51
  linegap=linegap,
51
52
  sizefunc=font.size,
@@ -76,7 +77,7 @@ screen = pygame.display.set_mode((wscrn, hscrn))
76
77
  clock = pygame.time.Clock()
77
78
  surface = render_wrap(
78
79
  font=pygame.font.Font(None, 20),
79
- text=LOREM_IPSUM_P,
80
+ text=LOREM_IPSUM_PARAGRAPHS,
80
81
  width=wscrn,
81
82
  antialias=True,
82
83
  color='#ffffff',
@@ -99,24 +100,22 @@ while running:
99
100
 
100
101
  ## Print a wrap text to terminal🔡
101
102
  ```py
102
- # Only supports in txtwrap 1.1.0+
103
- from txtwrap import printwrap, LOREM_IPSUM_W
103
+ from txtwrap import printwrap, LOREM_IPSUM_WORDS
104
104
 
105
- printwrap(LOREM_IPSUM_W, width=20, alignment='left')
105
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='left')
106
106
  print('=' * 20)
107
- printwrap(LOREM_IPSUM_W, width=20, alignment='center')
107
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='center')
108
108
  print('=' * 20)
109
- printwrap(LOREM_IPSUM_W, width=20, alignment='right')
109
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='right')
110
110
  print('=' * 20)
111
- printwrap(LOREM_IPSUM_W, width=20, alignment='fill')
111
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='fill')
112
112
  ```
113
113
 
114
114
  ## Short a long text🔤
115
115
  ```py
116
- from txtwrap import shorten, LOREM_IPSUM_S
116
+ from txtwrap import shorten, LOREM_IPSUM_SENTENCES
117
117
 
118
- short_lorem = shorten(LOREM_IPSUM_S, width=20, placeholder='…')
119
- # Only supports in txtwrap 1.1.0+
118
+ short_lorem = shorten(LOREM_IPSUM_SENTENCES, width=20, placeholder='…')
120
119
  test = shorten(' Helllo, \t\r\n World!! \f', width=20, placeholder='…', strip_space=True)
121
120
 
122
121
  print(short_lorem)
@@ -129,18 +128,17 @@ print(test)
129
128
 
130
129
  from re import compile
131
130
  from random import randint
132
- from txtwrap import printwrap, LOREM_IPSUM_P
131
+ from txtwrap import printwrap, LOREM_IPSUM_PARAGRAPHS
133
132
 
134
133
  # Set the text to be printed here
135
- text = LOREM_IPSUM_P
134
+ text = LOREM_IPSUM_PARAGRAPHS
136
135
 
137
- remove_ansi_regex = compile(r'\x1b\[[0-9;]*[mK]').sub
136
+ remove_ansi_regex = compile(r'\x1b\[(K|.*?m)').sub
138
137
 
139
138
  def ralen(s: str) -> int:
140
139
  return len(remove_ansi_regex('', s))
141
140
 
142
141
  while True:
143
- # Only supports in txtwrap 1.1.0+
144
142
  printwrap(
145
143
  ''.join(f'\x1b[{randint(31, 36)}m{char}' for char in text) + '\x1b[0m',
146
144
  end='\x1b[H\x1b[J',
@@ -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.1.1',
8
+ version='1.2.0',
9
9
  description='A simple text wrapping tool.',
10
10
  long_description=long_description,
11
11
  long_description_content_type='text/markdown',
@@ -6,8 +6,9 @@ A simple text wrapping tool
6
6
 
7
7
  from .txtwrap import (
8
8
  version,
9
- LOREM_IPSUM_W, LOREM_IPSUM_S, LOREM_IPSUM_P,
9
+ LOREM_IPSUM_WORDS, LOREM_IPSUM_SENTENCES, LOREM_IPSUM_PARAGRAPHS,
10
10
  mono, word, wrap, align, fillstr, printwrap,
11
+ indent, dedent,
11
12
  shorten
12
13
  )
13
14
 
@@ -15,14 +16,16 @@ __version__ = version
15
16
  __author__ = 'azzammuhyala'
16
17
  __license__ = 'MIT'
17
18
  __all__ = [
18
- 'LOREM_IPSUM_W',
19
- 'LOREM_IPSUM_S',
20
- 'LOREM_IPSUM_P',
19
+ 'LOREM_IPSUM_WORDS',
20
+ 'LOREM_IPSUM_SENTENCES',
21
+ 'LOREM_IPSUM_PARAGRAPHS',
21
22
  'mono',
22
23
  'word',
23
24
  'wrap',
24
25
  'align',
25
26
  'fillstr',
26
27
  'printwrap',
28
+ 'indent',
29
+ 'dedent',
27
30
  'shorten'
28
31
  ]
@@ -1,8 +1,19 @@
1
1
  from argparse import ArgumentParser
2
- from txtwrap import version, printwrap, shorten
2
+ from os import name, get_terminal_size
3
+ from txtwrap import version, printwrap, indent, dedent, shorten
4
+
5
+ if name == 'nt':
6
+ pyname = 'python|py'
7
+ elif name == 'posix':
8
+ pyname = 'python3'
9
+ else:
10
+ pyname = 'python'
3
11
 
4
12
  parser = ArgumentParser(
5
- description='Command-line tool for wrapping, aligning, or shortening text.'
13
+ prog='txtwrap',
14
+ description='Command-line tool for wrapping, aligning, or shortening text.',
15
+ epilog=f'for example: {pyname} -m txtwrap "Lorem ipsum odor amet, consectetuer adipiscing '
16
+ 'elit." -w 20 -m word -a center'
6
17
  )
7
18
 
8
19
  parser.add_argument(
@@ -37,9 +48,9 @@ parser.add_argument(
37
48
  parser.add_argument(
38
49
  '-m', '--method',
39
50
  type=str,
40
- choices={'word', 'mono', 'shorten'},
51
+ choices={'word', 'mono', 'indent', 'dedent', 'shorten'},
41
52
  default='word',
42
- metavar='{word|mono|shorten}',
53
+ metavar='{word|mono|indent|dedent|shorten}',
43
54
  help='Method to be applied to the text (default: "word")'
44
55
  )
45
56
 
@@ -58,6 +69,14 @@ parser.add_argument(
58
69
  help='Neglect empty lines in the text'
59
70
  )
60
71
 
72
+ parser.add_argument(
73
+ '-x', '--prefix',
74
+ type=str,
75
+ default=None,
76
+ metavar='<str>',
77
+ help='Prefix to be added (indent) or remove (dedent) to the text'
78
+ )
79
+
61
80
  parser.add_argument(
62
81
  '-s', '--start',
63
82
  type=int,
@@ -82,15 +101,18 @@ parser.add_argument(
82
101
 
83
102
  args = parser.parse_args()
84
103
 
85
- if args.method == 'shorten':
86
- from os import get_terminal_size
87
-
104
+ if args.method == 'indent':
105
+ if args.prefix is None:
106
+ raise ValueError('The prefix (-x, --prefix) is required for the indent method')
107
+ print(indent(args.text, args.prefix))
108
+ elif args.method == 'dedent':
109
+ print(dedent(args.text, args.prefix))
110
+ elif args.method == 'shorten':
88
111
  if args.width is None:
89
112
  try:
90
113
  args.width = get_terminal_size().columns
91
114
  except:
92
115
  args.width = 70
93
-
94
116
  print(
95
117
  shorten(
96
118
  text=args.text,
@@ -1,47 +1,46 @@
1
- from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union
1
+ from typing import Any, Callable, Dict, List, Literal, Optional, Sequence, Tuple, Union
2
2
  from os import get_terminal_size
3
3
  from re import compile
4
4
 
5
5
  hyphenated_regex = compile(r'(?<=-)(?=(?!-).)')
6
- version = '1.1.1'
7
-
8
- LOREM_IPSUM_W = 'Lorem ipsum odor amet, consectetuer adipiscing elit.'
9
- LOREM_IPSUM_S = ('Lorem ipsum odor amet, consectetuer adipiscing elit. In malesuada eros natoque '
10
- 'urna felis diam aptent donec. Cubilia libero morbi fusce tempus, luctus aenean '
11
- 'augue. Mus senectus rutrum phasellus fusce dictum platea. Eros a integer nec '
12
- 'fusce erat urna.')
13
- LOREM_IPSUM_P = ('Lorem ipsum odor amet, consectetuer adipiscing elit. Nulla porta ex condimentum '
14
- 'velit facilisi; consequat congue. Tristique duis sociosqu aliquam semper sit id. '
15
- 'Nisi morbi purus, nascetur elit pellentesque venenatis. Velit commodo molestie '
16
- 'potenti placerat faucibus convallis. Himenaeos dapibus ipsum natoque nam dapibus '
17
- 'habitasse diam. Viverra ac porttitor cras tempor cras. Pharetra habitant nibh '
18
- 'dui ipsum scelerisque cras? Efficitur phasellus etiam congue taciti tortor quam. '
19
- 'Volutpat quam vulputate condimentum hendrerit justo congue iaculis nisl nullam.'
20
- '\n\nInceptos tempus nostra fringilla arcu; tellus blandit facilisi risus. Platea '
21
- 'bibendum tristique lectus nunc placerat id aliquam. Eu arcu nisl mattis potenti '
22
- 'elementum. Dignissim vivamus montes volutpat litora felis fusce ultrices. '
23
- 'Vulputate magna nascetur bibendum inceptos scelerisque morbi posuere. Consequat '
24
- 'dolor netus augue augue tristique curabitur habitasse bibendum. Consectetur est '
25
- 'per eros semper, magnis interdum libero. Arcu adipiscing litora metus fringilla '
26
- 'varius gravida congue tellus adipiscing. Blandit nulla mauris nullam ante metus '
27
- 'curae scelerisque.\n\nSem varius sodales ut volutpat imperdiet turpis primis '
28
- 'nullam. At gravida tincidunt phasellus lacus duis integer eros penatibus. '
29
- 'Interdum mauris molestie posuere nascetur dignissim himenaeos; magna et quisque. '
30
- 'Dignissim malesuada etiam donec vehicula aliquet bibendum. Magna dapibus sapien '
31
- 'semper parturient id dis? Pretium orci ante leo, porta tincidunt molestie. '
32
- 'Malesuada dictumst commodo consequat interdum nisi fusce cras rhoncus feugiat.'
33
- '\n\nHimenaeos mattis commodo suspendisse maecenas cras arcu. Habitasse id '
34
- 'facilisi praesent justo molestie felis luctus suspendisse. Imperdiet ipsum '
35
- 'praesent nunc mauris mattis curabitur. Et consectetur morbi auctor feugiat enim '
36
- 'ridiculus arcu. Ultricies magna blandit eget; vivamus sollicitudin nisl proin. '
37
- 'Sollicitudin sociosqu et finibus elit vestibulum sapien nec odio euismod. Turpis '
38
- 'eleifend amet quis auctor cursus. Vehicula pharetra sapien praesent amet purus '
39
- 'ante. Risus blandit cubilia lorem hendrerit penatibus in magnis.\n\nAmet posuere '
40
- 'nunc; maecenas consequat risus potenti. Volutpat leo lacinia sapien nulla '
41
- 'sagittis dignissim mauris ultrices aliquet. Nisi pretium interdum luctus donec '
42
- 'magna suscipit. Dapibus tristique felis natoque malesuada augue? Justo faucibus '
43
- 'tincidunt congue arcu sem; fusce aliquet proin. Commodo neque nibh; tempus ad '
44
- 'tortor netus. Mattis ultricies nec maximus porttitor non mauris?')
6
+ version = '1.2.0'
7
+
8
+ LOREM_IPSUM_WORDS = 'Lorem ipsum odor amet, consectetuer adipiscing elit.'
9
+ LOREM_IPSUM_SENTENCES = (
10
+ 'Lorem ipsum odor amet, consectetuer adipiscing elit. In malesuada eros natoque urna felis '
11
+ 'diam aptent donec. Cubilia libero morbi fusce tempus, luctus aenean augue. Mus senectus '
12
+ 'rutrum phasellus fusce dictum platea. Eros a integer nec fusce erat urna.'
13
+ )
14
+ LOREM_IPSUM_PARAGRAPHS = (
15
+ 'Lorem ipsum odor amet, consectetuer adipiscing elit. Nulla porta ex condimentum velit '
16
+ 'facilisi; consequat congue. Tristique duis sociosqu aliquam semper sit id. Nisi morbi purus, '
17
+ 'nascetur elit pellentesque venenatis. Velit commodo molestie potenti placerat faucibus '
18
+ 'convallis. Himenaeos dapibus ipsum natoque nam dapibus habitasse diam. Viverra ac porttitor '
19
+ 'cras tempor cras. Pharetra habitant nibh dui ipsum scelerisque cras? Efficitur phasellus '
20
+ 'etiam congue taciti tortor quam. Volutpat quam vulputate condimentum hendrerit justo congue '
21
+ 'iaculis nisl nullam.\n\nInceptos tempus nostra fringilla arcu; tellus blandit facilisi risus. '
22
+ 'Platea bibendum tristique lectus nunc placerat id aliquam. Eu arcu nisl mattis potenti '
23
+ 'elementum. Dignissim vivamus montes volutpat litora felis fusce ultrices. Vulputate magna '
24
+ 'nascetur bibendum inceptos scelerisque morbi posuere. Consequat dolor netus augue augue '
25
+ 'tristique curabitur habitasse bibendum. Consectetur est per eros semper, magnis interdum '
26
+ 'libero. Arcu adipiscing litora metus fringilla varius gravida congue tellus adipiscing. '
27
+ 'Blandit nulla mauris nullam ante metus curae scelerisque.\n\nSem varius sodales ut volutpat '
28
+ 'imperdiet turpis primis nullam. At gravida tincidunt phasellus lacus duis integer eros '
29
+ 'penatibus. Interdum mauris molestie posuere nascetur dignissim himenaeos; magna et quisque. '
30
+ 'Dignissim malesuada etiam donec vehicula aliquet bibendum. Magna dapibus sapien semper '
31
+ 'parturient id dis? Pretium orci ante leo, porta tincidunt molestie. Malesuada dictumst '
32
+ 'commodo consequat interdum nisi fusce cras rhoncus feugiat.\n\nHimenaeos mattis commodo '
33
+ 'suspendisse maecenas cras arcu. Habitasse id facilisi praesent justo molestie felis luctus '
34
+ 'suspendisse. Imperdiet ipsum praesent nunc mauris mattis curabitur. Et consectetur morbi '
35
+ 'auctor feugiat enim ridiculus arcu. Ultricies magna blandit eget; vivamus sollicitudin nisl '
36
+ 'proin. Sollicitudin sociosqu et finibus elit vestibulum sapien nec odio euismod. Turpis '
37
+ 'eleifend amet quis auctor cursus. Vehicula pharetra sapien praesent amet purus ante. Risus '
38
+ 'blandit cubilia lorem hendrerit penatibus in magnis.\n\nAmet posuere nunc; maecenas consequat '
39
+ 'risus potenti. Volutpat leo lacinia sapien nulla sagittis dignissim mauris ultrices aliquet. '
40
+ 'Nisi pretium interdum luctus donec magna suscipit. Dapibus tristique felis natoque malesuada '
41
+ 'augue? Justo faucibus tincidunt congue arcu sem; fusce aliquet proin. Commodo neque nibh; '
42
+ 'tempus ad tortor netus. Mattis ultricies nec maximus porttitor non mauris?'
43
+ )
45
44
 
46
45
  def mono(
47
46
 
@@ -64,11 +63,14 @@ def mono(
64
63
  list[str]: A list of strings, where each string is a line of the wrapped text.
65
64
  """
66
65
 
67
- assert isinstance(text, str), "text must be a string"
68
- assert isinstance(width, (int, float)), "width must be an integer or float"
69
- assert callable(lenfunc), "lenfunc must be a callable function"
70
-
71
- assert width > 0, "width must be greater than 0"
66
+ if not isinstance(text, str):
67
+ raise TypeError("text must be a string")
68
+ if not isinstance(width, (int, float)):
69
+ raise TypeError("width must be an integer or float")
70
+ if not callable(lenfunc):
71
+ raise TypeError("lenfunc must be a callable function")
72
+ if width <= 0:
73
+ raise ValueError("width must be greater than 0")
72
74
 
73
75
  parts = []
74
76
  current_char = ''
@@ -106,11 +108,14 @@ def word(
106
108
  list[str]: A list of strings, where each string is a line of wrapped text.
107
109
  """
108
110
 
109
- assert isinstance(text, str), "text must be a string"
110
- assert isinstance(width, (int, float)), "width must be an integer or float"
111
- assert callable(lenfunc), "lenfunc must be a callable function"
112
-
113
- assert width > 0, "width must be greater than 0"
111
+ if not isinstance(text, str):
112
+ raise TypeError("text must be a string")
113
+ if not isinstance(width, (int, float)):
114
+ raise TypeError("width must be an integer or float")
115
+ if not callable(lenfunc):
116
+ raise TypeError("lenfunc must be a callable function")
117
+ if width <= 0:
118
+ raise ValueError("width must be greater than 0")
114
119
 
115
120
  lines = []
116
121
  current_line = ''
@@ -167,11 +172,14 @@ def wrap(
167
172
  list[str]: A list of wrapped lines.
168
173
  """
169
174
 
170
- assert isinstance(text, str), "text must be a string"
171
- assert isinstance(width, (int, float)), "width must be an integer or float"
172
- assert callable(lenfunc), "lenfunc must be a callable function"
173
-
174
- assert width > 0, "width must be greater than 0"
175
+ if not isinstance(text, str):
176
+ raise TypeError("text must be a string")
177
+ if not isinstance(width, (int, float)):
178
+ raise TypeError("width must be an integer or float")
179
+ if not callable(lenfunc):
180
+ raise TypeError("lenfunc must be a callable function")
181
+ if width <= 0:
182
+ raise ValueError("width must be greater than 0")
175
183
 
176
184
  wrapped_lines = []
177
185
 
@@ -193,7 +201,7 @@ def wrap(
193
201
 
194
202
  def align(
195
203
 
196
- text: str,
204
+ text_or_wrapped: Union[str, Sequence[str]],
197
205
  width: Union[int, float] = 70,
198
206
  linegap: Union[int, float] = 0,
199
207
  sizefunc: Callable[[str], Tuple[Union[int, float], Union[int, float]]] = lambda s : (len(s), 1),
@@ -210,7 +218,8 @@ def align(
210
218
  Wraps and aligns text within a specified width and yields the position and content of each line.
211
219
 
212
220
  Parameters:
213
- text (str): The text to be wrapped and aligned.
221
+ text_or_wrapped (str | Sequence[str]): The text to be wrapped and aligned, or a sequence of
222
+ wrapped lines.
214
223
  width (int | float, optional): The maximum width of each line. Defaults to 70.
215
224
  linegap (int | float, optional): The vertical gap between lines. Defaults to 0.
216
225
  sizefunc (Callable[[str], tuple[int | float, int | float]], optional): A function that
@@ -235,20 +244,28 @@ def align(
235
244
  Defaults to False.
236
245
 
237
246
  Returns:
238
- list[tuple[int | float, int | float, str] |
239
- dict[Literal['aligned', 'wrapped', 'size'], Any]]: A list of tuples containing the
240
- position and content of each line.
241
- If return_details, a dictionary
242
- containing the wrapped text, and
243
- the size is returned.
247
+ list[tuple[int | float, int | float, str]] |
248
+ dict[Literal['aligned', 'wrapped', 'size'], Any]: A list of tuples containing the position
249
+ and content of each line.
250
+ If return_details, a dictionary containing
251
+ the wrapped text, and the size is
252
+ returned.
244
253
  """
245
254
 
246
- assert isinstance(linegap, (int, float)), "linegap must be an integer or float"
247
- assert callable(sizefunc), "sizefunc must be a callable function"
248
-
249
- assert linegap >= 0, "linegap must be equal to or greater than 0"
255
+ if not isinstance(linegap, (int, float)):
256
+ raise TypeError("linegap must be an integer or a float")
257
+ if not callable(sizefunc):
258
+ raise TypeError("sizefunc must be a callable function")
259
+ if linegap < 0:
260
+ raise ValueError("linegap must be equal to or greater than 0")
261
+
262
+ if isinstance(text_or_wrapped, str):
263
+ wrapped = wrap(text_or_wrapped, width, lambda s : sizefunc(s)[0], method, preserve_empty)
264
+ elif isinstance(text_or_wrapped, Sequence):
265
+ wrapped = text_or_wrapped
266
+ else:
267
+ raise TypeError("text_or_wrapped must be a string or a sequence of strings")
250
268
 
251
- wrapped = wrap(text, width, lambda s : sizefunc(s)[0], method, preserve_empty)
252
269
  size_wrapped = {i: sizefunc(line) for i, line in enumerate(wrapped)}
253
270
  aligned_positions = []
254
271
  offset_y = 0
@@ -306,7 +323,7 @@ def align(
306
323
  if use_min_width and alignment == 'fill':
307
324
  if no_spaces:
308
325
  size_width = max_width
309
- elif text:
326
+ elif text_or_wrapped:
310
327
  size_width = width
311
328
  else:
312
329
  size_width = 0
@@ -323,10 +340,10 @@ def align(
323
340
 
324
341
  def fillstr(
325
342
 
326
- text: str,
327
- width: Union[int, float] = 70,
343
+ text_or_wrapped: Union[str, Sequence[str]],
344
+ width: int = 70,
328
345
  fill: str = ' ',
329
- lenfunc: Callable[[str], Union[int, float]] = len,
346
+ lenfunc: Callable[[str], int] = len,
330
347
  method: Literal['mono', 'word'] = 'word',
331
348
  alignment: Union[Callable[[str], str], Literal['left', 'center', 'right', 'fill']] = 'left',
332
349
  preserve_empty: bool = True
@@ -337,30 +354,39 @@ def fillstr(
337
354
  String formats a given text to fit within a specified width, using various alignment methods.
338
355
 
339
356
  Parameters:
340
- text (str): The text to be formatted.
341
- width (Union[int, float], optional): The width of the formatted text. Defaults to 70.
357
+ text_or_wrapped (str | Sequence[str]): The text to be formatted, or a sequence of wrapped
358
+ lines.
359
+ width (int, optional): The width of the formatted text. Defaults to 70.
342
360
  fill (str, optional): The character used to fill the space. Must be a single character.
343
361
  Defaults to ' '.
344
- lenfunc (Callable[[str], Union[int, float]], optional): A function to calculate the
345
- length of a string. Defaults to len.
362
+ lenfunc (Callable[[str], int], optional): A function to calculate the length of a string.
363
+ Defaults to len.
346
364
  method (Literal['mono', 'word'], optional): The method to use for wrapping.
347
365
  'mono' for character-based wrapping, 'word'
348
366
  for word-based wrapping. Defaults to 'word'.
349
- alignment (Union[Callable[[str], str],
350
- Literal['left', 'center', 'right', 'fill']], optional): The alignment of the
351
- text. 'left', 'center',
352
- 'right', or 'fill'.
353
- Defaults to 'left'.
367
+ alignment (Callable[[str], str] |
368
+ Literal['left', 'center', 'right', 'fill'], optional): The alignment of the
369
+ text. 'left', 'center',
370
+ 'right', or 'fill'.
371
+ Defaults to 'left'.
354
372
  preserve_empty (bool, optional): Whether to preserve empty lines. Defaults to True.
355
373
 
356
374
  Returns:
357
375
  str: The formatted text.
358
376
  """
359
377
 
360
- assert isinstance(fill, str), "fill must be a string"
361
- assert len(fill) == 1, "fill must be a single character"
378
+ if not isinstance(fill, str):
379
+ raise TypeError("fill must be a string")
380
+ if lenfunc(fill) != 1:
381
+ raise ValueError("fill must be a single character")
382
+
383
+ if isinstance(text_or_wrapped, str):
384
+ wrapped = wrap(text_or_wrapped, width, lenfunc, method, preserve_empty)
385
+ elif isinstance(text_or_wrapped, Sequence):
386
+ wrapped = text_or_wrapped
387
+ else:
388
+ raise TypeError("text_or_wrapped must be a string or a sequence of strings")
362
389
 
363
- wrapped = wrap(text, width, lenfunc, method, preserve_empty)
364
390
  justified_lines = ''
365
391
 
366
392
  if callable(alignment):
@@ -417,12 +443,13 @@ def printwrap(
417
443
  end: Optional[str] = '\n',
418
444
  fill: str = ' ',
419
445
  width: Optional[int] = None,
420
- lenfunc: Callable[[str], Union[int, float]] = len,
446
+ lenfunc: Callable[[str], int] = len,
421
447
  method: Literal['word', 'mono'] = 'word',
422
448
  alignment: Union[Callable[[str], str], Literal['left', 'center', 'right', 'fill']] = 'left',
423
449
  file: Optional[object] = None,
424
450
  flush: bool = False,
425
- preserve_empty: bool = True
451
+ preserve_empty: bool = True,
452
+ is_wrapped: bool = False
426
453
 
427
454
  ) -> None:
428
455
 
@@ -436,18 +463,19 @@ def printwrap(
436
463
  fill (str): Fill character for padding. Default to ' '.
437
464
  width (Optional[int]): Width of the output. If None, it tries to use the terminal width or
438
465
  defaults to 70.
439
- lenfunc (Callable[[str], Union[int, float]]): Function to calculate the length of a string.
440
- Default is len.
466
+ lenfunc (Callable[[str], int]): Function to calculate the length of a string.
467
+ Default is len.
441
468
  method (Literal['word', 'mono']): The method to use for wrapping. 'mono' for character-based
442
469
  wrapping, 'word' for word-based wrapping.
443
470
  Defaults to 'word'.
444
- alignment (Union[Callable[[str], str],
445
- Literal['left', 'center', 'right', 'fill']]): Alignment of the text.
446
- Default is 'left'.
471
+ alignment (Callable[[str], str] |
472
+ Literal['left', 'center', 'right', 'fill']): Alignment of the text.
473
+ Default is 'left'.
447
474
  file (Optional[object]): A file-like object (stream) to write the output to.
448
475
  Default is None, which means sys.stdout.
449
476
  flush (bool): Whether to forcibly flush the stream. Default is False.
450
477
  preserve_empty (bool, optional): Whether to preserve empty lines. Defaults to True.
478
+ is_wrapped (bool, optional): Whether the values are already wrapped. Defaults to False.
451
479
  """
452
480
 
453
481
  if width is None:
@@ -456,9 +484,11 @@ def printwrap(
456
484
  except:
457
485
  width = 70
458
486
 
487
+ map_values = map(str, values)
488
+
459
489
  print(
460
490
  fillstr(
461
- (' ' if sep is None else sep).join(map(str, values)),
491
+ map_values if is_wrapped else (' ' if sep is None else sep).join(map_values),
462
492
  width,
463
493
  fill,
464
494
  lenfunc,
@@ -471,6 +501,70 @@ def printwrap(
471
501
  flush=flush
472
502
  )
473
503
 
504
+ def indent(
505
+
506
+ text: str,
507
+ prefix: str,
508
+ predicate: Callable[[str], bool] = lambda line: line.strip()
509
+
510
+ ) -> str:
511
+
512
+ """
513
+ Adds a specified prefix to each line of the given text that satisfies the predicate.
514
+
515
+ Parameters:
516
+ text (str): The input text to be processed.
517
+ prefix (str): The prefix to add to each line.
518
+ predicate (Callable[[str], bool], optional): A function that determines whether a line
519
+ should be prefixed. Defaults to a lambda
520
+ function that returns True for non-empty lines.
521
+
522
+ Returns:
523
+ str: The processed text with the prefix added to each line that satisfies the predicate.
524
+ """
525
+
526
+ if not isinstance(text, str):
527
+ raise TypeError("text must be a string")
528
+ if not isinstance(prefix, str):
529
+ raise TypeError("prefix must be a string")
530
+ if not callable(predicate):
531
+ raise TypeError("predicate must be a callable function")
532
+
533
+ return '\n'.join(prefix + line for line in text.splitlines() if predicate(line))
534
+
535
+ def dedent(
536
+
537
+ text: str,
538
+ prefix: Optional[str] = None,
539
+ predicate: Callable[[str], bool] = lambda line: line.strip()
540
+
541
+ ) -> str:
542
+
543
+ """
544
+ Remove any leading whitespace from each line in the given text.
545
+
546
+ Parameters:
547
+ text (str): The input text from which to remove leading whitespace.
548
+ prefix (Optional[str], optional): A prefix to remove from the start of each line.
549
+ Defaults to None (remove all leading whitespace).
550
+ predicate (Callable[[str], bool], optional): A function that determines whether a line
551
+ should be processed. Defaults to a
552
+ lambda function that returns True for
553
+ non-empty lines.
554
+
555
+ Returns:
556
+ str: The text with leading whitespace removed from each line.
557
+ """
558
+
559
+ if not isinstance(text, str):
560
+ raise TypeError("text must be a string")
561
+ if not isinstance(prefix, (str, type(None))):
562
+ raise TypeError("prefix must be a string")
563
+ if not callable(predicate):
564
+ raise TypeError("predicate must be a callable function")
565
+
566
+ return '\n'.join(line.lstrip(prefix) for line in text.splitlines() if predicate(line))
567
+
474
568
  def shorten(
475
569
 
476
570
  text: str,
@@ -499,14 +593,20 @@ def shorten(
499
593
  str: The shortened text with the placeholder appended if necessary.
500
594
  """
501
595
 
502
- assert isinstance(text, str), "text must be a string"
503
- assert isinstance(width, (int, float)), "width must be an integer or float"
504
- assert isinstance(start, int), "start must be an integer"
505
- assert callable(lenfunc), "lenfunc must be a callable function"
506
- assert isinstance(placeholder, str), "placeholder must be a string"
507
-
508
- assert width >= lenfunc(placeholder), "width must be greater than length of the placeholder"
509
- assert start >= 0, "start must be equal to or greater than 0"
596
+ if not isinstance(text, str):
597
+ raise TypeError("text must be a string")
598
+ if not isinstance(width, (int, float)):
599
+ raise TypeError("width must be an integer or float")
600
+ if not isinstance(start, int):
601
+ raise TypeError("start must be an integer")
602
+ if not callable(lenfunc):
603
+ raise TypeError("lenfunc must be a callable function")
604
+ if not isinstance(placeholder, str):
605
+ raise TypeError("placeholder must be a string")
606
+ if width < lenfunc(placeholder):
607
+ raise ValueError("width must be greater than length of the placeholder")
608
+ if start < 0:
609
+ raise ValueError("start must be equal to or greater than 0")
510
610
 
511
611
  if strip_space:
512
612
  text = ' '.join(text.split())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: txtwrap
3
- Version: 1.1.1
3
+ Version: 1.2.0
4
4
  Summary: A simple text wrapping tool.
5
5
  Author: azzammuhyala
6
6
  License: MIT
@@ -18,16 +18,18 @@ A tool for wrapping a text.🔨
18
18
  > **⚠️All documents are in the each module.⚠️**
19
19
 
20
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`
29
- - `printwrap`
30
- - `shorten`
21
+ - `LOREM_IPSUM_WORDS` (same as `LOREM_IPSUM_W`)
22
+ - `LOREM_IPSUM_SENTENCES` (same as `LOREM_IPSUM_S`)
23
+ - `LOREM_IPSUM_PARAGRAPHS` (same as `LOREM_IPSUM_P`)
24
+ - `mono` (Fixed)
25
+ - `word` (Fixed)
26
+ - `wrap` (Fixed)
27
+ - `align` (Updated)
28
+ - `fillstr` (Updated)
29
+ - `printwrap` (Updated)
30
+ - `indent` (New)
31
+ - `dedent` (New)
32
+ - `shorten` (Fixed)
31
33
 
32
34
  Mod `python -m txtwrap` Commands❗:
33
35
  ```shell
@@ -38,7 +40,7 @@ Examples❓:
38
40
  ## Render a wrap text in PyGame🎮
39
41
  ```py
40
42
  from typing import Literal, Optional
41
- from txtwrap import align, LOREM_IPSUM_P
43
+ from txtwrap import align, LOREM_IPSUM_PARAGRAPHS
42
44
  import pygame
43
45
 
44
46
  def render_wrap(
@@ -57,9 +59,8 @@ def render_wrap(
57
59
 
58
60
  ) -> pygame.Surface:
59
61
 
60
- # Only supports in txtwrap 1.1.1+
61
62
  align_info = align(
62
- text=text,
63
+ text_or_wrapped=str(text),
63
64
  width=width,
64
65
  linegap=linegap,
65
66
  sizefunc=font.size,
@@ -90,7 +91,7 @@ screen = pygame.display.set_mode((wscrn, hscrn))
90
91
  clock = pygame.time.Clock()
91
92
  surface = render_wrap(
92
93
  font=pygame.font.Font(None, 20),
93
- text=LOREM_IPSUM_P,
94
+ text=LOREM_IPSUM_PARAGRAPHS,
94
95
  width=wscrn,
95
96
  antialias=True,
96
97
  color='#ffffff',
@@ -113,24 +114,22 @@ while running:
113
114
 
114
115
  ## Print a wrap text to terminal🔡
115
116
  ```py
116
- # Only supports in txtwrap 1.1.0+
117
- from txtwrap import printwrap, LOREM_IPSUM_W
117
+ from txtwrap import printwrap, LOREM_IPSUM_WORDS
118
118
 
119
- printwrap(LOREM_IPSUM_W, width=20, alignment='left')
119
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='left')
120
120
  print('=' * 20)
121
- printwrap(LOREM_IPSUM_W, width=20, alignment='center')
121
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='center')
122
122
  print('=' * 20)
123
- printwrap(LOREM_IPSUM_W, width=20, alignment='right')
123
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='right')
124
124
  print('=' * 20)
125
- printwrap(LOREM_IPSUM_W, width=20, alignment='fill')
125
+ printwrap(LOREM_IPSUM_WORDS, width=20, alignment='fill')
126
126
  ```
127
127
 
128
128
  ## Short a long text🔤
129
129
  ```py
130
- from txtwrap import shorten, LOREM_IPSUM_S
130
+ from txtwrap import shorten, LOREM_IPSUM_SENTENCES
131
131
 
132
- short_lorem = shorten(LOREM_IPSUM_S, width=20, placeholder='…')
133
- # Only supports in txtwrap 1.1.0+
132
+ short_lorem = shorten(LOREM_IPSUM_SENTENCES, width=20, placeholder='…')
134
133
  test = shorten(' Helllo, \t\r\n World!! \f', width=20, placeholder='…', strip_space=True)
135
134
 
136
135
  print(short_lorem)
@@ -143,18 +142,17 @@ print(test)
143
142
 
144
143
  from re import compile
145
144
  from random import randint
146
- from txtwrap import printwrap, LOREM_IPSUM_P
145
+ from txtwrap import printwrap, LOREM_IPSUM_PARAGRAPHS
147
146
 
148
147
  # Set the text to be printed here
149
- text = LOREM_IPSUM_P
148
+ text = LOREM_IPSUM_PARAGRAPHS
150
149
 
151
- remove_ansi_regex = compile(r'\x1b\[[0-9;]*[mK]').sub
150
+ remove_ansi_regex = compile(r'\x1b\[(K|.*?m)').sub
152
151
 
153
152
  def ralen(s: str) -> int:
154
153
  return len(remove_ansi_regex('', s))
155
154
 
156
155
  while True:
157
- # Only supports in txtwrap 1.1.0+
158
156
  printwrap(
159
157
  ''.join(f'\x1b[{randint(31, 36)}m{char}' for char in text) + '\x1b[0m',
160
158
  end='\x1b[H\x1b[J',
File without changes
File without changes