Vargula API

A comprehensive Python library for terminal text styling, formatting, and UI components.


API Reference

Creating Instances

Thread-Safe Operations

Each Vargula instance maintains its own state, making them inherently thread-safe when used independently. This is essential for concurrent applications:

from vargula import Vargula
import threading
import time

def process_with_theme(theme_name: str, task_id: int):
    """Each thread creates its own instance for complete isolation"""
    # Create a dedicated instance for this thread
    vg = Vargula()
    vg.set_theme(theme_name)
    
    # Do work with isolated styling
    for i in range(3):
        vg.write(f"[Task {task_id}] Step {i+1} processing...")
        time.sleep(0.5)
    
    vg.write(f"[Task {task_id}] <green>Complete!</green>")

# Create threads with different themes
threads = [
    threading.Thread(target=process_with_theme, args=("dark", 1)),
    threading.Thread(target=process_with_theme, args=("light", 2)),
    threading.Thread(target=process_with_theme, args=("dark", 3))
]

# Start all threads - no style interference between them
for thread in threads:
    thread.start()

# Wait for completion
for thread in threads:
    thread.join()

Output:

Demo

Why this matters for threading:

  • No global state to cause race conditions

  • Each thread can have its own theme

  • Styles set in one thread don’t affect others

  • Safe for use in thread pools and async contexts

Core Styling Functions

style(text, color=None, bg=None, look=None)

Apply styling to text directly.

Parameters:

  • text (str): Text to style

  • color (str|tuple): Foreground color (name, hex, or RGB tuple)

  • bg (str|tuple): Background color (name, hex, or RGB tuple)

  • look (str|list): Text decoration(s) - “bold”, “italic”, “underline”, etc.

Returns: Styled string with ANSI codes

Examples:

# Named colors
print(vg.style("Error", color="red", look="bold"))

# Hex colors
print(vg.style("Custom", color="#FF5733", bg="#1a1a1a"))

# RGB tuples
print(vg.style("RGB", color=(255, 87, 51)))

# Multiple looks
print(vg.style("Fancy", color="cyan", look=["bold", "underline"]))

Demo

Available Colors:

  • Basic: black, red, green, yellow, blue, magenta, cyan, white

  • Bright: bright_black, bright_red, bright_green, bright_yellow, bright_blue, bright_magenta, bright_cyan, bright_white

Available Looks:

  • bold, dim, italic, underline, blink, reverse, hidden, strikethrough

format(text)

Format text using HTML-like markup tags.

Parameters:

  • text (str): Text with markup tags

Returns: Formatted string with ANSI codes

Examples:

# Using predefined color tags
print(vg.format("This is <red>red</red> and <blue>blue</blue>"))

# Using custom styles (see create())
vg.create("error", color="red", look="bold")
print(vg.format("An <error>error</error> occurred"))

# Nested tags
print(vg.format("<bold>Bold with <red>red text</red></bold>"))

# Hex colors directly
print(vg.format("Hex <#FF5733>color</#FF5733>"))

# Combined styles
print(vg.format("<bold><underline><cyan>Triple style</cyan></underline></bold>"))

Demo

create(name, color=None, bg=None, look=None)

Create a custom reusable style tag.

Parameters:

  • name (str): Name of the custom style

  • color (str|tuple): Foreground color

  • bg (str|tuple): Background color

  • look (str|list): Text decoration(s)

Returns: None

Examples:

# Create custom styles
vg.create("error", color="red", look="bold")
vg.create("success", color="green", look="bold")
vg.create("highlight", bg="yellow", color="black")

# Use them with format()
print(vg.format("<error>Error!</error>"))
print(vg.format("<success>Success!</success>"))
print(vg.format("<highlight>Important</highlight>"))

Demo

delete(name)

Delete a custom style tag.

Parameters:

  • name (str): Name of the style to delete

Returns: bool - True if deleted, False if not found

Example:

