plotext-plus 1.0.1__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.
@@ -0,0 +1,136 @@
1
+ # /usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # This file contains the output handling system using chuk-term
5
+ # It provides both the traditional direct output and new banner-based output modes
6
+
7
+ import sys
8
+ from chuk_term import ui
9
+ from rich.panel import Panel
10
+ from rich.console import Console
11
+ from rich.text import Text
12
+
13
+
14
+ class PlotextOutput:
15
+ """
16
+ Unified output handler for plotext that supports both traditional
17
+ terminal output and chuk-term enhanced output with banners and themes.
18
+ """
19
+
20
+ def __init__(self, use_banners=False, banner_title=None):
21
+ self.use_banners = use_banners
22
+ self.banner_title = banner_title or "Plotext Chart"
23
+ self._buffer = []
24
+ self.console = Console()
25
+
26
+ def write(self, content):
27
+ """
28
+ Main output method that handles both traditional and banner-based output.
29
+
30
+ Args:
31
+ content (str): The content to output (typically the chart canvas)
32
+ """
33
+ if self.use_banners:
34
+ self._write_with_banner(content)
35
+ else:
36
+ self._write_direct(content)
37
+
38
+ def _write_direct(self, content):
39
+ """Traditional direct output to stdout (maintains backward compatibility)"""
40
+ sys.stdout.write(content)
41
+
42
+ def _write_with_banner(self, content):
43
+ """Output content within a chuk-term banner/panel using Rich panels"""
44
+ # Rich panels need consistent line widths for proper alignment
45
+ # We need to ensure all lines have exactly the same visible width
46
+
47
+ from rich.text import Text
48
+
49
+ # Convert content to Rich Text object to properly handle ANSI codes
50
+ # This ensures consistent width calculations
51
+ rich_text = Text.from_ansi(content)
52
+
53
+ # Create a Rich panel with the processed content
54
+ panel = Panel(
55
+ rich_text,
56
+ title=f"📊 {self.banner_title}",
57
+ border_style="bright_blue",
58
+ padding=(0, 1),
59
+ expand=False # Don't auto-expand, use content width
60
+ )
61
+
62
+ # Use Rich console to print the panel
63
+ self.console.print() # Add spacing before
64
+ self.console.print(panel)
65
+ self.console.print() # Add spacing after
66
+
67
+ def _clean_ansi_codes(self, content):
68
+ """Remove ANSI escape codes for cleaner display in Rich panels"""
69
+ import re
70
+ # This removes basic ANSI codes but preserves the chart structure
71
+ ansi_escape = re.compile(r'\x1b\[[0-9;]*[a-zA-Z]')
72
+ return ansi_escape.sub('', content)
73
+
74
+ def set_banner_mode(self, enabled, title=None):
75
+ """Enable or disable banner mode"""
76
+ self.use_banners = enabled
77
+ if title:
78
+ self.banner_title = title
79
+
80
+ def info(self, message):
81
+ """Output informational message using chuk-term"""
82
+ ui.info(message)
83
+
84
+ def success(self, message):
85
+ """Output success message using chuk-term"""
86
+ ui.success(message)
87
+
88
+ def warning(self, message):
89
+ """Output warning message using chuk-term"""
90
+ ui.warning(message)
91
+
92
+ def error(self, message):
93
+ """Output error message using chuk-term"""
94
+ ui.error(message)
95
+
96
+
97
+ # Global output instance
98
+ _output = PlotextOutput()
99
+
100
+ def write(string):
101
+ """
102
+ The main write function used by plotext (maintains API compatibility).
103
+ This replaces the original write function in _utility.py
104
+ """
105
+ _output.write(string)
106
+
107
+ def set_output_mode(use_banners=False, banner_title=None):
108
+ """
109
+ Configure output mode for plotext.
110
+
111
+ Args:
112
+ use_banners (bool): Whether to use chuk-term banners
113
+ banner_title (str): Title for the banner (optional)
114
+ """
115
+ _output.set_banner_mode(use_banners, banner_title)
116
+
117
+ def get_output_instance():
118
+ """Get the global output instance for advanced usage"""
119
+ return _output
120
+
121
+ # Convenience functions for chuk-term output
122
+ def info(message):
123
+ """Output info message via chuk-term"""
124
+ _output.info(message)
125
+
126
+ def success(message):
127
+ """Output success message via chuk-term"""
128
+ _output.success(message)
129
+
130
+ def warning(message):
131
+ """Output warning message via chuk-term"""
132
+ _output.warning(message)
133
+
134
+ def error(message):
135
+ """Output error message via chuk-term"""
136
+ _output.error(message)
plotext_plus/_shtab.py ADDED
@@ -0,0 +1,9 @@
1
+ # added by user @Freed-Wu as a replacement for package shtab if not present and in particular its method add_argument_to
2
+
3
+ FILE = None
4
+ DIRECTORY = DIR = None
5
+
6
+ def add_argument_to(parser, *args, **kwargs):
7
+ from argparse import Action
8
+ Action.complete = None
9
+ return parser
@@ -0,0 +1,343 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Plotext Theme Library - Compatible with chuk-term themes
4
+ Provides color schemes and styling that match chuk-term's visual themes.
5
+ """
6
+
7
+ from plotext_plus._dict import no_color, color_sequence
8
+
9
+ # Color definitions used across themes
10
+ rgb_colors = {
11
+ # Chuk-term compatible colors
12
+ 'bright_green': (0, 255, 0),
13
+ 'bright_red': (255, 0, 0),
14
+ 'bright_yellow': (255, 255, 0),
15
+ 'bright_cyan': (0, 255, 255),
16
+ 'bright_white': (255, 255, 255),
17
+ 'bright_blue': (0, 100, 255),
18
+ 'bright_magenta': (255, 0, 255),
19
+
20
+ 'dark_green': (0, 128, 0),
21
+ 'dark_red': (128, 0, 0),
22
+ 'dark_goldenrod': (184, 134, 11),
23
+ 'dark_cyan': (0, 139, 139),
24
+ 'dark_blue': (0, 0, 139),
25
+ 'dark_magenta': (139, 0, 139),
26
+
27
+ # Dracula theme colors
28
+ 'dracula_background': (40, 42, 54),
29
+ 'dracula_foreground': (248, 248, 242),
30
+ 'dracula_cyan': (139, 233, 253),
31
+ 'dracula_green': (80, 250, 123),
32
+ 'dracula_orange': (255, 184, 108),
33
+ 'dracula_pink': (255, 121, 198),
34
+ 'dracula_purple': (189, 147, 249),
35
+
36
+ # Solarized colors
37
+ 'sol_base03': (0, 43, 54), # darkest
38
+ 'sol_base02': (7, 54, 66),
39
+ 'sol_base01': (88, 110, 117), # dark gray
40
+ 'sol_base00': (101, 123, 131), # light gray
41
+ 'sol_base0': (131, 148, 150), # main text (dark)
42
+ 'sol_base1': (147, 161, 161), # secondary text
43
+ 'sol_base2': (238, 232, 213), # background highlights
44
+ 'sol_base3': (253, 246, 227), # lightest
45
+ 'sol_red': (220, 50, 47),
46
+ 'sol_green': (133, 153, 0),
47
+ 'sol_yellow': (181, 137, 0),
48
+ 'sol_blue': (38, 139, 210),
49
+ 'sol_magenta': (211, 54, 130),
50
+ 'sol_cyan': (42, 161, 152),
51
+
52
+ # Terminal colors
53
+ 'term_black': (0, 0, 0),
54
+ 'term_white': (255, 255, 255),
55
+ 'term_gray': (128, 128, 128),
56
+ }
57
+
58
+ def create_chuk_term_themes():
59
+ """
60
+ Create a theme dictionary compatible with chuk-term themes.
61
+ Each theme follows plotext format: [canvas_color, axes_color, ticks_color, ticks_style, color_sequence]
62
+ """
63
+ themes = {}
64
+
65
+ # === DEFAULT THEME ===
66
+ # Matches chuk-term default theme (cyan primary, blue secondary)
67
+ sequence = [rgb_colors['bright_cyan'], rgb_colors['bright_blue'], rgb_colors['bright_magenta'],
68
+ rgb_colors['bright_green'], rgb_colors['bright_yellow'], rgb_colors['bright_red']]
69
+ sequence += [el for el in color_sequence if el not in sequence]
70
+ themes['chuk_default'] = ['white', rgb_colors['bright_cyan'], rgb_colors['dark_cyan'], 'bold', sequence]
71
+
72
+ # === DARK THEME ===
73
+ # Matches chuk-term dark theme (bright colors on dark background)
74
+ sequence = [rgb_colors['bright_cyan'], rgb_colors['bright_green'], rgb_colors['bright_yellow'],
75
+ rgb_colors['bright_magenta'], rgb_colors['bright_blue'], rgb_colors['bright_red']]
76
+ sequence += [el for el in color_sequence if el not in sequence]
77
+ themes['chuk_dark'] = ['black', rgb_colors['bright_cyan'], rgb_colors['bright_white'], 'bold', sequence]
78
+
79
+ # === LIGHT THEME ===
80
+ # Matches chuk-term light theme (dark colors on light background)
81
+ sequence = [rgb_colors['dark_cyan'], rgb_colors['dark_green'], rgb_colors['dark_goldenrod'],
82
+ rgb_colors['dark_magenta'], rgb_colors['dark_blue'], rgb_colors['dark_red']]
83
+ sequence += [el for el in color_sequence if el not in sequence]
84
+ themes['chuk_light'] = ['white', rgb_colors['dark_cyan'], 'black', no_color, sequence]
85
+
86
+ # === MINIMAL THEME ===
87
+ # Matches chuk-term minimal theme (no colors, just structure)
88
+ sequence = ['white', 'white', 'white', 'white', 'white']
89
+ sequence += [el for el in color_sequence if el not in sequence]
90
+ themes['chuk_minimal'] = [no_color, 'white', 'white', no_color, sequence]
91
+
92
+ # === TERMINAL THEME ===
93
+ # Matches chuk-term terminal theme (basic ANSI colors)
94
+ sequence = ['cyan', 'blue', 'magenta', 'green', 'yellow', 'red']
95
+ sequence += [el for el in color_sequence if el not in sequence]
96
+ themes['chuk_terminal'] = ['black', 'white', 'white', 'bold', sequence]
97
+
98
+ # === ENHANCED THEMES ===
99
+
100
+ # Professional/Corporate theme
101
+ sequence = [rgb_colors['dark_blue'], rgb_colors['dark_cyan'], rgb_colors['dark_green'],
102
+ (100, 100, 100), (150, 150, 150), (200, 100, 50)]
103
+ sequence += [el for el in color_sequence if el not in sequence]
104
+ themes['professional'] = ['white', rgb_colors['dark_blue'], 'black', no_color, sequence]
105
+
106
+ # Scientific theme (inspired by matplotlib defaults)
107
+ sequence = [(31, 119, 180), (255, 127, 14), (44, 160, 44), (214, 39, 40),
108
+ (148, 103, 189), (140, 86, 75), (227, 119, 194), (127, 127, 127)]
109
+ sequence += [el for el in color_sequence if el not in sequence]
110
+ themes['scientific'] = ['white', (70, 70, 70), (50, 50, 50), no_color, sequence]
111
+
112
+ # Gaming/Neon theme
113
+ sequence = [(0, 255, 255), (255, 0, 255), (0, 255, 0), (255, 255, 0),
114
+ (255, 0, 0), (0, 100, 255), (255, 100, 0)]
115
+ sequence += [el for el in color_sequence if el not in sequence]
116
+ themes['neon'] = ['black', (0, 255, 255), (255, 255, 255), 'bold', sequence]
117
+
118
+ # Pastel theme (soft, muted colors)
119
+ sequence = [(173, 216, 230), (255, 182, 193), (221, 160, 221), (144, 238, 144),
120
+ (255, 218, 185), (230, 230, 250), (255, 240, 245)]
121
+ sequence += [el for el in color_sequence if el not in sequence]
122
+ themes['pastel'] = ['white', (150, 150, 200), (100, 100, 100), no_color, sequence]
123
+
124
+ # High contrast theme (for accessibility)
125
+ sequence = ['black', 'white', rgb_colors['bright_yellow'], rgb_colors['bright_cyan'],
126
+ rgb_colors['bright_magenta'], rgb_colors['bright_green']]
127
+ sequence += [el for el in color_sequence if el not in sequence]
128
+ themes['high_contrast'] = ['white', 'black', 'black', 'bold', sequence]
129
+
130
+ # === POPULAR THEMES ===
131
+
132
+ # Dracula theme - popular dark theme with purples and pinks
133
+ sequence = [rgb_colors['dracula_cyan'], rgb_colors['dracula_green'], rgb_colors['dracula_orange'],
134
+ rgb_colors['dracula_pink'], rgb_colors['dracula_purple']]
135
+ sequence += [el for el in color_sequence if el not in sequence]
136
+ themes['dracula'] = [rgb_colors['dracula_background'], rgb_colors['dracula_foreground'],
137
+ rgb_colors['dracula_cyan'], 'bold', sequence]
138
+
139
+ # Solarized Dark
140
+ sequence = [rgb_colors['sol_cyan'], rgb_colors['sol_green'], rgb_colors['sol_yellow'],
141
+ rgb_colors['sol_blue'], rgb_colors['sol_magenta'], rgb_colors['sol_red']]
142
+ sequence += [el for el in color_sequence if el not in sequence]
143
+ themes['solarized_dark'] = [rgb_colors['sol_base03'], rgb_colors['sol_base0'],
144
+ rgb_colors['sol_base1'], no_color, sequence]
145
+
146
+ # Solarized Light
147
+ sequence = [rgb_colors['sol_cyan'], rgb_colors['sol_green'], rgb_colors['sol_yellow'],
148
+ rgb_colors['sol_blue'], rgb_colors['sol_magenta'], rgb_colors['sol_red']]
149
+ sequence += [el for el in color_sequence if el not in sequence]
150
+ themes['solarized_light'] = [rgb_colors['sol_base3'], rgb_colors['sol_base01'],
151
+ rgb_colors['sol_base00'], no_color, sequence]
152
+
153
+ # Matrix theme (enhanced version)
154
+ sequence = [(0, 255, 65), (0, 200, 50), (0, 150, 35), (0, 100, 20)]
155
+ sequence += [el for el in color_sequence if el not in sequence]
156
+ themes['matrix_enhanced'] = ['black', (0, 255, 65), (0, 255, 65), 'bold', sequence]
157
+
158
+ # Cyberpunk theme
159
+ sequence = [(255, 20, 147), (0, 255, 255), (255, 215, 0), (124, 252, 0),
160
+ (255, 69, 0), (138, 43, 226)]
161
+ sequence += [el for el in color_sequence if el not in sequence]
162
+ themes['cyberpunk'] = ['black', (255, 20, 147), (0, 255, 255), 'bold', sequence]
163
+
164
+ return themes
165
+
166
+ def get_theme_info():
167
+ """
168
+ Get information about all available themes.
169
+
170
+ Returns:
171
+ dict: Theme information with descriptions and color palettes
172
+ """
173
+ return {
174
+ # Chuk-term compatible themes
175
+ 'chuk_default': {
176
+ 'name': 'Chuk Default',
177
+ 'description': 'Default chuk-term theme with cyan and blue accents',
178
+ 'primary_colors': ['cyan', 'blue', 'magenta'],
179
+ 'background': 'white',
180
+ 'style': 'modern'
181
+ },
182
+ 'chuk_dark': {
183
+ 'name': 'Chuk Dark',
184
+ 'description': 'Dark theme with bright accent colors',
185
+ 'primary_colors': ['bright_cyan', 'bright_green', 'bright_yellow'],
186
+ 'background': 'black',
187
+ 'style': 'modern'
188
+ },
189
+ 'chuk_light': {
190
+ 'name': 'Chuk Light',
191
+ 'description': 'Light theme with muted colors for light terminals',
192
+ 'primary_colors': ['dark_cyan', 'dark_green', 'dark_blue'],
193
+ 'background': 'white',
194
+ 'style': 'modern'
195
+ },
196
+ 'chuk_minimal': {
197
+ 'name': 'Chuk Minimal',
198
+ 'description': 'Minimal theme with no colors, focus on structure',
199
+ 'primary_colors': ['white'],
200
+ 'background': 'none',
201
+ 'style': 'minimal'
202
+ },
203
+ 'chuk_terminal': {
204
+ 'name': 'Chuk Terminal',
205
+ 'description': 'Basic terminal theme using ANSI colors',
206
+ 'primary_colors': ['cyan', 'blue', 'magenta'],
207
+ 'background': 'black',
208
+ 'style': 'terminal'
209
+ },
210
+
211
+ # Enhanced themes
212
+ 'professional': {
213
+ 'name': 'Professional',
214
+ 'description': 'Corporate-friendly theme with muted blues',
215
+ 'primary_colors': ['dark_blue', 'dark_cyan', 'gray'],
216
+ 'background': 'white',
217
+ 'style': 'corporate'
218
+ },
219
+ 'scientific': {
220
+ 'name': 'Scientific',
221
+ 'description': 'Scientific theme inspired by matplotlib',
222
+ 'primary_colors': ['blue', 'orange', 'green'],
223
+ 'background': 'white',
224
+ 'style': 'academic'
225
+ },
226
+ 'neon': {
227
+ 'name': 'Neon',
228
+ 'description': 'Gaming-inspired theme with bright neon colors',
229
+ 'primary_colors': ['neon_cyan', 'neon_magenta', 'neon_green'],
230
+ 'background': 'black',
231
+ 'style': 'gaming'
232
+ },
233
+ 'pastel': {
234
+ 'name': 'Pastel',
235
+ 'description': 'Soft, muted colors for gentle visualization',
236
+ 'primary_colors': ['light_blue', 'light_pink', 'light_green'],
237
+ 'background': 'white',
238
+ 'style': 'soft'
239
+ },
240
+ 'high_contrast': {
241
+ 'name': 'High Contrast',
242
+ 'description': 'High contrast theme for accessibility',
243
+ 'primary_colors': ['black', 'white', 'yellow'],
244
+ 'background': 'white',
245
+ 'style': 'accessible'
246
+ },
247
+
248
+ # Popular themes
249
+ 'dracula': {
250
+ 'name': 'Dracula',
251
+ 'description': 'Popular dark theme with purple and pink accents',
252
+ 'primary_colors': ['dracula_cyan', 'dracula_pink', 'dracula_purple'],
253
+ 'background': 'dracula_dark',
254
+ 'style': 'popular'
255
+ },
256
+ 'solarized_dark': {
257
+ 'name': 'Solarized Dark',
258
+ 'description': 'Popular dark theme with carefully chosen colors',
259
+ 'primary_colors': ['sol_cyan', 'sol_green', 'sol_blue'],
260
+ 'background': 'solarized_dark',
261
+ 'style': 'popular'
262
+ },
263
+ 'solarized_light': {
264
+ 'name': 'Solarized Light',
265
+ 'description': 'Light version of the popular Solarized theme',
266
+ 'primary_colors': ['sol_cyan', 'sol_green', 'sol_blue'],
267
+ 'background': 'solarized_light',
268
+ 'style': 'popular'
269
+ },
270
+ 'matrix_enhanced': {
271
+ 'name': 'Matrix Enhanced',
272
+ 'description': 'Enhanced matrix theme with green on black',
273
+ 'primary_colors': ['matrix_green'],
274
+ 'background': 'black',
275
+ 'style': 'classic'
276
+ },
277
+ 'cyberpunk': {
278
+ 'name': 'Cyberpunk',
279
+ 'description': 'Futuristic theme with pink and cyan',
280
+ 'primary_colors': ['hot_pink', 'cyan', 'gold'],
281
+ 'background': 'black',
282
+ 'style': 'futuristic'
283
+ }
284
+ }
285
+
286
+ def apply_chuk_theme_to_chart(chart, theme_name='chuk_default'):
287
+ """
288
+ Apply a chuk-term compatible theme to a plotext chart.
289
+
290
+ Args:
291
+ chart: Plotext chart instance
292
+ theme_name (str): Name of theme to apply
293
+
294
+ Returns:
295
+ chart: Chart with theme applied
296
+ """
297
+ themes = create_chuk_term_themes()
298
+
299
+ if theme_name not in themes:
300
+ theme_name = 'chuk_default'
301
+
302
+ # Apply theme using plotext's theme system
303
+ chart.theme(theme_name)
304
+ return chart
305
+
306
+ def get_chuk_theme_for_banner_mode(theme_name='chuk_default'):
307
+ """
308
+ Get appropriate banner styling based on theme.
309
+
310
+ Args:
311
+ theme_name (str): Theme name
312
+
313
+ Returns:
314
+ dict: Banner styling configuration
315
+ """
316
+ theme_info = get_theme_info()
317
+ info = theme_info.get(theme_name, theme_info['chuk_default'])
318
+
319
+ # Map theme styles to banner configurations
320
+ style_mappings = {
321
+ 'modern': {'style': 'rounded', 'padding': (0, 1)},
322
+ 'minimal': {'style': 'none', 'padding': (0, 0)},
323
+ 'terminal': {'style': 'ascii', 'padding': (0, 1)},
324
+ 'corporate': {'style': 'heavy', 'padding': (0, 2)},
325
+ 'academic': {'style': 'double', 'padding': (0, 1)},
326
+ 'gaming': {'style': 'rounded', 'padding': (0, 2)},
327
+ 'soft': {'style': 'rounded', 'padding': (0, 2)},
328
+ 'accessible': {'style': 'heavy', 'padding': (0, 1)},
329
+ 'popular': {'style': 'rounded', 'padding': (0, 1)},
330
+ 'classic': {'style': 'ascii', 'padding': (0, 1)},
331
+ 'futuristic': {'style': 'rounded', 'padding': (0, 2)}
332
+ }
333
+
334
+ return style_mappings.get(info['style'], style_mappings['modern'])
335
+
336
+ # Export the theme functions for easy access
337
+ __all__ = [
338
+ 'create_chuk_term_themes',
339
+ 'get_theme_info',
340
+ 'apply_chuk_theme_to_chart',
341
+ 'get_chuk_theme_for_banner_mode',
342
+ 'rgb_colors'
343
+ ]