Cursers
A minimal threaded wrapper for Python curses that simplifies terminal user interface development with built-in threading support and lifecycle management.
Features
- Simple context manager for curses applications
- Built-in update loop with configurable FPS
- Lifecycle hooks for application logic
- Threaded version for running updates in separate thread
- Text drawing utilities with styling support
Installation
pip install cursers
Quick Start
Basic App
import cursers
class MyApp(cursers.App):
# Called when entering the application context
def on_enter(self):
self.draw_text(0, 0, "Hello, World!", bold=True)
# Called each frame with the current key input
def on_update(self, key):
if key == 27: # ESC key
self.exit()
# Run the application
with MyApp() as app:
while app.is_running():
app.update()
Threaded App
import cursers
import time
class MyThreadedApp(cursers.ThreadedApp):
def on_enter(self):
self.draw_text(0, 0, "Running in background thread!")
def on_update(self, key):
if key == 27: # ESC key
self.exit()
# Run in background thread
with MyThreadedApp() as app:
while app.is_running():
time.sleep(0.1) # Do other work
API Reference
App Class
The main application class that provides a context manager for curses applications.
Constructor
App(fps=30)
fps: Target frames per second (default: 30)
Methods
is_running(): ReturnsTrueif the application is runningupdate(): Updates the application state and handles input (call in main loop)exit(): Signals the application to exitdraw_text(y, x, text, bold=False, underline=False): Draw text at position
Lifecycle Hooks
Override these methods in your subclass:
on_enter(): Called when entering the contexton_update(key): Called every frame with key input (-1 if no key pressed)on_exit(): Called when exiting the context
ThreadedApp Class
Extends App to run the update loop in a separate thread.
class MyThreadedApp(cursers.ThreadedApp):
def on_update(self, key):
# Handle input and drawing
pass
with MyThreadedApp() as app:
# Update loop runs automatically in background thread
while app.is_running():
# Main thread is free for other tasks
time.sleep(0.1)
Thread Class
Basic threading context manager for custom threading needs.
class MyThread(cursers.Thread):
def run(self):
# Your thread code here
pass
with MyThread() as thread:
# Thread runs automatically
pass
Examples
Check out the examples/ directory for complete working examples:
examples/move_control.py- Basic movement control with keyboard inputexamples/move_control_gravity.py- Threaded application with gravity simulation
Development
Setup
# Clone the repository
git clone https://github.com/threeal/cursers.git
cd cursers
# Install development dependencies
uv sync
# Install Git hooks
uv run lefthook install
Code Quality
# Format code
dprint fmt
# Run linter
uv run ruff check --fix
License
This project is licensed under the terms of the MIT License.
Copyright © 2025 Alfi Maulana
Metadata
Release files for cursers 0.1.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 | |
|---|---|---|---|
| cursers-0.1.0.tar.gz | 4.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cursers-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 9.4 kB
Release files / cursers-0.1.0.tar.gz
| Download URL | cursers-0.1.0.tar.gz |
|---|---|
| Size | 4.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6682c9c8c38b0a45f8f2a3a624cd63e7dce71a08cfa36b4bceae6c8b76dd0294
|
|
BLAKE2b-256 checksum How to use checksums |
fba0ec548c5308ae43c39460005e90f104ab262a05d0a22a57c36be6dc143bb8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.13
|
Release files / cursers-0.1.0-py3-none-any.whl
| Download URL | cursers-0.1.0-py3-none-any.whl |
|---|---|
| Size | 5.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f0a14236891664b3c42ac5fd1e825cc457e10f13baaced59acb73e04d4e01502
|
|
BLAKE2b-256 checksum How to use checksums |
6b9792cd79c4391f0a19e89a7c66a0de004fc5e7963e77e5851b335a8322a619
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.13
|