vg.create("temp", color="blue")
vg.delete("temp")  # Returns True
vg.delete("temp")  # Returns False (already deleted)

write(*args, sep=" ", end="\n", file=None, flush=False)

Format and print text with markup in one call. Works exactly like built-in print() but automatically formats markup tags.

Parameters:

  • *args: Values to print (will be converted to strings and formatted)

  • sep (str): String inserted between values (default: single space)

  • end (str): String appended after the last value (default: newline)

  • file: File object; defaults to sys.stdout

  • flush (bool): Whether to forcibly flush the stream

Returns: None (prints to stdout)

Examples:

# Basic usage
vg.write("This is <red>red</red> and <bold>bold</bold>")

# Multiple arguments with custom separator
vg.write("Hello", "<red>World</red>", sep=" → ")
# Output: Hello → World (with "World" in red)

# Formatted separator
vg.write("user", "localhost", sep=vg.format("<cyan>@</cyan>"))
# Output: user@localhost (with @ in cyan)

# Custom end character
vg.write("<bold>Processing</bold>", end="... ")
vg.write("<green>Done!</green>")
# Output: Processing... Done! (on same line)

Demo

strip(text)

Remove all markup tags from text.

Parameters:

  • text (str): Text containing markup tags

Returns: Plain text without tags

Example:

text = "Hello <red>world</red>!"
plain = vg.strip(text)  # "Hello world!"

clean(text)

Remove all ANSI escape codes from text.

Parameters:

  • text (str): Text containing ANSI codes

Returns: Plain text without ANSI codes

Example:

styled = vg.style("Colored", color="red")
plain = vg.clean(styled)  # "Colored" (no ANSI codes)

length(text)

Calculate visible length of text (ignoring ANSI codes).

Parameters:

  • text (str): Text with ANSI codes

Returns: int - Visible character count

Example:

styled = vg.style("Hello", color="red")
print(len(styled))        # 18 (includes ANSI codes)
print(vg.length(styled))  # 5 (visible length)

enable() / disable()

Globally enable or disable styling.

Parameters: None

Returns: None

Example:

vg.disable()
print(vg.style("No color", color="red"))  # Prints plain text

vg.enable()
print(vg.style("Has color", color="red"))  # Prints colored text

temporary(name, color=None, bg=None, look=None)

Context manager for temporary custom styles.

Parameters: Same as create()

Returns: Context manager

Example:

with vg.temporary("temp", color="cyan", look="bold"):
    print(vg.format("<temp>Temporary style</temp>"))
# "temp" style is automatically deleted after the block

Demo

Theme Functions

set_theme(theme)

Set a predefined or custom theme.

Parameters:

  • theme (str|dict): Theme name (“dark”, “light”) or custom theme dictionary

Returns: None

Example:

# Built-in themes
vg.set_theme("dark")
print(vg.format("<error>Error!</error> <success>OK</success>"))

vg.set_theme("light")
print(vg.format("<warning>Warning</warning>"))

# Custom theme
custom = {
    "error": {"color": "red", "look": "bold"},
    "info": {"color": "blue"},
    "highlight": {"bg": "yellow", "color": "black"}
}
vg.set_theme(custom)

Demo

Built-in Theme Styles:

  • error, success, warning, info, debug, critical

Tables

Table(title=None, caption=None, ...)

Create a Rich-style table with customizable styling.

Parameters:

  • title (str): Optional title above table

  • caption (str): Optional caption below table

  • style (str): Default style for all cells

  • title_style (str): Style for title (default: “bold”)

  • caption_style (str): Style for caption (default: “dim”)

  • header_style (str): Style for header row (default: “bold”)

  • border_style (str): Style for border characters

  • show_header (bool): Show header row (default: True)

  • show_lines (bool): Show lines between rows (default: False)

  • padding (tuple): (vertical, horizontal) padding (default: (0, 1))

  • expand (bool): Expand to full terminal width (default: False)

  • min_width (int): Minimum table width

  • box (str): Border style (default: “rounded”)

