Skip to content

Instantly share code, notes, and snippets.

@r0x0d
Created December 12, 2024 19:27
Show Gist options
  • Save r0x0d/f4f25257cdb294b1e79fc0e3f30918ed to your computer and use it in GitHub Desktop.
Save r0x0d/f4f25257cdb294b1e79fc0e3f30918ed to your computer and use it in GitHub Desktop.
import shutil
import time
from pathlib import Path
from typing import List, Tuple
from command_line_assistant.rendering.decorators.colors import ColorDecorator
from command_line_assistant.rendering.decorators.style import StyleDecorator
from command_line_assistant.rendering.decorators.text import (
EmojiDecorator,
TextWrapDecorator,
WriteOnceDecorator,
)
from command_line_assistant.rendering.renders.spinner import Frames, SpinnerRenderer
from command_line_assistant.rendering.renders.text import TextRenderer
from command_line_assistant.rendering.stream import StdoutStream
def get_terminal_width() -> int:
"""Get current terminal width."""
return shutil.get_terminal_size().columns
def render_row(items: List[Tuple[TextRenderer, str]], column_width: int = 30) -> None:
"""Render a row of items with proper spacing."""
for renderer, text in items:
formatted_text = f"{text:<{column_width}}"
renderer.render(formatted_text)
print() # New line after each row
def chunk_list(lst: list, chunk_size: int) -> List[list]:
"""Split list into chunks of specified size."""
return [lst[i:i + chunk_size] for i in range(0, len(lst), chunk_size)]
def demo_color_decorator():
print("\nColor Decorator Demo")
print("=" * get_terminal_width())
# Calculate widths for formatting
name_width = 15
sample_width = 20
total_width = name_width + sample_width + 5 # 5 for spacing
columns = get_terminal_width() // total_width
def print_color_row(colors: List[str], is_background: bool = False):
for i in range(0, len(colors), columns):
chunk = colors[i:i + columns]
# Print each color in the chunk
for color in chunk:
# Print color name without decoration
print(f"{color:<{name_width}}", end="")
# Print sample text with color decoration
renderer = TextRenderer()
if is_background:
renderer.update(ColorDecorator(foreground="white", background=color))
sample_text = "Sample Text"
else:
renderer.update(ColorDecorator(foreground=color))
sample_text = "Sample Text"
renderer.render(f"{sample_text:<{sample_width}}")
print() # New line after each row
# Foreground Colors
print("\nForeground Colors:")
print("-" * get_terminal_width())
foreground_colors = list(ColorDecorator.FOREGROUND_COLORS.keys())
print_color_row(foreground_colors)
# Background Colors
print("\nBackground Colors:")
print("-" * get_terminal_width())
background_colors = list(ColorDecorator.BACKGROUND_COLORS.keys())
print_color_row(background_colors, is_background=True)
def demo_style_decorator():
print("\nStyle Decorator Demo:")
print("--------------------")
terminal_width = get_terminal_width()
columns_per_row = terminal_width // 30
items = []
for style in StyleDecorator.STYLES.keys():
renderer = TextRenderer()
renderer.update(StyleDecorator(style=style))
items.append((renderer, f"Style {style}"))
rows = chunk_list(items, columns_per_row)
for row in rows:
render_row(row)
def demo_emoji_decorator():
print("\nEmoji Decorator Demo:")
print("--------------------")
emoji_samples = [
("U+1F600", "Grinning Face"),
("U+1F4BB", "Laptop"),
("U+2728", "Sparkles"),
("U+1F680", "Rocket"),
("U+1F4A1", "Light Bulb"),
("U+1F431", "Cat Face"),
("U+1F436", "Dog Face"),
("U+1F951", "Avocado"),
("U+1F389", "Party Popper"),
("U+1F3C6", "Trophy"),
]
terminal_width = get_terminal_width()
columns_per_row = terminal_width // 35 # Wider columns for emojis
items = []
for code, description in emoji_samples:
renderer = TextRenderer()
renderer.update(EmojiDecorator(code))
items.append((renderer, description))
rows = chunk_list(items, columns_per_row)
for row in rows:
render_row(row, column_width=35)
def demo_text_wrap_decorator():
print("\nText Wrap Decorator Demo:")
print("-----------------------")
sample_text = "This is a sample text that demonstrates wrapping. It should show different wrapping styles and indentation options available in the TextWrapDecorator."
# Default wrap
print("\nDefault wrap:")
renderer = TextRenderer()
renderer.update(TextWrapDecorator())
renderer.render(sample_text)
# Custom width wrap
print("\nCustom width (40 chars):")
renderer = TextRenderer()
renderer.update(TextWrapDecorator(width=40))
renderer.render(sample_text)
# Indented wrap
print("\nIndented wrap:")
renderer = TextRenderer()
renderer.update(TextWrapDecorator(indent=" "))
renderer.render(sample_text)
def demo_write_once_decorator():
print("\nWrite Once Decorator Demo")
print("========================")
# First, ensure we clean up any existing state files
state_dir = Path("~/.local/state/command-line-assistant").expanduser()
if state_dir.exists():
for file in state_dir.glob("demo_*"):
file.unlink()
messages = [
("demo_1", "This message should appear only once"),
("demo_2", "This is another one-time message"),
("demo_1", "This won't appear because demo_1 was already shown"),
("demo_2", "This won't appear because demo_2 was already shown"),
("demo_3", "But this new message with demo_3 will appear")
]
print("\nRunning multiple writes with different state files:")
print("------------------------------------------------")
for state_file, message in messages:
renderer = TextRenderer()
renderer.update(WriteOnceDecorator(state_filename=state_file))
renderer.render(message)
print("\nRunning the same messages again:")
print("-------------------------------")
for state_file, message in messages:
renderer = TextRenderer()
renderer.update(WriteOnceDecorator(state_filename=state_file))
renderer.render(message)
def demo_stdout_stream():
print("\nStdout Stream Demo")
print("=================")
renderer = TextRenderer() # Default is stdout
renderer.update(ColorDecorator(foreground="green"))
print("Standard output:", end="\t")
renderer.render("This message goes to stdout")
def demo_stderr_stream():
from command_line_assistant.rendering.stream import StderrStream
print("\nStderr Stream Demo")
print("=================")
renderer = TextRenderer(stream=StderrStream())
renderer.update(ColorDecorator(foreground="red"))
print("Standard error:")
renderer.render("This message goes to stderr")
def demo_spinner_renderer():
print("\nSpinner Renderer Demo")
print("====================")
# Basic spinner with color
print("\nBasic spinner with color:")
spinner = SpinnerRenderer(
message="Loading with green color",
stream=StdoutStream(end=""),
delay=0.1
)
spinner.update(ColorDecorator(foreground="green"))
with spinner:
time.sleep(2)
# Spinner with emoji and color
print("\nSpinner with emoji and color:")
spinner = SpinnerRenderer(
message="Processing with robot emoji",
stream=StdoutStream(end=""),
delay=0.1
)
spinner.update(EmojiDecorator("U+1F916"))
spinner.update(ColorDecorator(foreground="cyan"))
with spinner:
time.sleep(2)
# Spinner with multiple decorators
print("\nSpinner with multiple decorators:")
spinner = SpinnerRenderer(
message="Complex spinner demonstrating multiple decorators working together seamlessly",
stream=StdoutStream(end=""),
frames=Frames.moving,
delay=0.1
)
spinner.update(EmojiDecorator("U+1F680"))
spinner.update(ColorDecorator(foreground="magenta"))
with spinner:
time.sleep(2)
def main():
print(f"Rendering Library Demo (Terminal width: {get_terminal_width()} columns)")
print("="* get_terminal_width())
demo_spinner_renderer()
# ---
demo_color_decorator()
demo_style_decorator()
demo_emoji_decorator()
demo_text_wrap_decorator()
demo_write_once_decorator()
# ---
demo_stdout_stream()
demo_stderr_stream()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment