wizlib 3.3.8__py3-none-any.whl → 3.3.10__py3-none-any.whl

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.

Potentially problematic release.


This version of wizlib might be problematic. Click here for more details.

wizlib/ui/shell_ui.py CHANGED
@@ -4,6 +4,7 @@ import sys
4
4
  from wizlib.ui import UI, Chooser, Emphasis
5
5
  from wizlib.ui.shell.line_editor import ShellLineEditor
6
6
  from wizlib.ui.shell import S
7
+ from wizlib.ui.text_wrapper import StreamingTextWrapper
7
8
  import wizlib.io
8
9
 
9
10
  COLOR = {
@@ -23,10 +24,35 @@ class ShellUI(UI):
23
24
 
24
25
  name = "shell"
25
26
 
26
- def send(self, value: str = '', emphasis: Emphasis = Emphasis.GENERAL):
27
- """Output some text"""
28
- sys.stderr.write(COLOR[emphasis] + value + S.RESET + '\n')
29
- sys.stderr.flush()
27
+ def __init__(self):
28
+ super().__init__()
29
+ self._wrapper = None
30
+
31
+ def send(self, value: str = '', emphasis: Emphasis = Emphasis.GENERAL,
32
+ newline: bool = True, wrap: int = 0):
33
+ """Output some text
34
+
35
+ Args:
36
+ value: Text to output
37
+ emphasis: Color/emphasis style
38
+ newline: Whether to append a newline
39
+ wrap: Column width to wrap at (0 = no wrapping)
40
+ """
41
+ if wrap > 0:
42
+ # Initialize wrapper if needed or if width changed
43
+ if self._wrapper is None or self._wrapper.width != wrap:
44
+ self._wrapper = StreamingTextWrapper(
45
+ width=wrap, output_stream=sys.stderr)
46
+
47
+ # Use streaming wrapper
48
+ self._wrapper.write_streaming(value, COLOR[emphasis])
49
+ if newline:
50
+ self._wrapper.write_newline()
51
+ else:
52
+ # Original behavior - no wrapping
53
+ end = '\n' if newline else ''
54
+ sys.stderr.write(COLOR[emphasis] + value + S.RESET + end)
55
+ sys.stderr.flush()
30
56
 
31
57
  def ask(self, value: str):
32
58
  """Prompt for input"""
@@ -0,0 +1,103 @@
1
+ """
2
+ Streaming text wrapper that provides word wrapping with backspace correction
3
+ for a typewriter-like streaming experience.
4
+ """
5
+
6
+ import sys
7
+ from enum import Enum
8
+ from wizlib.ui import Emphasis
9
+
10
+
11
+ class StreamingTextWrapper:
12
+ """Handles streaming text output with word wrapping that uses backspace
13
+ to correct words that would overflow the line boundary.
14
+
15
+ Provides a typewriter-like streaming experience where characters are
16
+ written immediately, but words are moved to the next line if they
17
+ would overflow.
18
+ """
19
+
20
+ def __init__(self, width: int = 80, output_stream=None):
21
+ """Initialize the wrapper.
22
+
23
+ Args:
24
+ width: Column width to wrap at
25
+ output_stream: Stream to write to (defaults to sys.stderr)
26
+ """
27
+ self.width = width
28
+ self.output_stream = output_stream or sys.stderr
29
+ self._current_col = 0
30
+ self._word_buffer = [] # Buffer for current word being streamed
31
+
32
+ def _write_char(self, char: str, color_code: str = ''):
33
+ """Write a single character with optional color."""
34
+ if color_code:
35
+ self.output_stream.write(color_code + char + '\033[0m')
36
+ else:
37
+ self.output_stream.write(char)
38
+ self.output_stream.flush()
39
+
40
+ def _backspace_buffer(self):
41
+ """Backspace over the current word buffer."""
42
+ for _ in range(len(self._word_buffer)):
43
+ self.output_stream.write('\b \b') # backspace, space, backspace
44
+ self.output_stream.flush()
45
+
46
+ def write_streaming(self, text: str, color_code: str = ''):
47
+ """Write text with streaming word wrapping.
48
+
49
+ Args:
50
+ text: Text to output
51
+ color_code: ANSI color code to apply
52
+ """
53
+ for char in text:
54
+ if char == '\n':
55
+ # Explicit newline - flush buffer and reset
56
+ self._word_buffer = []
57
+ self._write_char(char)
58
+ self._current_col = 0
59
+ elif char in ' \t':
60
+ # Word boundary - write the space and clear buffer
61
+ self._word_buffer = []
62
+ self._write_char(char, color_code)
63
+ self._current_col += 1
64
+ else:
65
+ # Regular character - add to buffer and write immediately
66
+ self._word_buffer.append(char)
67
+ self._write_char(char, color_code)
68
+ self._current_col += 1
69
+
70
+ # Check if this character pushed us over the width
71
+ if self._current_col > self.width:
72
+ # Only backspace and wrap if the word can fit on a new line
73
+ # If the word itself is longer than width, let it continue
74
+ if len(self._word_buffer) <= self.width:
75
+ # We've gone over - backspace the whole current word
76
+ self._backspace_buffer()
77
+ self._current_col -= len(self._word_buffer)
78
+
79
+ # Write newline
80
+ self._write_char('\n')
81
+ self._current_col = 0
82
+
83
+ # Rewrite word on new line
84
+ for c in self._word_buffer:
85
+ self._write_char(c, color_code)
86
+ self._current_col += 1
87
+
88
+ def write_newline(self):
89
+ """Write a newline and reset position."""
90
+ self.output_stream.write('\n')
91
+ self.output_stream.flush()
92
+ self._current_col = 0
93
+ self._word_buffer = []
94
+
95
+ def reset_position(self):
96
+ """Reset the column position (useful for explicit positioning)."""
97
+ self._current_col = 0
98
+ self._word_buffer = []
99
+
100
+ @property
101
+ def current_column(self):
102
+ """Get the current column position."""
103
+ return self._current_col
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wizlib
3
- Version: 3.3.8
3
+ Version: 3.3.10
4
4
  Summary: Framework for flexible and powerful command-line applications
5
5
  License: MIT
6
6
  Author: Steampunk Wizard
@@ -13,8 +13,9 @@ wizlib/test_case.py,sha256=T5cX7yWy94hf8JuherDeBCH9Gve5tx2x_PZOte4udC0,1017
13
13
  wizlib/ui/__init__.py,sha256=ve_p_g4aBujh4jIJMgKkJ6cE5PT0aeY5AgRlneDswGg,4241
14
14
  wizlib/ui/shell/__init__.py,sha256=VFtxcvTh5Mhyx6JHbR1C8yIDHlOsrNjdqSVfH5ZPAtQ,1154
15
15
  wizlib/ui/shell/line_editor.py,sha256=OXOgHBhp7EfheZK1mdOykYqB_aXDn2bHA12dvHN9kFg,8087
16
- wizlib/ui/shell_ui.py,sha256=jre7E_5vP_SceNH7GYenfXZpFf4h9Sbh9cWZZycTYk8,1911
16
+ wizlib/ui/shell_ui.py,sha256=zsqmfL5LTnH_yqfqHUmBKhkZdb5cjRWL96vmfTrAn3U,2855
17
+ wizlib/ui/text_wrapper.py,sha256=WYL59E9cMRv0gI2Yhrc5GJTvstRZO86uYUD7lmDiwjM,3812
17
18
  wizlib/ui_handler.py,sha256=JoZadtw9DKAtGvHKP3_BJF2NaYqmcQYNdsY4PeRnOjg,634
18
- wizlib-3.3.8.dist-info/METADATA,sha256=w0tyNEY4z8Vm_tPJKmfqxlkAJ0S_ikDlzMHTon_J55c,995
19
- wizlib-3.3.8.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
20
- wizlib-3.3.8.dist-info/RECORD,,
19
+ wizlib-3.3.10.dist-info/METADATA,sha256=s7L0Q0x7p3Wi0-hTGlD0z2cz0XqcyAbe14YNzErmUJs,996
20
+ wizlib-3.3.10.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
21
+ wizlib-3.3.10.dist-info/RECORD,,