This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 1.0.1 instead.
Reason given by maintainers: Contained placeholder author info, use 1.0.1
codehs-utils
A Python library for terminal colors, gradients, banners, drawing, and keyboard/mouse input, originally built for CodeHS's Python environment.
Features
- RGB and named colors for foreground and background, plus mixing/lighten/darken
- Gradient text with built-in presets (rainbow, fire, ocean, sunset, and more)
- Composable text banners and boxes, alignable and laid out side by side
- Rectangles with fill and border drawing
- A half-block pixel canvas for square-pixel graphics
- Keyboard and mouse input, including click-and-drag mouse events
- Cursor and screen control (alternate screen, hide/show cursor, clear, resize-aware sizing)
- Clickable buttons with hover/press states
Installation
pip install codehs-utils
Quick Start
import codehs_utils as c
# Colorful banner
print(c.banner("Hello, World!", color="white", background="blue"))
# Interactive app with mouse support
with c.app(mouse=True):
c.banner("Click anywhere, press ESC to quit").draw(1, 1)
for event in c.events(timeout=5):
if event is None or (event.kind == "key" and event.key == "ESC"):
break
Documentation
Color Functions
from codehs_utils import ColorLike, ColorText, GradientText
# Using named colors, hex, or RGB tuples
red = ColorLike("red")
also_red = ColorLike("#ff0000")
also_red_too = ColorLike((255, 0, 0))
print(ColorText("Red text", foreground=red))
# Mixing and adjusting colors
lighter = red.lighten(0.3)
darker = red.darken(0.3)
contrast = red.contrast() # black or white, whichever reads better
# Background colors
print(ColorText("Green background", background="green"))
Gradient Text
from codehs_utils import GradientText
# Built-in preset, as a shortcut method...
print(GradientText.rainbow("This text has rainbow colors!"))
# ...or via from_preset(), which every shortcut method calls internally
print(GradientText.from_preset("Same thing", preset="rainbow"))
# Custom stops
print(GradientText("Custom gradient", colors=["red", "orange", "yellow"]))
# Background gradient
print(GradientText("Rainbow background!", background_colors="rainbow"))
Mixing two colors together (used internally by .lighten()/.darken(), also usable directly):
from codehs_utils import ColorLike
blend = ColorLike("red").mix("blue", t=0.5) # 50/50 blend
print(blend.to_hex())
Style Methods
ColorText and GradientText share a set of chainable style methods (from their common _StyleMixin), so you can build up a piece of styled text step by step instead of passing everything to the constructor at once:
from codehs_utils import ColorText
msg = ColorText("warning!").bold().underline()
msg.set_background("red")
print(msg)
Available chainable methods:
.bold(),.italic(),.underline(),.strikethrough(),.dim(),.blink(),.reverse()— turn on a single style.add_style(name)/.remove_style(name)— turn a named style on/off.set_styles(*names)— replace the whole style list at once.set_text(text)— change the wrapped text.set_background(color)— set or clear the background color.set_reset(bool)— whether an ANSI reset code is appended after the text (defaultTrue)
Every method returns self, so calls can be chained.
StyledText concatenates several ColorText/GradientText/plain-string pieces into one object, and can be wrapped or aligned as a whole:
from codehs_utils import ColorText, GradientText, StyledText
line = StyledText([ColorText("Error: ", "red"), GradientText.fire("something broke")])
print(line)
print(line.align(40, "center"))
print(line.wrap(20))
Cursor & Screen Control
from codehs_utils import (
clear_screen, clear_line, set_cursor_pos, set_cursor_row, set_cursor_col,
move_cursor, save_cursor_position, restore_cursor_position,
hide_cursor, show_cursor, get_cursor_position, get_terminal_size,
enter_alt_screen, leave_alt_screen, restore_terminal,
)
# Clear the screen, or just the current line
clear_screen()
clear_line(mode="to_end") # "full", "to_end", or "to_start"
# Move the cursor
set_cursor_pos(10, 5) # absolute: row 10, column 5
set_cursor_row(10)
set_cursor_col(5)
move_cursor(dx=2, dy=-1) # relative
# Save/restore cursor position
save_cursor_position()
restore_cursor_position()
# Hide/show the cursor
hide_cursor()
show_cursor()
# Read back state
row, col = get_cursor_position()
width, height = get_terminal_size()
# The alternate screen buffer (used internally by app())
enter_alt_screen()
leave_alt_screen()
# Manually undo everything (hide_cursor, alt screen, mouse tracking, raw
# mode) in one call — normally you'd just use app() instead
restore_terminal()
Lower-level output helpers, used internally but available directly:
from codehs_utils import write, frame
write("some text") # like print(), but no trailing newline and no `sep`
# Batch several writes into one flush, avoiding flicker/tearing
with frame():
write("line one\n")
write("line two\n")
Text Formatting
from codehs_utils import align_text, wrap_text
# Text alignment
text = "Hello World"
print(align_text(text, 20, "center")) # Center align in 20 characters
print(align_text(text, 20, "right")) # Right align
print(align_text(text, 20, "left")) # Left align
# Word wrapping (ANSI-aware, so styled text still wraps correctly)
print(wrap_text("A long line of text that needs wrapping", width=15))
Banners & Boxes
from codehs_utils import banner, Banner, BannerRow
# A styled box of text
b = banner("Important Message", color="black", background="lightyellow")
print(b)
# Draw it at a specific position in an app()
b.draw(row=1, col=1)
# Lay banners out side by side
row = BannerRow([banner("One"), banner("Two"), banner("Three")])
print(row)
# Adjust spacing and vertical alignment between banners
row.set_gap(3).set_valign("middle")
# Align a whole banner (or row) within a wider field
print(b.align(width=40, align="right"))
Rectangles & Pixels
from codehs_utils import Rect, fill_rect, set_pixel, get_pixel_size
# Fill a rectangle
rect = fill_rect(row=1, col=1, width=10, height=3, color="blue")
# Draw a border around a Rect
rect.draw_border(color="cyan", style="double")
# Half-block pixel canvas
width, height = get_pixel_size()
set_pixel(x=5, y=5, color="red")
Keyboard & Mouse Input
from codehs_utils import get_key, get_keys, get_mouse_event, events, app, KeyEvent, MouseEvent
with app(mouse=True):
for event in events(timeout=None):
if isinstance(event, KeyEvent):
print("Key pressed:", event.key)
elif isinstance(event, MouseEvent):
print("Mouse:", event.type, event.button, event.x, event.y)
# Blocking single-key read (outside an app(), still uses raw/cbreak mode)
key = get_key(timeout=5)
# Drain every key pressed so far without blocking
keys = get_keys()
# Just the next mouse event
mouse_event = get_mouse_event(timeout=1)
Mouse tracking can also be toggled manually, if you're not using app():
from codehs_utils import enable_mouse_tracking, disable_mouse_tracking
enable_mouse_tracking()
disable_mouse_tracking()
Advanced Usage
Custom Colors and Gradients
from codehs_utils import ColorLike, GradientText
# Create ColorLike objects directly
purple = ColorLike((128, 64, 192))
print(purple.to_hex())
# List and preview all built-in gradient presets
print(GradientText.list_presets())
GradientText.preview_presets()
Clickable Buttons
from codehs_utils import Button, app, events
with app(mouse=True):
button = Button("Click me", row=2, col=2, on_click=lambda: print("Clicked!"))
button.draw()
for event in events(timeout=10):
if event is None:
break
# handle() updates hover/pressed state, redraws if it changed, fires
# on_click when appropriate, and returns True exactly on that click
button.handle(event)
The app() Context Manager
from codehs_utils import app
with app(mouse=True, cursor=False, clear=True, alt_screen=True):
... # Terminal state is restored automatically on exit, even on Ctrl+C
Reference
Text Styles
Passed as styles=[...] to ColorText/GradientText, or via .bold(), .italic(), etc:
bolddimitalicunderlineblinkreversestrikethrough
Border Styles
Passed as style= to Rect.draw_border():
single—┌─┐ └─┘double—╔═╗ ╚═╝rounded—╭─╮ ╰─╯heavy—┏━┓ ┗━┛ascii—+-+ +-+
Gradient Presets
Built into GradientText, usable by name (e.g. GradientText.rainbow(...)):
rainbow,fire,ocean,sunset,pastel,grayscale,neon,forest,mint,gold
API Reference
Every public name is re-exported from the top level (import codehs_utils as c), so the module path below is just for grouping — you don't need to import from it directly.
Colors — colors
| Name | Description |
|---|---|
ColorLike(color) |
Parses a name, "#hex", or (r, g, b) tuple into a normalized color |
ColorLike.rgb |
The parsed (r, g, b) tuple, or None |
ColorLike.to_hex() |
Returns "#rrggbb" |
ColorLike.luminance() |
Perceived brightness, 0.0–1.0 |
ColorLike.contrast() |
Black or white, whichever reads better on this color |
ColorLike.mix(other, t=0.5) |
Blends toward another color by ratio t |
ColorLike.lighten(amount=0.2) / .darken(amount=0.2) |
Mixes toward white / black |
ColorLike.print_samples() |
Prints every named color as a labeled banner |
ColorText(text, foreground=, background=, styles=, reset=) |
A single piece of solid-colored/styled text |
GradientText(text, colors=, color=, background=, background_colors=, styles=, reset=) |
Text with a foreground and/or background gradient |
GradientText.from_preset(text, preset="rainbow", **kwargs) |
Build from a named preset |
GradientText.rainbow(...), .fire(...), .ocean(...), .sunset(...), .pastel(...), .grayscale(...), .neon(...), .forest(...), .mint(...), .gold(...) |
Shortcut constructors, one per built-in preset |
GradientText.list_presets() |
List of built-in preset names |
GradientText.preview_presets(sample_text=, print_output=True) |
Prints (and returns) a sample of every preset |
StyledText(parts=None) |
Concatenates strings/ColorText/GradientText into one object |
ColorSpec, GradientColors |
Type aliases used in the signatures above (not runtime objects) |
Shared style methods (on ColorText and GradientText, via _StyleMixin):
| Name | Description |
|---|---|
.bold() .dim() .italic() .underline() .blink() .reverse() .strikethrough() |
Turn on one style |
.add_style(name) / .remove_style(name) |
Turn a named style on/off |
.set_styles(*names) |
Replace the whole style list |
.set_text(text) |
Change the wrapped text |
.set_background(color) |
Set or clear the background color |
.set_reset(bool) |
Whether a trailing ANSI reset code is appended |
.set_color(color) (ColorText only) |
Set or clear the foreground color |
.set_colors(colors) / .set_background_gradient(colors) (GradientText only) |
Set the foreground / background gradient stops |
StyledText methods:
| Name | Description |
|---|---|
.wrap(width, collapse_space=True) |
ANSI-aware word wrap of the combined text |
.align(width, align="left", fillchar=" ") |
Align the combined text within width |
Text — text
| Name | Description |
|---|---|
wrap_text(text, width, collapse_space=True, break_long_words=True, preserve_newlines=True) |
ANSI-aware word wrapping |
align_text(text, width, align="left", fillchar=" ") |
"left", "right", "center", or "justify" alignment |
Geometry — geometry
| Name | Description |
|---|---|
Rect(row, col, width, height) |
A rectangle; also returned by most drawing functions |
Rect.top .left .bottom .right |
Edge coordinates |
Rect.contains(x, y) |
Whether a point falls inside the rect |
Rect.fill(color=None, char=" ") |
Fill the rect (wraps fill_rect) |
Rect.draw_border(color=None, style="single", background=None) |
Draw a border around the rect |
Drawing — drawing
| Name | Description |
|---|---|
Banner(lines) |
A block of text padded to a uniform width |
Banner.height |
Number of lines |
Banner.draw(row, col) |
Draw at a position, returns the Rect drawn |
Banner.align(width, align="left", fillchar=" ") |
Align the banner within a wider field |
BannerRow(banners, gap=1, valign="top") |
Lay several banners out side by side |
BannerRow.width .height |
Combined dimensions |
BannerRow.set_gap(gap) / .set_valign(valign) |
Adjust spacing / vertical alignment |
BannerRow.draw(row, col) / .align(width, align=, fillchar=) |
Same as on Banner |
banner(text, width=None, color=, colors=, background=, background_colors=, styles=, padding=1, align="center") |
Build a styled Banner in one call |
fill_rect(row, col, width, height, color=None, char=" ", foreground=None) |
Fill a rectangle directly, returns a Rect |
get_pixel_size() |
Terminal size in half-block pixels ((width, height * 2)) |
set_pixel(x, y, color) / clear_pixel(x, y) / clear_pixels() |
Half-block pixel canvas |
Button(text, row, col, width=, background=, color=, hover_background=, hover_color=, pressed_background=, pressed_color=, padding=1, styles=, trigger="release", on_click=) |
A clickable button |
Button.draw() |
(Re)draw the button in its current state |
Button.handle(event) |
Update state from a MouseEvent, redraw if needed, fire on_click; returns True on a completed click |
Terminal — terminal
| Name | Description |
|---|---|
app(mouse=False, cursor=False, clear=True, alt_screen=True, catch_interrupt=True) |
Context manager: sets up and tears down an interactive session |
MouseEvent |
.type, .button, .x, .y, .shift, .alt, .ctrl; .inside(rect) |
KeyEvent |
.key; compares equal to a plain string |
get_key(timeout=None) |
Block for a single keypress |
get_keys() / get_key_nonblocking() |
Drain all buffered keys without blocking |
get_mouse_event(timeout=None) / get_mouse_event_nonblocking() |
Get the next mouse event |
get_event(timeout=None) |
Get the next key or mouse event |
events(timeout=None) |
Infinite iterator over get_event() |
get_cursor_position() / gcp |
Query the cursor's current position (gcp is an alias) |
get_terminal_size() |
(width, height) in characters |
clear_screen(scrollback=True) / clear_line(mode="full") |
Clear the screen / current line |
set_cursor_pos(row, col) / set_cursor_row(row) / set_cursor_col(col) |
Absolute cursor positioning |
move_cursor(dx=0, dy=0) |
Relative cursor movement |
save_cursor_position() / restore_cursor_position() |
Push/pop cursor position |
hide_cursor() / show_cursor() |
Toggle cursor visibility |
enter_alt_screen() / leave_alt_screen() |
Toggle the alternate screen buffer |
enable_mouse_tracking() / disable_mouse_tracking() |
Toggle mouse event reporting |
print_at(row, col, text, clear_to_end=False) |
Print (possibly multi-line) text at a position, returns a Rect |
restore_terminal() |
Undo cursor/mouse/alt-screen/raw-mode state in one call |
Output buffering — _buffer (re-exported)
| Name | Description |
|---|---|
write(*parts, sep="", flush=True) |
Like print(), but no newline and writes go through the frame buffer |
frame(sync=False) |
Context manager: batch writes into a single flush |
Requirements
- Python 3.8+
- No third-party dependencies
Examples
Create a Colorful Banner
from codehs_utils import banner, clear_screen, GradientText
clear_screen()
print(banner("WELCOME", color="black", background="lightgreen"))
print()
print(GradientText.rainbow("- Terminal Toolkit Demo -"))
print(GradientText.rainbow("=" * 50))
Simple Paint Program
from codehs_utils import app, events, set_pixel
with app(mouse=True):
for event in events(timeout=None):
if event is None or (event.kind == "key" and event.key == "ESC"):
break
if event.kind == "mouse" and event.button == "left":
set_pixel(event.x, event.y, "red")
Bordered Dialog Box
from codehs_utils import Rect, print_at
box = Rect(row=3, col=5, width=30, height=6)
box.fill(color="black")
box.draw_border(color="white", style="rounded")
print_at(box.row + 2, box.col + 2, "Press any key to continue...")
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Release files for codehs-utils 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| codehs_utils-1.0.0.tar.gz | 26.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| codehs_utils-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.5 kB
Release files / codehs_utils-1.0.0.tar.gz
| Download URL | codehs_utils-1.0.0.tar.gz |
|---|---|
| Size | 26.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
50d263e259cc2c31a38d06f044880a81165d6fe209cad065a09a3a3d2aae507f
|
|
BLAKE2b-256 checksum How to use checksums |
79ec43d264a6bdf42e235c409065e7d3a8e5fca3bd3ad8d959a7b626c26bf244
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / codehs_utils-1.0.0-py3-none-any.whl
| Download URL | codehs_utils-1.0.0-py3-none-any.whl |
|---|---|
| Size | 29.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d309f78a57d8a09362527e795670fbe9ad5ef8d572d5ba6ed52eb848e2e553c9
|
|
BLAKE2b-256 checksum How to use checksums |
fee759d5a84e923ed2c3f59b5caaf9c5d8731aa5a003f54a54994236d6b769bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|