Box Styles:

  • "rounded" - Rounded corners (╭─╮)

  • "square" - Square corners (┌─┐)

  • "double" - Double lines (╔═╗)

  • "heavy" - Heavy lines (┏━┓)

  • "minimal" - Minimal borders

  • "none" - No borders

Example:

table = vg.Table(
    title="Sales Report",
    caption="Q4 2024",
    title_style="bold cyan",
    border_style="blue",
    show_lines=True,
    box="double"
)

table.add_column("Region", style="cyan", justify="left")
table.add_column("Revenue", style="green", justify="right")
table.add_column("Growth", style="yellow", justify="center")

table.add_row("North", "$1.2M", "+15%")
table.add_row("South", "$890K", "+8%", style="dim")
table.add_row("East", "$1.5M", "+22%")

print(table)

Output:

Demo

Table.add_column(header, style=None, justify="left", ...)

Add a column to the table.

Parameters:

  • header (str): Column header text

  • style (str): Style for this column’s cells

  • justify (str): Alignment - “left”, “center”, “right”

  • no_wrap (bool): Disable text wrapping

  • overflow (str): Overflow handling - “ellipsis”, “crop”, “fold”

  • width (int): Fixed column width

  • min_width (int): Minimum column width

  • max_width (int): Maximum column width

Example:

table.add_column("Name", style="bold", justify="left", width=20)
table.add_column("Score", style="green", justify="right", max_width=10)
table.add_column("Status", justify="center")

Demo

Table.add_row(*cells, style=None)

Add a row of data to the table.

Parameters:

  • *cells: Cell values (one per column)

  • style (str): Style for entire row (overrides column styles)

Example:

table.add_row("Alice", "95", "Active")
table.add_row("Bob", "87", "Active", style="dim")  # Dimmed row

Demo

Progress Bars

ProgressBar(total=100, desc="", ...)

Create a customizable progress bar.

Parameters:

  • total (int): Total number of iterations

  • desc (str): Description text

  • unit (str): Unit name (e.g., “files”, “items”, “it”)

  • bar_width (int): Width of progress bar (default: 40)

  • complete_style (str): Style for completed portion (default: “green”)

  • incomplete_style (str): Style for incomplete portion (default: “bright_black”)

  • percentage_style (str): Style for percentage (default: “cyan”)

  • desc_style (str): Style for description (default: “bold”)

  • show_percentage (bool): Show percentage (default: True)

  • show_count (bool): Show count (default: True)

  • show_rate (bool): Show processing rate (default: True)

  • show_eta (bool): Show estimated time (default: True)

  • refresh_rate (float): Min seconds between updates (default: 0.1)

Example:

import time

progress = vg.ProgressBar(
    total=500,
    desc="Downloading",
    unit="files",
    bar_width=50,
    complete_style="green",
    desc_style="bold cyan"
)

for i in range(500):
    # Do work
    time.sleep(0.01)
    progress.update(1)

progress.close()

Output:

Demo

ProgressBar.update(n=1)

Update progress by n steps.

Parameters:

  • n (int): Number of steps to advance (default: 1)

Example:

pbar = vg.ProgressBar(total=100)
pbar.update(1)   # Advance by 1
pbar.update(10)  # Advance by 10

ProgressBar.close()

Complete and close the progress bar.

Example:

pbar = vg.ProgressBar(total=100)
# ... work ...
pbar.close()  # Ensures final state is displayed

progress_bar(iterable, total=None, desc="", **kwargs)

Wrap an iterable with a progress bar.

Parameters:

  • iterable: Any iterable object

  • total (int): Total count (auto-detected if possible)

  • desc (str): Description

  • **kwargs: Additional ProgressBar arguments

Returns: Iterator yielding items from iterable

Example:

import time

for item in vg.progress_bar(range(100), desc="Processing"):
    # Process item
    time.sleep(0.01)

Output:

Demo

MultiProgress()

Manage multiple progress bars simultaneously.

