Lightweight theme support for Python curses applications
Inspired by FlossWare curses-java, this library brings professional theme support to Python's standard curses module with zero external dependencies.
- 🎨 8 Built-in Themes: Modern, classic IDE, and retro computer themes
- 🔌 Pluggable Architecture: Easy custom theme creation
- 🎯 Semantic Colors:
primary,success,error,warning,info - 🔄 Runtime Theme Switching: Change themes on-the-fly
- 🖥️ Terminal Aware: Auto-detects 8/16/256 color support with fallbacks
- 📦 Zero Dependencies: Only uses Python standard library
curses - 🧪 Thoroughly Tested: Comprehensive test coverage
- 📚 Well Documented: API reference, examples, and guides
#!/usr/bin/env python3
import curses
from curses_themes import ThemeManager
def main(stdscr):
# Load and apply a theme
theme = ThemeManager.load('dark')
theme.apply(stdscr)
# Use semantic colors
stdscr.addstr(0, 0, "Success!", curses.color_pair(theme.colors.success))
stdscr.addstr(1, 0, "Error!", curses.color_pair(theme.colors.error))
stdscr.addstr(2, 0, "Warning!", curses.color_pair(theme.colors.warning))
# Draw themed boxes
theme.draw_box(stdscr, 4, 2, 10, 40, title="My Panel")
stdscr.refresh()
stdscr.getch()
if __name__ == "__main__":
curses.wrapper(main)pip install curses-themesOr install from source:
git clone https://github.com/FlossWare/curses-themes.git
cd curses-themes
pip install -e .
![]() Default Classic terminal aesthetic Timeless |
![]() Dark Professional dark mode Modern |
![]() Light High contrast for bright environments Modern |
![]() TI-99/4A Texas Instruments home computer 1981-1984 |
![]() TRS-80 Tandy/Radio Shack monochrome 1980-1983 |
![]() DOS Classic MS-DOS interface 1981-1995 |
![]() dBASE III Iconic database software 1984-1985 |
![]() dBASE IV Windowed database interface 1988-1993 |
![]() Borland 3D Turbo Vision 3D look 1990-1997 |
![]() dBASE IV 3D 3D windowed database UI 1988-1993 |
| Theme | Era | Style | Colors | Best For |
|---|---|---|---|---|
| Default | Timeless | Minimal | B/W | Universal compatibility |
| Dark | Modern | Professional | Blues/Greens | Low-light coding |
| Light | Modern | Clean | High contrast | Bright environments |
| TI-99/4A | 1981-1984 | Retro | Cyan/Blue | Nostalgia, gaming UIs |
| TRS-80 | 1980-1983 | Monochrome | White/Black | Authentic retro feel |
| DOS | 1981-1995 | Classic | White/Yellow | System utilities |
| dBASE III | 1984-1985 | Business | Cyan menus | Database applications |
| dBASE IV | 1988-1993 | Windowed | Blue background | Modern database UIs |
| Borland 3D | 1990-1997 | 3D Effect | Gray/Blue shadows | IDE-style applications |
| dBASE IV 3D | 1988-1993 | 3D Windowed | Blue with depth | Sophisticated database UIs |
from curses_themes import Theme, ThemeManager
class SolarizedTheme(Theme):
"""Solarized Dark theme"""
def __init__(self):
super().__init__(
name="Solarized Dark",
description="Precision colors for machines and people",
author="Ethan Schoonover"
)
def get_color_map(self):
return {
'background': (0, 43, 54),
'foreground': (131, 148, 150),
'primary': (38, 139, 210),
'success': (133, 153, 0),
'error': (220, 50, 47),
'warning': (181, 137, 0),
'info': (42, 161, 152),
'accent': (211, 54, 130),
}
# Register and use
ThemeManager.register(SolarizedTheme)
theme = ThemeManager.load('solarized-dark')import curses
from curses_themes import ThemeManager
def main(stdscr):
themes = ['default', 'dark', 'light', 'borland3d', 'dbase3']
current = 0
while True:
theme = ThemeManager.load(themes[current])
theme.apply(stdscr)
stdscr.clear()
stdscr.addstr(0, 0, f"Theme: {themes[current]}",
curses.color_pair(theme.colors.primary))
stdscr.addstr(2, 0, "Press 'n' for next, 'q' to quit")
key = stdscr.getch()
if key == ord('q'):
break
elif key == ord('n'):
current = (current + 1) % len(themes)
curses.wrapper(main)ThemeManager.load(name)- Load theme by nameThemeManager.register(theme_class, name=None)- Register custom themeThemeManager.list_themes()- List available themes
theme.apply(stdscr)- Apply theme to screentheme.colors.primary- Primary colortheme.colors.success- Success colortheme.colors.error- Error colortheme.colors.warning- Warning colortheme.colors.info- Info colortheme.colors.accent- Accent colortheme.draw_box(stdscr, y, x, height, width, title="")- Draw themed box
See the examples/ directory for complete demonstrations:
basic_usage.py- Simple theme demonstrationtheme_switcher.py- Interactive theme switchingdashboard.py- Full TUI dashboard with themescustom_theme.py- Creating custom themes
Contributions welcome! See CONTRIBUTING.md for guidelines.
- Create theme class in
curses_themes/themes/your_theme.py - Implement
get_color_map()method - Optionally override
get_border_chars() - Add tests in
tests/test_themes/test_your_theme.py - Submit pull request
- curses-java - Java terminal UI library with themes (inspiration for this project)
- Textual - Modern Python TUI framework
- Rich - Rich terminal output library
GPL-3.0 - See LICENSE file for details.
FlossWare - https://github.com/FlossWare
Inspired by the excellent curses-java library.









