webscout 6.3__py3-none-any.whl → 6.4__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 webscout might be problematic. Click here for more details.
- webscout/AIauto.py +191 -176
- webscout/AIbase.py +0 -197
- webscout/AIutel.py +488 -1130
- webscout/Bing_search.py +250 -153
- webscout/DWEBS.py +151 -19
- webscout/Extra/__init__.py +2 -1
- webscout/Extra/autocoder/__init__.py +9 -0
- webscout/Extra/autocoder/autocoder_utiles.py +121 -0
- webscout/Extra/autocoder/rawdog.py +681 -0
- webscout/Extra/autollama.py +246 -195
- webscout/Extra/gguf.py +441 -416
- webscout/LLM.py +206 -43
- webscout/Litlogger/__init__.py +681 -0
- webscout/Provider/DARKAI.py +1 -1
- webscout/Provider/EDITEE.py +1 -1
- webscout/Provider/NinjaChat.py +1 -1
- webscout/Provider/PI.py +221 -207
- webscout/Provider/Perplexity.py +598 -598
- webscout/Provider/RoboCoders.py +206 -0
- webscout/Provider/TTI/AiForce/__init__.py +22 -0
- webscout/Provider/TTI/AiForce/async_aiforce.py +257 -0
- webscout/Provider/TTI/AiForce/sync_aiforce.py +242 -0
- webscout/Provider/TTI/Nexra/__init__.py +22 -0
- webscout/Provider/TTI/Nexra/async_nexra.py +286 -0
- webscout/Provider/TTI/Nexra/sync_nexra.py +258 -0
- webscout/Provider/TTI/PollinationsAI/__init__.py +23 -0
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +330 -0
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +285 -0
- webscout/Provider/TTI/__init__.py +2 -4
- webscout/Provider/TTI/artbit/__init__.py +22 -0
- webscout/Provider/TTI/artbit/async_artbit.py +184 -0
- webscout/Provider/TTI/artbit/sync_artbit.py +176 -0
- webscout/Provider/TTI/blackbox/__init__.py +4 -0
- webscout/Provider/TTI/blackbox/async_blackbox.py +212 -0
- webscout/Provider/TTI/{blackboximage.py → blackbox/sync_blackbox.py} +199 -153
- webscout/Provider/TTI/deepinfra/__init__.py +4 -0
- webscout/Provider/TTI/deepinfra/async_deepinfra.py +227 -0
- webscout/Provider/TTI/deepinfra/sync_deepinfra.py +199 -0
- webscout/Provider/TTI/huggingface/__init__.py +22 -0
- webscout/Provider/TTI/huggingface/async_huggingface.py +199 -0
- webscout/Provider/TTI/huggingface/sync_huggingface.py +195 -0
- webscout/Provider/TTI/imgninza/__init__.py +4 -0
- webscout/Provider/TTI/imgninza/async_ninza.py +214 -0
- webscout/Provider/TTI/{imgninza.py → imgninza/sync_ninza.py} +209 -136
- webscout/Provider/TTI/talkai/__init__.py +4 -0
- webscout/Provider/TTI/talkai/async_talkai.py +229 -0
- webscout/Provider/TTI/talkai/sync_talkai.py +207 -0
- webscout/Provider/__init__.py +146 -139
- webscout/Provider/askmyai.py +2 -2
- webscout/Provider/cerebras.py +227 -219
- webscout/Provider/llama3mitril.py +0 -1
- webscout/Provider/mhystical.py +176 -0
- webscout/Provider/perplexitylabs.py +265 -0
- webscout/Provider/twitterclone.py +251 -245
- webscout/Provider/typegpt.py +359 -0
- webscout/__init__.py +28 -23
- webscout/__main__.py +5 -5
- webscout/cli.py +252 -280
- webscout/conversation.py +227 -0
- webscout/exceptions.py +161 -29
- webscout/litagent/__init__.py +172 -0
- webscout/litprinter/__init__.py +831 -0
- webscout/optimizers.py +270 -0
- webscout/prompt_manager.py +279 -0
- webscout/swiftcli/__init__.py +810 -0
- webscout/transcriber.py +479 -551
- webscout/update_checker.py +125 -0
- webscout/version.py +1 -1
- {webscout-6.3.dist-info → webscout-6.4.dist-info}/METADATA +26 -45
- {webscout-6.3.dist-info → webscout-6.4.dist-info}/RECORD +75 -45
- webscout/Provider/TTI/AIuncensoredimage.py +0 -103
- webscout/Provider/TTI/Nexra.py +0 -120
- webscout/Provider/TTI/PollinationsAI.py +0 -138
- webscout/Provider/TTI/WebSimAI.py +0 -142
- webscout/Provider/TTI/aiforce.py +0 -160
- webscout/Provider/TTI/artbit.py +0 -141
- webscout/Provider/TTI/deepinfra.py +0 -148
- webscout/Provider/TTI/huggingface.py +0 -155
- webscout/Provider/TTI/talkai.py +0 -116
- webscout/models.py +0 -23
- /webscout/{g4f.py → gpt4free.py} +0 -0
- {webscout-6.3.dist-info → webscout-6.4.dist-info}/LICENSE.md +0 -0
- {webscout-6.3.dist-info → webscout-6.4.dist-info}/WHEEL +0 -0
- {webscout-6.3.dist-info → webscout-6.4.dist-info}/entry_points.txt +0 -0
- {webscout-6.3.dist-info → webscout-6.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,831 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Welcome to WebScout's Advanced Console Printer!
|
|
3
|
+
|
|
4
|
+
About This Printer:
|
|
5
|
+
- A powerful, feature-rich console output manager
|
|
6
|
+
- Created by Abhay Koul as part of the WebScout project
|
|
7
|
+
- Designed for beautiful, informative, and interactive terminal output
|
|
8
|
+
|
|
9
|
+
Core Features:
|
|
10
|
+
>>> printer.success("Operation completed successfully! ")
|
|
11
|
+
>>> printer.warning("Important notice! ")
|
|
12
|
+
>>> printer.info("Here's something interesting ")
|
|
13
|
+
>>> printer.error("Houston, we have a problem! ")
|
|
14
|
+
|
|
15
|
+
Special Features:
|
|
16
|
+
- Rich ANSI color support
|
|
17
|
+
- Data visualization tools
|
|
18
|
+
- Progress bars and spinners
|
|
19
|
+
- Code syntax highlighting
|
|
20
|
+
- Markdown rendering
|
|
21
|
+
- JSON pretty printing
|
|
22
|
+
|
|
23
|
+
For the best experience, use a terminal that supports UTF-8 and ANSI colors.
|
|
24
|
+
|
|
25
|
+
>>> # Basic Printing with Style
|
|
26
|
+
>>> printer.print("Hello World!", color="blue", bold=True)
|
|
27
|
+
>>> printer.print("Important Notice", bg_color="yellow", italic=True)
|
|
28
|
+
|
|
29
|
+
>>> # Layout and Formatting
|
|
30
|
+
>>> printer.print("Centered Text", center=True, width=50)
|
|
31
|
+
>>> printer.print("Indented Text", indent=4, prefix="→ ")
|
|
32
|
+
|
|
33
|
+
>>> # Borders and Decorations
|
|
34
|
+
>>> printer.print("Special Message", border=True, rounded_corners=True)
|
|
35
|
+
>>> printer.print("Alert", border=True, border_color="red", double_border=True)
|
|
36
|
+
|
|
37
|
+
>>> # Animations
|
|
38
|
+
>>> printer.print("Loading...", animate=True, animation_type="typing")
|
|
39
|
+
>>> printer.print("Processing", animate=True, animation_speed=0.1)
|
|
40
|
+
|
|
41
|
+
>>> # Data Visualization
|
|
42
|
+
>>> data = {"status": "active", "users": 100}
|
|
43
|
+
>>> printer.print(data, as_json=True) # Pretty JSON
|
|
44
|
+
>>> printer.print(data, as_tree=True) # Tree View
|
|
45
|
+
|
|
46
|
+
>>> # Code Highlighting
|
|
47
|
+
>>> code = '''def greet(): print("Hello!")'''
|
|
48
|
+
>>> printer.print(code, as_code=True, language="python")
|
|
49
|
+
|
|
50
|
+
>>> # Tables
|
|
51
|
+
>>> headers = ["Name", "Status"]
|
|
52
|
+
>>> rows = [["Server", "Online"]]
|
|
53
|
+
>>> printer.print([headers, rows], as_table=True)
|
|
54
|
+
|
|
55
|
+
>>> # Markdown Support
|
|
56
|
+
>>> printer.print("# Title\n- List item", markdown=True)
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
import sys
|
|
60
|
+
import os
|
|
61
|
+
import json
|
|
62
|
+
import time
|
|
63
|
+
import threading
|
|
64
|
+
import re
|
|
65
|
+
from typing import Any, Optional, TextIO, Union, Sequence, Dict, List
|
|
66
|
+
from datetime import datetime
|
|
67
|
+
import textwrap
|
|
68
|
+
from collections import defaultdict
|
|
69
|
+
import shutil
|
|
70
|
+
import inspect
|
|
71
|
+
try:
|
|
72
|
+
from pygments import highlight
|
|
73
|
+
from pygments.lexers import get_lexer_by_name
|
|
74
|
+
from pygments.formatters import Terminal256Formatter
|
|
75
|
+
PYGMENTS_AVAILABLE = True
|
|
76
|
+
except ImportError:
|
|
77
|
+
PYGMENTS_AVAILABLE = False
|
|
78
|
+
|
|
79
|
+
# Enable UTF-8 output on Windows
|
|
80
|
+
if sys.platform == 'win32':
|
|
81
|
+
import ctypes
|
|
82
|
+
kernel32 = ctypes.windll.kernel32
|
|
83
|
+
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
|
|
84
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
85
|
+
|
|
86
|
+
# Enable ANSI escape sequences for Windows
|
|
87
|
+
if os.name == 'nt':
|
|
88
|
+
import ctypes
|
|
89
|
+
kernel32 = ctypes.windll.kernel32
|
|
90
|
+
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
|
|
91
|
+
|
|
92
|
+
# ANSI Color Codes
|
|
93
|
+
class Colors:
|
|
94
|
+
"""ANSI color codes for terminal output."""
|
|
95
|
+
# Base colors
|
|
96
|
+
BLACK = '\033[30m'
|
|
97
|
+
RED = '\033[31m'
|
|
98
|
+
GREEN = '\033[32m'
|
|
99
|
+
YELLOW = '\033[33m'
|
|
100
|
+
BLUE = '\033[34m'
|
|
101
|
+
MAGENTA = '\033[35m'
|
|
102
|
+
CYAN = '\033[36m'
|
|
103
|
+
WHITE = '\033[37m'
|
|
104
|
+
GRAY = '\033[90m'
|
|
105
|
+
|
|
106
|
+
# Bright colors
|
|
107
|
+
BRIGHT_BLACK = '\033[90m'
|
|
108
|
+
BRIGHT_RED = '\033[91m'
|
|
109
|
+
BRIGHT_GREEN = '\033[92m'
|
|
110
|
+
BRIGHT_YELLOW = '\033[93m'
|
|
111
|
+
BRIGHT_BLUE = '\033[94m'
|
|
112
|
+
BRIGHT_MAGENTA = '\033[95m'
|
|
113
|
+
BRIGHT_CYAN = '\033[96m'
|
|
114
|
+
BRIGHT_WHITE = '\033[97m'
|
|
115
|
+
|
|
116
|
+
# Background colors
|
|
117
|
+
BG_BLACK = '\033[40m'
|
|
118
|
+
BG_RED = '\033[41m'
|
|
119
|
+
BG_GREEN = '\033[42m'
|
|
120
|
+
BG_YELLOW = '\033[43m'
|
|
121
|
+
BG_BLUE = '\033[44m'
|
|
122
|
+
BG_MAGENTA = '\033[45m'
|
|
123
|
+
BG_CYAN = '\033[46m'
|
|
124
|
+
BG_WHITE = '\033[47m'
|
|
125
|
+
|
|
126
|
+
# Styles
|
|
127
|
+
BOLD = '\033[1m'
|
|
128
|
+
DIM = '\033[2m'
|
|
129
|
+
ITALIC = '\033[3m'
|
|
130
|
+
UNDERLINE = '\033[4m'
|
|
131
|
+
BLINK = '\033[5m'
|
|
132
|
+
REVERSE = '\033[7m'
|
|
133
|
+
STRIKE = '\033[9m'
|
|
134
|
+
HIDDEN = '\033[8m'
|
|
135
|
+
|
|
136
|
+
# Special
|
|
137
|
+
RESET = '\033[0m'
|
|
138
|
+
CLEAR_SCREEN = '\033[2J'
|
|
139
|
+
CLEAR_LINE = '\033[2K'
|
|
140
|
+
|
|
141
|
+
# Cursor movement
|
|
142
|
+
UP = '\033[1A'
|
|
143
|
+
DOWN = '\033[1B'
|
|
144
|
+
RIGHT = '\033[1C'
|
|
145
|
+
LEFT = '\033[1D'
|
|
146
|
+
|
|
147
|
+
class SyntaxTheme:
|
|
148
|
+
"""Syntax highlighting theme."""
|
|
149
|
+
KEYWORD = Colors.MAGENTA + Colors.BOLD
|
|
150
|
+
STRING = Colors.GREEN
|
|
151
|
+
NUMBER = Colors.CYAN
|
|
152
|
+
COMMENT = Colors.BRIGHT_BLACK + Colors.ITALIC
|
|
153
|
+
FUNCTION = Colors.BRIGHT_BLUE
|
|
154
|
+
CLASS = Colors.BRIGHT_YELLOW + Colors.BOLD
|
|
155
|
+
OPERATOR = Colors.WHITE
|
|
156
|
+
BRACKET = Colors.WHITE
|
|
157
|
+
VARIABLE = Colors.BRIGHT_WHITE
|
|
158
|
+
|
|
159
|
+
class MarkdownTheme:
|
|
160
|
+
"""Theme for markdown elements."""
|
|
161
|
+
H1 = Colors.BOLD + Colors.BLUE
|
|
162
|
+
H2 = Colors.BOLD + Colors.CYAN
|
|
163
|
+
H3 = Colors.BOLD + Colors.GREEN
|
|
164
|
+
BOLD = Colors.BOLD
|
|
165
|
+
ITALIC = Colors.ITALIC
|
|
166
|
+
CODE = Colors.YELLOW
|
|
167
|
+
LINK = Colors.BLUE + Colors.UNDERLINE
|
|
168
|
+
LIST_BULLET = Colors.CYAN + "•" + Colors.RESET
|
|
169
|
+
QUOTE = Colors.GRAY
|
|
170
|
+
STRIKE = Colors.STRIKE
|
|
171
|
+
TABLE = Colors.GREEN
|
|
172
|
+
TASK = Colors.YELLOW
|
|
173
|
+
DETAILS = Colors.MAGENTA
|
|
174
|
+
|
|
175
|
+
class ThemeStyles:
|
|
176
|
+
SUCCESS = f"{Colors.GREEN}{Colors.BOLD}"
|
|
177
|
+
ERROR = f"{Colors.RED}{Colors.BOLD}"
|
|
178
|
+
WARNING = f"{Colors.YELLOW}{Colors.BOLD}"
|
|
179
|
+
INFO = f"{Colors.BLUE}{Colors.BOLD}"
|
|
180
|
+
DEBUG = f"{Colors.MAGENTA}"
|
|
181
|
+
CODE = f"{Colors.CYAN}"
|
|
182
|
+
|
|
183
|
+
class HoverInfo:
|
|
184
|
+
"""Hover information for different elements."""
|
|
185
|
+
BANNER = "A fancy banner to make your output pop!"
|
|
186
|
+
SUCCESS = "Something went right! "
|
|
187
|
+
ERROR = "Oops! Something went wrong "
|
|
188
|
+
WARNING = "Heads up! Something needs attention "
|
|
189
|
+
INFO = "Just some helpful info "
|
|
190
|
+
TABLE = "Data organized in rows and columns "
|
|
191
|
+
TREE = "Hierarchical data visualization "
|
|
192
|
+
JSON = "Pretty-printed JSON data "
|
|
193
|
+
CODE = "Syntax-highlighted code block "
|
|
194
|
+
|
|
195
|
+
class ProgressBar:
|
|
196
|
+
def __init__(self, total: int, width: int = 40, prefix: str = '', suffix: str = ''):
|
|
197
|
+
self.total = total
|
|
198
|
+
self.width = width
|
|
199
|
+
self.prefix = prefix
|
|
200
|
+
self.suffix = suffix
|
|
201
|
+
self.current = 0
|
|
202
|
+
|
|
203
|
+
def update(self, current: int):
|
|
204
|
+
self.current = current
|
|
205
|
+
filled = int(self.width * current / self.total)
|
|
206
|
+
bar = f"{Colors.GREEN}{'█' * filled}{Colors.RESET}{'░' * (self.width - filled)}"
|
|
207
|
+
percent = f"{Colors.CYAN}{int(100 * current / self.total)}%{Colors.RESET}"
|
|
208
|
+
print(f'\r{self.prefix} |{bar}| {percent} {self.suffix}', end='', flush=True)
|
|
209
|
+
if current >= self.total:
|
|
210
|
+
print()
|
|
211
|
+
|
|
212
|
+
class Spinner:
|
|
213
|
+
def __init__(self, message: str = ''):
|
|
214
|
+
self.message = message
|
|
215
|
+
self.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
216
|
+
self.running = False
|
|
217
|
+
self.thread = None
|
|
218
|
+
|
|
219
|
+
def spin(self):
|
|
220
|
+
while self.running:
|
|
221
|
+
for frame in self.frames:
|
|
222
|
+
if not self.running:
|
|
223
|
+
break
|
|
224
|
+
print(f'\r{Colors.CYAN}{frame}{Colors.RESET} {self.message}', end='', flush=True)
|
|
225
|
+
time.sleep(0.1)
|
|
226
|
+
|
|
227
|
+
def __enter__(self):
|
|
228
|
+
self.start()
|
|
229
|
+
return self
|
|
230
|
+
|
|
231
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
232
|
+
self.stop()
|
|
233
|
+
|
|
234
|
+
def start(self):
|
|
235
|
+
self.running = True
|
|
236
|
+
self.thread = threading.Thread(target=self.spin)
|
|
237
|
+
self.thread.start()
|
|
238
|
+
|
|
239
|
+
def stop(self):
|
|
240
|
+
self.running = False
|
|
241
|
+
if self.thread:
|
|
242
|
+
self.thread.join()
|
|
243
|
+
print('\r' + ' ' * (len(self.message) + 2), end='', flush=True)
|
|
244
|
+
print('\r', end='')
|
|
245
|
+
|
|
246
|
+
class LitPrinter:
|
|
247
|
+
def __init__(self,
|
|
248
|
+
file: TextIO = sys.stdout,
|
|
249
|
+
theme: Optional[dict] = None,
|
|
250
|
+
indent_size: int = 4,
|
|
251
|
+
buffer_size: int = 1024,
|
|
252
|
+
syntax_theme: Optional[Dict[str, str]] = None,
|
|
253
|
+
markdown_theme: Optional[Dict[str, str]] = None):
|
|
254
|
+
self.file = file
|
|
255
|
+
self.indent_size = indent_size
|
|
256
|
+
self.buffer_size = buffer_size
|
|
257
|
+
self._terminal_width = shutil.get_terminal_size().columns
|
|
258
|
+
self._last_line = ""
|
|
259
|
+
self._spinner_active = False
|
|
260
|
+
self._progress_active = False
|
|
261
|
+
|
|
262
|
+
# Default theme
|
|
263
|
+
self.theme = theme or {
|
|
264
|
+
"str": Colors.WHITE,
|
|
265
|
+
"int": Colors.CYAN,
|
|
266
|
+
"float": Colors.CYAN,
|
|
267
|
+
"bool": Colors.YELLOW,
|
|
268
|
+
"list": Colors.MAGENTA,
|
|
269
|
+
"dict": Colors.BLUE,
|
|
270
|
+
"none": Colors.RED,
|
|
271
|
+
"timestamp": Colors.GREEN,
|
|
272
|
+
"key": Colors.YELLOW,
|
|
273
|
+
"bracket": Colors.BLUE,
|
|
274
|
+
"comma": Colors.WHITE,
|
|
275
|
+
"colon": Colors.WHITE,
|
|
276
|
+
"url": f"{Colors.BLUE}{Colors.UNDERLINE}",
|
|
277
|
+
"number": Colors.CYAN,
|
|
278
|
+
"special": Colors.MAGENTA + Colors.BOLD,
|
|
279
|
+
"error": Colors.RED + Colors.BOLD,
|
|
280
|
+
"warning": Colors.YELLOW + Colors.BOLD,
|
|
281
|
+
"success": Colors.GREEN + Colors.BOLD,
|
|
282
|
+
"info": Colors.BLUE + Colors.BOLD,
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
self.syntax_theme = syntax_theme or vars(SyntaxTheme)
|
|
286
|
+
self.markdown_theme = markdown_theme or vars(MarkdownTheme)
|
|
287
|
+
|
|
288
|
+
def _get_terminal_width(self) -> int:
|
|
289
|
+
"""Get the terminal width or default to 80."""
|
|
290
|
+
try:
|
|
291
|
+
width = shutil.get_terminal_size().columns
|
|
292
|
+
return width if width > 0 else 80
|
|
293
|
+
except:
|
|
294
|
+
return 80
|
|
295
|
+
|
|
296
|
+
def _format_dict(self, d: dict, indent_level: int = 0) -> str:
|
|
297
|
+
"""Format dictionary with proper indentation and colors."""
|
|
298
|
+
if not d:
|
|
299
|
+
return f"{self.theme['bracket']}{{}}{Colors.RESET}"
|
|
300
|
+
|
|
301
|
+
indent = " " * (self.indent_size * indent_level)
|
|
302
|
+
next_indent = " " * (self.indent_size * (indent_level + 1))
|
|
303
|
+
|
|
304
|
+
lines = [f"{self.theme['bracket']}{{{Colors.RESET}"]
|
|
305
|
+
|
|
306
|
+
for i, (key, value) in enumerate(d.items()):
|
|
307
|
+
# Format key with quotes if it's a string
|
|
308
|
+
if isinstance(key, str):
|
|
309
|
+
formatted_key = f"{self.theme['key']}'{key}'{Colors.RESET}"
|
|
310
|
+
else:
|
|
311
|
+
formatted_key = f"{self.theme['key']}{key}{Colors.RESET}"
|
|
312
|
+
|
|
313
|
+
# Format value based on type
|
|
314
|
+
if isinstance(value, dict):
|
|
315
|
+
formatted_value = self._format_dict(value, indent_level + 1)
|
|
316
|
+
elif isinstance(value, str):
|
|
317
|
+
# Special handling for URLs
|
|
318
|
+
if any(url_prefix in value.lower() for url_prefix in ['http://', 'https://', 'www.']):
|
|
319
|
+
formatted_value = f"{self.theme['url']}{value}{Colors.RESET}"
|
|
320
|
+
else:
|
|
321
|
+
# Word wrap long strings
|
|
322
|
+
if len(value) > 80:
|
|
323
|
+
wrapped = textwrap.fill(value, width=80, subsequent_indent=next_indent + " ")
|
|
324
|
+
formatted_value = f"{self.theme['str']}'{wrapped}'{Colors.RESET}"
|
|
325
|
+
else:
|
|
326
|
+
formatted_value = f"{self.theme['str']}'{value}'{Colors.RESET}"
|
|
327
|
+
elif isinstance(value, (int, float)):
|
|
328
|
+
formatted_value = f"{self.theme['number']}{value}{Colors.RESET}"
|
|
329
|
+
elif isinstance(value, bool):
|
|
330
|
+
formatted_value = f"{self.theme['bool']}{value}{Colors.RESET}"
|
|
331
|
+
elif value is None:
|
|
332
|
+
formatted_value = f"{self.theme['none']}None{Colors.RESET}"
|
|
333
|
+
else:
|
|
334
|
+
formatted_value = self._format_value(value)
|
|
335
|
+
|
|
336
|
+
# Add comma if not last item
|
|
337
|
+
comma = f"{self.theme['comma']},{Colors.RESET}" if i < len(d) - 1 else ""
|
|
338
|
+
|
|
339
|
+
lines.append(f"{next_indent}{formatted_key}{self.theme['colon']}: {Colors.RESET}{formatted_value}{comma}")
|
|
340
|
+
|
|
341
|
+
lines.append(f"{indent}{self.theme['bracket']}}}{Colors.RESET}")
|
|
342
|
+
return '\n'.join(lines)
|
|
343
|
+
|
|
344
|
+
def _format_sequence(self, seq: Sequence, indent_level: int = 0) -> str:
|
|
345
|
+
"""Format sequences (lists, tuples, sets) with proper indentation."""
|
|
346
|
+
if not seq:
|
|
347
|
+
return f"{self.theme['bracket']}[]{Colors.RESET}"
|
|
348
|
+
|
|
349
|
+
indent = " " * (self.indent_size * indent_level)
|
|
350
|
+
next_indent = " " * (self.indent_size * (indent_level + 1))
|
|
351
|
+
|
|
352
|
+
lines = [f"{self.theme['bracket']}[{Colors.RESET}"]
|
|
353
|
+
|
|
354
|
+
for i, item in enumerate(seq):
|
|
355
|
+
formatted_item = self._format_value(item, indent_level + 1)
|
|
356
|
+
comma = f"{self.theme['comma']},{Colors.RESET}" if i < len(seq) - 1 else ""
|
|
357
|
+
lines.append(f"{next_indent}{formatted_item}{comma}")
|
|
358
|
+
|
|
359
|
+
lines.append(f"{indent}{self.theme['bracket']}]{Colors.RESET}")
|
|
360
|
+
return '\n'.join(lines)
|
|
361
|
+
|
|
362
|
+
def _format_value(self, value: Any, indent_level: int = 0) -> str:
|
|
363
|
+
"""Enhanced format for any value with proper indentation and styling."""
|
|
364
|
+
if value is None:
|
|
365
|
+
return f"{self.theme['none']}None{Colors.RESET}"
|
|
366
|
+
|
|
367
|
+
if isinstance(value, dict):
|
|
368
|
+
return self._format_dict(value, indent_level)
|
|
369
|
+
|
|
370
|
+
if isinstance(value, (list, tuple, set)):
|
|
371
|
+
return self._format_sequence(value, indent_level)
|
|
372
|
+
|
|
373
|
+
if isinstance(value, str):
|
|
374
|
+
return str(value)
|
|
375
|
+
|
|
376
|
+
if isinstance(value, bool):
|
|
377
|
+
return f"{self.theme['bool']}{str(value)}{Colors.RESET}"
|
|
378
|
+
|
|
379
|
+
if isinstance(value, (int, float)):
|
|
380
|
+
return f"{self.theme['number']}{str(value)}{Colors.RESET}"
|
|
381
|
+
|
|
382
|
+
if hasattr(value, '__dict__'):
|
|
383
|
+
return self._format_dict(value.__dict__, indent_level)
|
|
384
|
+
|
|
385
|
+
return str(value)
|
|
386
|
+
|
|
387
|
+
def _highlight_code(self, code: str, language: str = "python") -> str:
|
|
388
|
+
"""Print code with that extra drip """
|
|
389
|
+
if PYGMENTS_AVAILABLE:
|
|
390
|
+
try:
|
|
391
|
+
lexer = get_lexer_by_name(language)
|
|
392
|
+
formatter = Terminal256Formatter(style='monokai')
|
|
393
|
+
return highlight(code, lexer, formatter)
|
|
394
|
+
except:
|
|
395
|
+
pass
|
|
396
|
+
|
|
397
|
+
if language != 'python':
|
|
398
|
+
return code
|
|
399
|
+
|
|
400
|
+
lines = []
|
|
401
|
+
for line in code.split('\n'):
|
|
402
|
+
if '#' in line:
|
|
403
|
+
code_part, comment_part = line.split('#', 1)
|
|
404
|
+
line = code_part + f"{self.syntax_theme['COMMENT']}#{comment_part}{Colors.RESET}"
|
|
405
|
+
|
|
406
|
+
line = re.sub(r'(".*?"|\'.*?\')',
|
|
407
|
+
f"{self.syntax_theme['STRING']}\\1{Colors.RESET}", line)
|
|
408
|
+
|
|
409
|
+
line = re.sub(r'\b(\d+)\b',
|
|
410
|
+
f"{self.syntax_theme['NUMBER']}\\1{Colors.RESET}", line)
|
|
411
|
+
|
|
412
|
+
keywords = ['def', 'class', 'if', 'else', 'elif', 'for', 'while', 'try',
|
|
413
|
+
'except', 'finally', 'with', 'as', 'import', 'from', 'return']
|
|
414
|
+
|
|
415
|
+
for keyword in keywords:
|
|
416
|
+
line = re.sub(f'\\b{keyword}\\b',
|
|
417
|
+
f"{self.syntax_theme['KEYWORD']}{keyword}{Colors.RESET}", line)
|
|
418
|
+
|
|
419
|
+
lines.append(line)
|
|
420
|
+
|
|
421
|
+
return '\n'.join(lines)
|
|
422
|
+
|
|
423
|
+
def _format_markdown_stream(self, text: str) -> str:
|
|
424
|
+
"""Enhanced markdown formatting for streaming mode."""
|
|
425
|
+
# Headers with emoji flair
|
|
426
|
+
text = re.sub(r'^# (.+)$', f"{self.markdown_theme['H1']}🔥 \\1{Colors.RESET}", text, flags=re.M)
|
|
427
|
+
text = re.sub(r'^## (.+)$', f"{self.markdown_theme['H2']}✨ \\1{Colors.RESET}", text, flags=re.M)
|
|
428
|
+
text = re.sub(r'^### (.+)$', f"{self.markdown_theme['H3']}💫 \\1{Colors.RESET}", text, flags=re.M)
|
|
429
|
+
|
|
430
|
+
# Bold, italic, and combined with multiple styles
|
|
431
|
+
text = re.sub(r'\*\*\*(.+?)\*\*\*', f"{Colors.BOLD}{Colors.ITALIC}\\1{Colors.RESET}", text)
|
|
432
|
+
text = re.sub(r'\*\*(.+?)\*\*', f"{Colors.BOLD}\\1{Colors.RESET}", text)
|
|
433
|
+
text = re.sub(r'\*(.+?)\*', f"{Colors.ITALIC}\\1{Colors.RESET}", text)
|
|
434
|
+
text = re.sub(r'__(.+?)__', f"{Colors.BOLD}\\1{Colors.RESET}", text)
|
|
435
|
+
text = re.sub(r'_(.+?)_', f"{Colors.ITALIC}\\1{Colors.RESET}", text)
|
|
436
|
+
|
|
437
|
+
# Code blocks and inline code
|
|
438
|
+
text = re.sub(r'```(\w+)?\n(.*?)\n```', lambda m: self._highlight_code(m.group(2), m.group(1) or 'text'), text, flags=re.S)
|
|
439
|
+
text = re.sub(r'`(.+?)`', f"{Colors.CYAN}\\1{Colors.RESET}", text)
|
|
440
|
+
|
|
441
|
+
# Lists with proper indentation and bullets
|
|
442
|
+
lines = text.split('\n')
|
|
443
|
+
formatted_lines = []
|
|
444
|
+
for i, line in enumerate(lines):
|
|
445
|
+
# Match different bullet point styles
|
|
446
|
+
bullet_match = re.match(r'^(\s*)([-•*]|\d+\.) (.+)$', line)
|
|
447
|
+
if bullet_match:
|
|
448
|
+
indent, bullet, content = bullet_match.groups()
|
|
449
|
+
indent_level = len(indent) // 2
|
|
450
|
+
|
|
451
|
+
# Choose bullet style based on nesting level
|
|
452
|
+
if indent_level == 0:
|
|
453
|
+
bullet_style = "•"
|
|
454
|
+
elif indent_level == 1:
|
|
455
|
+
bullet_style = "◦"
|
|
456
|
+
else:
|
|
457
|
+
bullet_style = "▪"
|
|
458
|
+
|
|
459
|
+
# Format the line with proper indentation and bullet
|
|
460
|
+
formatted_line = f"{' ' * (indent_level * 2)}{Colors.CYAN}{bullet_style}{Colors.RESET} {content}"
|
|
461
|
+
formatted_lines.append(formatted_line)
|
|
462
|
+
else:
|
|
463
|
+
formatted_lines.append(line)
|
|
464
|
+
text = '\n'.join(formatted_lines)
|
|
465
|
+
|
|
466
|
+
# Links with underline
|
|
467
|
+
text = re.sub(r'\[(.+?)\]\((.+?)\)', f"{Colors.BLUE}{Colors.UNDERLINE}\\1{Colors.RESET}", text)
|
|
468
|
+
|
|
469
|
+
# Blockquotes with style
|
|
470
|
+
text = re.sub(r'^> (.+)$', f"{self.markdown_theme['QUOTE']}│ \\1{Colors.RESET}", text, flags=re.M)
|
|
471
|
+
|
|
472
|
+
# Strikethrough
|
|
473
|
+
text = re.sub(r'~~(.+?)~~', f"{Colors.STRIKE}\\1{Colors.RESET}", text)
|
|
474
|
+
|
|
475
|
+
# Task lists with fancy checkboxes
|
|
476
|
+
text = re.sub(r'- \[ \] (.+)$', f"{self.markdown_theme['TASK']}☐ \\1{Colors.RESET}", text, flags=re.M)
|
|
477
|
+
text = re.sub(r'- \[x\] (.+)$', f"{self.markdown_theme['TASK']}☑ \\1{Colors.RESET}", text, flags=re.M)
|
|
478
|
+
|
|
479
|
+
# Tables with borders
|
|
480
|
+
table_pattern = r'\|(.+?)\|[\r\n]+\|[-:| ]+\|[\r\n]+((?:\|.+?\|[\r\n]+)+)'
|
|
481
|
+
text = re.sub(table_pattern, self._format_table_markdown, text, flags=re.M)
|
|
482
|
+
|
|
483
|
+
return text
|
|
484
|
+
|
|
485
|
+
def _format_table_markdown(self, match) -> str:
|
|
486
|
+
"""Format markdown tables with style."""
|
|
487
|
+
header = [cell.strip() for cell in match.group(1).split('|') if cell.strip()]
|
|
488
|
+
rows = []
|
|
489
|
+
for row in match.group(2).strip().split('\n'):
|
|
490
|
+
cells = [cell.strip() for cell in row.split('|')[1:-1]]
|
|
491
|
+
if cells:
|
|
492
|
+
rows.append(cells)
|
|
493
|
+
|
|
494
|
+
# Get column widths
|
|
495
|
+
widths = [max(len(str(row[i])) for row in [header] + rows) for i in range(len(header))]
|
|
496
|
+
|
|
497
|
+
# Build table
|
|
498
|
+
result = []
|
|
499
|
+
# Header
|
|
500
|
+
result.append('┌' + '┬'.join('─' * (w + 2) for w in widths) + '┐')
|
|
501
|
+
result.append('│ ' + ' │ '.join(f"{h:<{w}}" for h, w in zip(header, widths)) + ' │')
|
|
502
|
+
result.append('├' + '┼'.join('─' * (w + 2) for w in widths) + '┤')
|
|
503
|
+
# Rows
|
|
504
|
+
for row in rows:
|
|
505
|
+
result.append('│ ' + ' │ '.join(f"{str(c):<{w}}" for c, w in zip(row, widths)) + ' │')
|
|
506
|
+
result.append('└' + '┴'.join('─' * (w + 2) for w in widths) + '┘')
|
|
507
|
+
|
|
508
|
+
return '\n'.join(result)
|
|
509
|
+
|
|
510
|
+
def print(self, *args,
|
|
511
|
+
# Builtin print compatibility
|
|
512
|
+
sep: str = " ",
|
|
513
|
+
end: str = "\n",
|
|
514
|
+
file: Optional[TextIO] = None,
|
|
515
|
+
flush: bool = True,
|
|
516
|
+
|
|
517
|
+
# Styling options
|
|
518
|
+
style: Optional[str] = None,
|
|
519
|
+
color: Optional[str] = None,
|
|
520
|
+
bg_color: Optional[str] = None,
|
|
521
|
+
bold: bool = False,
|
|
522
|
+
italic: bool = False,
|
|
523
|
+
underline: bool = False,
|
|
524
|
+
blink: bool = False,
|
|
525
|
+
strike: bool = False,
|
|
526
|
+
dim: bool = False,
|
|
527
|
+
reverse: bool = False,
|
|
528
|
+
|
|
529
|
+
# Layout options
|
|
530
|
+
markdown: Optional[bool] = None,
|
|
531
|
+
highlight: bool = False,
|
|
532
|
+
center: bool = False,
|
|
533
|
+
indent: int = 0,
|
|
534
|
+
prefix: Optional[str] = None,
|
|
535
|
+
suffix: Optional[str] = None,
|
|
536
|
+
width: Optional[int] = None,
|
|
537
|
+
padding: int = 0,
|
|
538
|
+
margin: int = 0,
|
|
539
|
+
align: str = "left",
|
|
540
|
+
|
|
541
|
+
# Border options
|
|
542
|
+
border: bool = False,
|
|
543
|
+
border_style: Optional[str] = None,
|
|
544
|
+
border_char: str = "─",
|
|
545
|
+
border_color: Optional[str] = None,
|
|
546
|
+
rounded_corners: bool = False,
|
|
547
|
+
double_border: bool = False,
|
|
548
|
+
|
|
549
|
+
# Animation options
|
|
550
|
+
animate: bool = False,
|
|
551
|
+
animation_speed: float = 0.05,
|
|
552
|
+
animation_type: str = "typing",
|
|
553
|
+
|
|
554
|
+
# Special features
|
|
555
|
+
as_table: bool = False,
|
|
556
|
+
as_tree: bool = False,
|
|
557
|
+
as_json: bool = False,
|
|
558
|
+
as_code: bool = False,
|
|
559
|
+
language: str = "python",
|
|
560
|
+
|
|
561
|
+
# Advanced features
|
|
562
|
+
raw: bool = False) -> None:
|
|
563
|
+
"""
|
|
564
|
+
Enhanced print with all builtin features plus rich formatting.
|
|
565
|
+
|
|
566
|
+
Supports all builtin print parameters plus rich formatting features.
|
|
567
|
+
Automatically detects and formats markdown content unless explicitly disabled.
|
|
568
|
+
"""
|
|
569
|
+
# Handle raw output mode
|
|
570
|
+
if raw:
|
|
571
|
+
print(*args, sep=sep, end=end, file=file or self.file, flush=flush)
|
|
572
|
+
return
|
|
573
|
+
|
|
574
|
+
# Join args with separator
|
|
575
|
+
output = sep.join(str(arg) for arg in args)
|
|
576
|
+
|
|
577
|
+
# Auto-detect markdown if not explicitly set
|
|
578
|
+
if markdown is None:
|
|
579
|
+
markdown = any(marker in output for marker in [
|
|
580
|
+
'#', '*', '_', '`', '>', '-', '•', '|',
|
|
581
|
+
# '✨', '🔥', '💫', '☐', '☑',
|
|
582
|
+
'http://', 'https://',
|
|
583
|
+
'```', '~~~',
|
|
584
|
+
'<details>', '<summary>',
|
|
585
|
+
])
|
|
586
|
+
|
|
587
|
+
# Apply markdown formatting if enabled
|
|
588
|
+
if markdown:
|
|
589
|
+
output = self._format_markdown_stream(output)
|
|
590
|
+
|
|
591
|
+
# Build style string
|
|
592
|
+
style_str = style or ""
|
|
593
|
+
if color:
|
|
594
|
+
style_str += getattr(Colors, color.upper(), "")
|
|
595
|
+
if bg_color:
|
|
596
|
+
style_str += getattr(Colors, f"BG_{bg_color.upper()}", "")
|
|
597
|
+
if bold:
|
|
598
|
+
style_str += Colors.BOLD
|
|
599
|
+
if italic:
|
|
600
|
+
style_str += Colors.ITALIC
|
|
601
|
+
if underline:
|
|
602
|
+
style_str += Colors.UNDERLINE
|
|
603
|
+
if blink:
|
|
604
|
+
style_str += Colors.BLINK
|
|
605
|
+
if strike:
|
|
606
|
+
style_str += Colors.STRIKE
|
|
607
|
+
if dim:
|
|
608
|
+
style_str += Colors.DIM
|
|
609
|
+
if reverse:
|
|
610
|
+
style_str += Colors.REVERSE
|
|
611
|
+
|
|
612
|
+
# Apply style if any
|
|
613
|
+
if style_str:
|
|
614
|
+
output = f"{style_str}{output}{Colors.RESET}"
|
|
615
|
+
|
|
616
|
+
# Handle special formatting
|
|
617
|
+
if as_json:
|
|
618
|
+
output = self._format_json(output)
|
|
619
|
+
elif as_code:
|
|
620
|
+
output = self._highlight_code(output, language)
|
|
621
|
+
elif as_table:
|
|
622
|
+
if isinstance(output, (list, tuple)):
|
|
623
|
+
self.table(*output)
|
|
624
|
+
return
|
|
625
|
+
elif as_tree:
|
|
626
|
+
if isinstance(output, (dict, list)):
|
|
627
|
+
self.tree(output)
|
|
628
|
+
return
|
|
629
|
+
|
|
630
|
+
# Apply layout options
|
|
631
|
+
if center:
|
|
632
|
+
term_width = self._get_terminal_width()
|
|
633
|
+
output = output.center(term_width)
|
|
634
|
+
if indent > 0:
|
|
635
|
+
output = " " * (indent * 4) + output
|
|
636
|
+
if prefix:
|
|
637
|
+
output = prefix + output
|
|
638
|
+
if suffix:
|
|
639
|
+
output = output + suffix
|
|
640
|
+
if width:
|
|
641
|
+
output = textwrap.fill(output, width=width)
|
|
642
|
+
|
|
643
|
+
# Add borders
|
|
644
|
+
if border:
|
|
645
|
+
width = max(len(line) for line in output.split('\n'))
|
|
646
|
+
border_top = '┌' + border_char * width + '┐'
|
|
647
|
+
border_bottom = '└' + border_char * width + '┘'
|
|
648
|
+
output = f"{border_top}\n{output}\n{border_bottom}"
|
|
649
|
+
|
|
650
|
+
# Handle animation
|
|
651
|
+
if animate:
|
|
652
|
+
for char in output:
|
|
653
|
+
print(char, end="", flush=True)
|
|
654
|
+
time.sleep(animation_speed)
|
|
655
|
+
print(end=end, flush=flush)
|
|
656
|
+
return
|
|
657
|
+
|
|
658
|
+
# Final output
|
|
659
|
+
print(output, end=end, file=file or self.file, flush=flush)
|
|
660
|
+
|
|
661
|
+
def status(self, text: str, style: Optional[str] = None):
|
|
662
|
+
"""Print a status message that can be overwritten."""
|
|
663
|
+
style = style or self.theme['info']
|
|
664
|
+
self._clear_line()
|
|
665
|
+
self._last_line = f"{style}{text}{Colors.RESET}"
|
|
666
|
+
print(self._last_line, end='\r', file=self.file, flush=True)
|
|
667
|
+
|
|
668
|
+
def banner(self, text: str, style: Optional[str] = None):
|
|
669
|
+
"""Print a fancy banner with hover info."""
|
|
670
|
+
print(f"\033]1337;Custom=id=banner:{HoverInfo.BANNER}\a", end='')
|
|
671
|
+
style = style or self.theme['special']
|
|
672
|
+
width = self._get_terminal_width() - 4
|
|
673
|
+
|
|
674
|
+
lines = textwrap.wrap(text, width=width, break_long_words=False)
|
|
675
|
+
|
|
676
|
+
print('╔' + '═' * width + '╗')
|
|
677
|
+
for line in lines:
|
|
678
|
+
padding = width - len(line)
|
|
679
|
+
print('║ ' + line + ' ' * padding + ' ║')
|
|
680
|
+
print('╚' + '═' * width + '╝')
|
|
681
|
+
print("\033]1337;Custom=id=banner:end\a", end='')
|
|
682
|
+
|
|
683
|
+
def success(self, text: str):
|
|
684
|
+
"""Print a success message with hover info."""
|
|
685
|
+
print(f"\033]1337;Custom=id=success:{HoverInfo.SUCCESS}\a", end='')
|
|
686
|
+
self.print(f"✓ {text}", style=self.theme['success'])
|
|
687
|
+
print("\033]1337;Custom=id=success:end\a", end='')
|
|
688
|
+
|
|
689
|
+
def error(self, text: str):
|
|
690
|
+
"""Print an error message with hover info."""
|
|
691
|
+
print(f"\033]1337;Custom=id=error:{HoverInfo.ERROR}\a", end='')
|
|
692
|
+
self.print(f"✗ {text}", style=self.theme['error'])
|
|
693
|
+
print("\033]1337;Custom=id=error:end\a", end='')
|
|
694
|
+
|
|
695
|
+
def warning(self, text: str):
|
|
696
|
+
"""Print a warning message with hover info."""
|
|
697
|
+
print(f"\033]1337;Custom=id=warning:{HoverInfo.WARNING}\a", end='')
|
|
698
|
+
self.print(f"⚠ {text}", style=self.theme['warning'])
|
|
699
|
+
print("\033]1337;Custom=id=warning:end\a", end='')
|
|
700
|
+
|
|
701
|
+
def info(self, text: str):
|
|
702
|
+
"""Print an info message with hover info."""
|
|
703
|
+
print(f"\033]1337;Custom=id=info:{HoverInfo.INFO}\a", end='')
|
|
704
|
+
self.print(f"ℹ {text}", style=self.theme['info'])
|
|
705
|
+
print("\033]1337;Custom=id=info:end\a", end='')
|
|
706
|
+
|
|
707
|
+
def table(self, headers: List[str], rows: List[List[Any]], style: Optional[str] = None):
|
|
708
|
+
"""Print a formatted table."""
|
|
709
|
+
style = style or self.theme['special']
|
|
710
|
+
|
|
711
|
+
col_widths = [len(h) for h in headers]
|
|
712
|
+
for row in rows:
|
|
713
|
+
for i, cell in enumerate(row):
|
|
714
|
+
col_widths[i] = max(col_widths[i], len(str(cell)))
|
|
715
|
+
|
|
716
|
+
header_line = '| ' + ' | '.join(f"{h:<{w}}" for h, w in zip(headers, col_widths)) + ' |'
|
|
717
|
+
print(header_line)
|
|
718
|
+
|
|
719
|
+
separator = '+' + '+'.join('-' * (w + 2) for w in col_widths) + '+'
|
|
720
|
+
print(separator)
|
|
721
|
+
|
|
722
|
+
for row in rows:
|
|
723
|
+
row_line = '| ' + ' | '.join(f"{str(cell):<{w}}" for cell, w in zip(row, col_widths)) + ' |'
|
|
724
|
+
print(row_line)
|
|
725
|
+
|
|
726
|
+
def tree(self, data: Union[Dict, List], indent: int = 0):
|
|
727
|
+
"""Print a tree structure of nested data."""
|
|
728
|
+
if isinstance(data, dict):
|
|
729
|
+
for key, value in data.items():
|
|
730
|
+
self.print(" " * indent + "├─ " + str(key) + ":", style=self.theme['key'])
|
|
731
|
+
if isinstance(value, (dict, list)):
|
|
732
|
+
self.tree(value, indent + 1)
|
|
733
|
+
else:
|
|
734
|
+
self.print(" " * (indent + 1) + "└─ " + str(value))
|
|
735
|
+
elif isinstance(data, list):
|
|
736
|
+
for item in data:
|
|
737
|
+
if isinstance(item, (dict, list)):
|
|
738
|
+
self.tree(item, indent + 1)
|
|
739
|
+
else:
|
|
740
|
+
self.print(" " * indent + "├─ " + str(item))
|
|
741
|
+
|
|
742
|
+
def json(self, data: Any, indent: int = 4):
|
|
743
|
+
"""Print formatted JSON data."""
|
|
744
|
+
formatted = json.dumps(data, indent=indent)
|
|
745
|
+
self.print(formatted, highlight=True)
|
|
746
|
+
|
|
747
|
+
def code_block(self, code: str, language: str = "python"):
|
|
748
|
+
"""Print code in a fancy box with syntax highlighting."""
|
|
749
|
+
highlighted = self._highlight_code(code, language)
|
|
750
|
+
lines = highlighted.split('\n')
|
|
751
|
+
|
|
752
|
+
width = max(len(line) for line in lines)
|
|
753
|
+
width = min(width, self._get_terminal_width() - 4) # Account for borders
|
|
754
|
+
|
|
755
|
+
print('┌' + '─' * width + '┐')
|
|
756
|
+
|
|
757
|
+
for line in lines:
|
|
758
|
+
if len(line) > width:
|
|
759
|
+
line = line[:width-3] + '...'
|
|
760
|
+
else:
|
|
761
|
+
line = line + ' ' * (width - len(line))
|
|
762
|
+
print('│ ' + line + ' │')
|
|
763
|
+
|
|
764
|
+
print('└' + '─' * width + '┘')
|
|
765
|
+
|
|
766
|
+
def _clear_line(self):
|
|
767
|
+
"""Clear the current line."""
|
|
768
|
+
print('\r' + ' ' * self._get_terminal_width(), end='\r', file=self.file, flush=True)
|
|
769
|
+
|
|
770
|
+
if __name__ == "__main__":
|
|
771
|
+
printer = LitPrinter()
|
|
772
|
+
|
|
773
|
+
printer.banner("Welcome to the LitPrinter Demo! ")
|
|
774
|
+
|
|
775
|
+
printer.status("Loading that heat... ")
|
|
776
|
+
time.sleep(1)
|
|
777
|
+
printer.status("Almost ready to drop... ")
|
|
778
|
+
time.sleep(1)
|
|
779
|
+
printer.status("")
|
|
780
|
+
|
|
781
|
+
printer.success("Ayy, we made it! ")
|
|
782
|
+
printer.error("Houston, we got a problem! ")
|
|
783
|
+
printer.warning("Hold up, something sus... ")
|
|
784
|
+
printer.info("Just so you know fam... ")
|
|
785
|
+
|
|
786
|
+
headers = ["Name", "Vibe", "Energy"]
|
|
787
|
+
rows = [
|
|
788
|
+
["Python", "Immaculate", "100%"],
|
|
789
|
+
["Java", "Decent", "75%"],
|
|
790
|
+
["C++", "Complex", "85%"]
|
|
791
|
+
]
|
|
792
|
+
printer.table(headers, rows)
|
|
793
|
+
|
|
794
|
+
data = {
|
|
795
|
+
"squad": {
|
|
796
|
+
"python": {"vibe": "lit", "power": "over 9000"},
|
|
797
|
+
"javascript": {"vibe": "cool", "power": "8000"}
|
|
798
|
+
},
|
|
799
|
+
"config": {
|
|
800
|
+
"mode": "beast",
|
|
801
|
+
"activated": True
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
printer.tree(data)
|
|
805
|
+
|
|
806
|
+
printer.json(data)
|
|
807
|
+
|
|
808
|
+
code = '''def print_drip():
|
|
809
|
+
# This function brings the heat
|
|
810
|
+
print("Straight bussin!")
|
|
811
|
+
return True # No cap'''
|
|
812
|
+
printer.code_block(code)
|
|
813
|
+
|
|
814
|
+
printer.print("Basic text but make it fancy ")
|
|
815
|
+
printer.print("Colors go hard", style=Colors.GREEN)
|
|
816
|
+
printer.print("Bold & Blue = Different breed", style=Colors.BLUE + Colors.BOLD)
|
|
817
|
+
|
|
818
|
+
markdown_text = """# Main Title (Straight Fire)
|
|
819
|
+
## Subtitle (Also Heat)
|
|
820
|
+
- First thing's first
|
|
821
|
+
- Second thing's second
|
|
822
|
+
**Bold moves** and *smooth style*
|
|
823
|
+
"""
|
|
824
|
+
printer.print(markdown_text, markdown=True)
|
|
825
|
+
|
|
826
|
+
test_dict = {
|
|
827
|
+
"name": "LitPrinter",
|
|
828
|
+
"vibes": ["immaculate", "unmatched", "different"],
|
|
829
|
+
"config": {"mode": "beast", "level": "over 9000"}
|
|
830
|
+
}
|
|
831
|
+
printer.print(test_dict)
|