Example:

with vg.MultiProgress() as mp:
    task1 = mp.add_task("Download", total=100)
    task2 = mp.add_task("Extract", total=50)
    task3 = mp.add_task("Process", total=75)
    
    for i in range(100):
        mp.update(task1, 1)
        if i % 2 == 0:
            mp.update(task2, 1)
        if i % 3 == 0:
            mp.update(task3, 1)
        time.sleep(0.02)

Output:

Demo

MultiProgress.add_task(desc, total=100, **kwargs)

Add a new progress task.

Parameters:

  • desc (str): Task description

  • total (int): Total iterations

  • **kwargs: Additional ProgressBar arguments

Returns: int - Task ID for updating

MultiProgress.update(task_id, n=1)

Update a specific task.

Parameters:

  • task_id (int): ID returned from add_task()

  • n (int): Steps to advance

Color Palette Generation

generate_palette(base_color=None, scheme="random", count=5, ...)

Generate a color palette based on color theory.

Parameters:

  • base_color (str): Starting hex color (e.g., ‘#FF5733’). Random if None

  • scheme (str): Color harmony scheme

  • count (int): Number of colors to generate

  • saturation_range (tuple): (min, max) saturation (0-1)

  • value_range (tuple): (min, max) brightness (0-1)

  • randomize (bool): Add slight variations (default: True)

Returns: List of hex color strings

Schemes:

  • "monochromatic" - Single hue variations

  • "analogous" - Adjacent hues (±30°)

  • "complementary" - Opposite hues (180°)

  • "triadic" - Three evenly spaced hues (120°)

  • "tetradic" - Four hues (60°, 180°, 240°)

  • "split_complementary" - Base + two adjacent to complement

  • "square" - Four evenly spaced hues (90°)

  • "random" - Random colors

Examples:

# Complementary palette from blue
colors = vg.generate_palette("#3498db", "complementary", 5)
# ['#3498db', '#db7834', '#34a4db', '#db3449', '#4ddb34']

# Random palette
colors = vg.generate_palette(scheme="random", count=8)

# Analogous with custom ranges
colors = vg.generate_palette(
    base_color="#e74c3c",
    scheme="analogous",
    count=6,
    saturation_range=(0.6, 0.9),
    value_range=(0.6, 0.95)
)

generate_theme_palette(scheme="random", base_color=None, ...)

Generate a complete theme with semantic colors.

Parameters:

  • scheme (str): Color harmony scheme

  • base_color (str): Optional base color

  • include_neutrals (bool): Add grayscale colors (default: True)

  • force_semantic_colors (bool): Use standard colors for success/warning/error (default: False)

Returns: Dictionary mapping theme names to hex colors

Example:

theme = vg.generate_theme_palette("complementary", "#3498db")
# {
#     'primary': '#3498db',
#     'secondary': '#db7834',
#     'accent': '#34dbb4',
#     'success': '#2ecc71',
#     'warning': '#f39c12',
#     'error': '#e74c3c',
#     'info': '#3498db',
#     'background': '#1a1a1a',
#     'foreground': '#e0e0e0'
# }

vg.apply_palette_theme(theme)
print(vg.format("<primary>Primary</primary> <error>Error</error>"))

generate_accessible_theme(base_color, scheme="complementary", ...)

Generate theme with WCAG contrast validation.

Parameters:

  • base_color (str): Base hex color

  • scheme (str): Color harmony scheme

  • background (str): Background color (default: “#1a1a1a”)

  • min_contrast (float): Minimum contrast ratio (default: 4.5)

  • wcag_level (str): “AA” or “AAA”

Returns: Dictionary with accessible colors

Example:

# All colors will meet WCAG AA on white background
theme = vg.generate_accessible_theme(
    "#3498db",
    scheme="triadic",
    background="#ffffff",
    wcag_level="AA"
)

preview_palette(colors, width=40, show_info=True)

Generate text preview of a color palette.

Parameters:

  • colors (list): List of hex colors

  • width (int): Width of color blocks (default: 40)

  • show_info (bool): Show HSV values (default: True)

Returns: Formatted string with colored blocks

Example:

colors = vg.generate_palette("#3498db", "analogous", 5)
print(vg.preview_palette(colors))

Output:

Demo

apply_palette_theme(palette, register_styles=True)

Apply a generated palette as the active theme.

Parameters:

  • palette (dict): Dictionary from generate_theme_palette()

  • register_styles (bool): Register each color as custom style (default: True)

Example:

theme = vg.generate_theme_palette("analogous", "#e74c3c")
vg.apply_palette_theme(theme)

print(vg.format("<primary>Primary</primary>"))
print(vg.format("<success>Success</success>"))
print(vg.format("<error>Error</error>"))

Demo

Color Manipulation

lighten(color, amount=0.1)

Increase brightness of a color.

Parameters:

  • color (str): Hex color

  • amount (float): Brightness increase (0-1)

Returns: Hex color string

Example:

lighter = vg.lighten("#3498db", 0.2)  # '#3cb0ff'

darken(color, amount=0.1)

Decrease brightness of a color.

Parameters:

  • color (str): Hex color

  • amount (float): Brightness decrease (0-1)

Returns: Hex color string

Example:

darker = vg.darken("#3498db", 0.2)  # '#2774a7'

saturate(color, amount=0.1)

Increase saturation of a color.

Parameters:

  • color (str): Hex color

  • amount (float): Saturation increase (0-1)

Returns: Hex color string

Example:

more_saturated = vg.saturate("#80a0c0", 0.3)  # '#5a9ad8'

desaturate(color, amount=0.1)

Decrease saturation of a color.

Parameters:

  • color (str): Hex color

  • amount (float): Saturation decrease (0-1)

Returns: Hex color string

Example:

less_saturated = vg.desaturate("#3498db", 0.3)  # '#4683c0'

shift_hue(color, degrees)

Rotate hue by specified degrees.

Parameters:

  • color (str): Hex color

  • degrees (float): Degrees to rotate (-360 to 360)

Returns: Hex color string

Example:

shifted = vg.shift_hue("#FF0000", 120)  # '#00ff00' (Red → Green)

invert(color)

Invert a color.

Parameters:

  • color (str): Hex color

Returns: Hex color string

Example:

inverted = vg.invert("#FF0000")  # '#00ffff' (Red → Cyan)

mix(color1, color2, weight=0.5)

Mix two colors together.

Parameters:

  • color1 (str): First hex color

  • color2 (str): Second hex color

  • weight (float): Weight of first color (0-1, default: 0.5)

Returns: Hex color string

Example:

mixed = vg.mix("#FF0000", "#0000FF", 0.5)  # '#7f007f' (Purple)
mixed = vg.mix("#FF0000", "#0000FF", 0.8)  # More red

Accessibility Functions

calculate_contrast_ratio(color1, color2)

Calculate WCAG 2.1 contrast ratio.

Parameters:

  • color1 (str): First hex color

  • color2 (str): Second hex color

Returns: float - Contrast ratio (1-21, 21 is max)

Example:

ratio = vg.calculate_contrast_ratio("#FFFFFF", "#000000")  # 21.0
ratio = vg.calculate_contrast_ratio("#3498db", "#1a1a1a")  # ~5.2

meets_wcag(color1, color2, level="AA", large_text=False)

Check if colors meet WCAG contrast requirements.

Parameters:

  • color1 (str): Foreground hex color

  • color2 (str): Background hex color

  • level (str): “AA” or “AAA”

  • large_text (bool): True if text is 18pt+ or 14pt+ bold

Returns: bool

WCAG Requirements:

  • AA Normal Text: 4.5:1 minimum

  • AA Large Text: 3:1 minimum

  • AAA Normal Text: 7:1 minimum

  • AAA Large Text: 4.5:1 minimum

Example:

if vg.meets_wcag("#FFFFFF", "#000000", "AAA"):
    print("Perfect contrast!")

if not vg.meets_wcag("#777777", "#888888", "AA"):
    print("Insufficient contrast for normal text")

ensure_contrast(foreground, background, min_ratio=4.5, max_iterations=20)

Adjust foreground color to meet minimum contrast.

Parameters:

  • foreground (str): Foreground hex color to adjust

  • background (str): Background hex color

  • min_ratio (float): Minimum contrast ratio (default: 4.5)

  • max_iterations (int): Max adjustment attempts (default: 20)

Returns: Adjusted hex color

Example:

# Ensure text is readable on gray background
adjusted = vg.ensure_contrast("#888888", "#999999", min_ratio=4.5)
# Returns darkened/lightened color that meets contrast requirement

Color Blindness Functions

simulate_colorblindness(hex_color, cb_type)

Simulate how a color appears to colorblind individuals.

Parameters:

  • hex_color (str): Input hex color

  • cb_type (str): Type of color blindness

Types:

  • "protanopia" - Red-blind (no red cones)

  • "deuteranopia" - Green-blind (no green cones)

  • "tritanopia" - Blue-blind (no blue cones)

  • "protanomaly" - Red-weak (defective red cones)

  • "deuteranomaly" - Green-weak (defective green cones)

  • "tritanomaly" - Blue-weak (defective blue cones)

Returns: Hex color as seen by colorblind person

Example:

# How red appears to someone with deuteranopia
simulated = vg.simulate_colorblindness("#FF0000", "deuteranopia")
# '#b89000' (brownish-yellow)

# Test all your colors
for color in palette:
    sim = vg.simulate_colorblindness(color, "deuteranopia")
    print(f"{color}{sim}")

validate_colorblind_safety(colors, cb_type="deuteranopia", min_difference=30)

Check if palette colors are distinguishable.

Parameters:

  • colors (list): List of hex colors

  • cb_type (str): Color blindness type

  • min_difference (float): Min perceptual difference (default: 30)

Returns: Tuple of (is_safe: bool, problems: list of (index, index) tuples)

Example:

colors = ["#FF0000", "#00FF00", "#0000FF"]
is_safe, problems = vg.validate_colorblind_safety(colors, "deuteranopia")

if not is_safe:
    for i, j in problems:
        print(f"Colors {i} and {j} are too similar: {colors[i]} vs {colors[j]}")

Persistence Functions

save_palette(colors, filename, metadata=None)

Save color palette to JSON file.

Parameters:

  • colors (list): List of hex colors

  • filename (str): Output file path

  • metadata (dict): Optional metadata

Example:

palette = vg.generate_palette("#3498db", "complementary", 5)
vg.save_palette(
    palette,
    "my_theme.json",
    metadata={"name": "Ocean Blue", "scheme": "complementary"}
)

load_palette(filename)

Load color palette from JSON file.

Parameters:

  • filename (str): Input file path

Returns: Tuple of (colors: list, metadata: dict)

Example:

colors, metadata = vg.load_palette("my_theme.json")
print(f"Loaded: {metadata['name']}")
print(vg.preview_palette(colors))

save_theme(theme, filename, metadata=None)

Save theme palette to JSON file.

Parameters:

  • theme (dict): Theme from generate_theme_palette()

  • filename (str): Output file path

  • metadata (dict): Optional metadata

Example:

theme = vg.generate_theme_palette("triadic", "#9b59b6")
vg.save_theme(
    theme,
    "purple_theme.json",
    metadata={"name": "Purple Rain", "author": "Me"}
)

load_theme(filename)

Load theme palette from JSON file.

Parameters:

  • filename (str): Input file path

Returns: Tuple of (theme: dict, metadata: dict)

Example:

theme, metadata = vg.load_theme("purple_theme.json")
vg.apply_palette_theme(theme)
print(vg.format("<primary>Using loaded theme!</primary>"))