ucharm

charm

Beautiful terminal output - boxes, tables, progress bars, and more

charm

The charm module provides high-level UI components for beautiful terminal output.

import charm
# or
from ucharm import box, table, success, error, warning, info

Status Messages

Display styled status messages with icons:

charm.success("Build completed!")    # ✓ Build completed!
charm.error("Build failed")          # ✗ Build failed
charm.warning("Deprecated API")      # ⚠ Deprecated API
charm.info("Starting server...")     # ℹ Starting server...

Boxes

Draw bordered boxes around content:

charm.box("Hello, World!", title="Greeting", border_color="cyan")

Output:

╭─ Greeting ────────╮
│ Hello, World!     │
╰───────────────────╯

Parameters

ParameterTypeDefaultDescription
contentstrrequiredText to display inside the box
titlestrNoneOptional title in the top border
borderstr"rounded"Border style: "rounded", "square", "double", "heavy", "none"
border_colorstrNoneBorder color (see colors below)
paddingint1Padding inside the box

Tables

Display formatted tables with optional headers:

charm.table([
    ["Name", "Age", "Role"],
    ["Alice", "28", "Engineer"],
    ["Bob", "34", "Designer"],
], headers=True)

Output:

┌───────┬─────┬──────────┐
│ Name  │ Age │ Role     │
├───────┼─────┼──────────┤
│ Alice │ 28  │ Engineer │
│ Bob   │ 34  │ Designer │
└───────┴─────┴──────────┘

Parameters

ParameterTypeDefaultDescription
rowslistrequiredList of rows, each row is a list of cell values
headersboolFalseIf True, first row is styled as header with separator
borderstr"square"Border style: "square", "rounded", "double", "heavy", "none"
border_colorstrNoneBorder color

Rules

Draw horizontal dividers:

charm.rule("Section Title", color="cyan")

Output:

──────────────── Section Title ────────────────

Parameters

ParameterTypeDefaultDescription
titlestrNoneOptional centered title
charstr"─"Character to use for the rule
colorstrNoneColor for the rule
widthint80Total width of the rule

Progress Bars

Display progress with optional elapsed time:

import time

start = time.time()
for i in range(101):
    elapsed = time.time() - start
    charm.progress(i, 100, label="Downloading", width=30, elapsed=elapsed)
    time.sleep(0.05)
charm.progress_done()

Output:

Downloading ████████████████░░░░░░░░░░░░░░ 53%  2.6s

Parameters

ParameterTypeDefaultDescription
currentintrequiredCurrent progress value
totalintrequiredTotal value (100%)
labelstrNoneLabel before the progress bar
widthint40Width of the progress bar
colorstrNoneColor for the filled portion
elapsedfloatNoneElapsed time in seconds to display

Spinners

Display animated spinners for indeterminate progress:

import time

for i in range(30):
    charm.spinner(i, "Loading data...", color="cyan")
    time.sleep(0.1)
charm.progress_done()
charm.success("Done!")

Parameters

ParameterTypeDefaultDescription
frameintrequiredFrame index (cycles through 10 frames)
messagestrNoneMessage to display after spinner
colorstrNoneColor for the spinner

Text Styling

Apply ANSI styles to text:

styled = charm.style("Important!", fg="red", bold=True)
print(styled)

Parameters

ParameterTypeDefaultDescription
textstrrequiredText to style
fgstrNoneForeground color
bgstrNoneBackground color
boldboolFalseBold text
dimboolFalseDim/faint text
italicboolFalseItalic text
underlineboolFalseUnderlined text
strikethroughboolFalseStrikethrough text

Colors

Available color names:

  • Basic: black, red, green, yellow, blue, magenta, cyan, white, gray/grey
  • Hex: #ff5500, #abc
  • RGB values via ansi.rgb(r, g, b)

Utility Functions

visible_len

Get the visible length of text (excluding ANSI escape codes):

styled = charm.style("Hello", fg="red", bold=True)
print(len(styled))              # 19 (includes escape codes)
print(charm.visible_len(styled)) # 5 (visible characters only)

spinner_frame

Get a single spinner frame character:

frame = charm.spinner_frame(0)  # Returns "⠋"

On this page