Skip to content

FlossWare/curses-themes

Repository files navigation

curses-themes

Lightweight theme support for Python curses applications

License: MIT Python 3.9+ codecov Code Quality

Inspired by FlossWare curses-java, this library brings professional theme support to Python's standard curses module with zero external dependencies.

Features

  • 🎨 10 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

Quick Start

#!/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)  # REQUIRED before using colors
    
    # Semantic colors - general-purpose coloring by intent
    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))
    
    # Component colors - UI widget styling
    stdscr.addstr(3, 0, "[ Save ]", curses.color_pair(theme.components.button))
    
    # Draw themed boxes
    theme.draw_box(stdscr, 5, 2, 10, 40, title="My Panel")
    
    stdscr.refresh()
    stdscr.getch()

if __name__ == "__main__":
    curses.wrapper(main)

Important: You must call theme.apply(stdscr) before accessing theme.colors or theme.components, or a RuntimeError is raised. Color attributes return integers that must be wrapped with curses.color_pair() when used with curses display functions. See the API Documentation for details.

Installation

pip install curses-themes

Or install from source:

git clone https://github.com/FlossWare/curses-themes.git
cd curses-themes
pip install -e .

Windows

Python on Windows doesn't include the curses module. Install with Windows support:

pip install curses-themes[windows]

Or install windows-curses separately:

pip install windows-curses

Use Windows Terminal for best color support.

Theme Gallery

Modern Themes

Default Theme - Classic white-on-black terminal aesthetic
Default
Classic terminal aesthetic
Timeless
Dark Theme - Muted colors on dark background, modern dark mode
Dark
Professional dark mode
Modern
Light Theme - Bright background with dark text, high contrast
Light
High contrast for bright environments
Modern

Retro Computer Themes

TI-99/4A Theme - Cyan-on-blue Texas Instruments home computer look
TI-99/4A
Texas Instruments home computer
1981-1984
TRS-80 Theme - White-on-black Tandy/Radio Shack monochrome display
TRS-80
Tandy/Radio Shack monochrome
1980-1983

Business Software Themes

DOS Theme - Classic MS-DOS white-on-black text mode interface
DOS
Classic MS-DOS interface
1981-1995
dBASE III Theme - Cyan menus on black, Ashton-Tate database look
dBASE III
Iconic database software
1984-1985
dBASE IV Theme - Blue background windowed database interface
dBASE IV
Windowed database interface
1988-1993

3D Effect Themes

Borland 3D Theme - Turbo Vision beveled buttons and drop shadows
Borland 3D
Turbo Vision 3D look
1990-1997
dBASE IV 3D Theme - Blue windowed database UI with 3D depth effects
dBASE IV 3D
3D windowed database UI
1988-1993

Theme Comparison

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

Creating Custom Themes

from curses_themes import Theme, ThemeManager

class SolarizedTheme(Theme):
    """Solarized Dark theme using declarative class attributes."""
    color_map = {
        '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),
    }
    component_colors = {
        'background': ((131, 148, 150), (0, 43, 54)),
        'button': ((38, 139, 210), (0, 43, 54)),
        'button_focused': ((0, 43, 54), (38, 139, 210)),
        'border': ((131, 148, 150), (0, 43, 54)),
    }
    border_chars = "┌─┐││└─┘"

    def __init__(self):
        super().__init__(
            name="Solarized Dark",
            description="Precision colors for machines and people",
            author="Ethan Schoonover",
        )

ThemeManager.register(SolarizedTheme)
theme = ThemeManager.load('solarized-dark')

Or create a theme without subclassing:

theme = ThemeManager.create(
    "Quick Theme",
    color_map={
        'background': (0, 0, 0), 'foreground': (255, 255, 255),
        'primary': (0, 120, 215), 'success': (16, 124, 16),
        'error': (232, 17, 35), 'warning': (193, 156, 0),
        'info': (0, 120, 212), 'accent': (142, 68, 173),
    },
)

Runtime Theme Switching

import curses
from curses_themes import ThemeManager

def main(stdscr):
    themes = ['default', 'dark', 'light', 'borland-3d', 'dbase-iii']
    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)

API Reference

ThemeManager

  • ThemeManager.load(name) - Load theme by name
  • ThemeManager.register(theme_class, name=None) - Register custom theme
  • ThemeManager.list_themes() - List available themes

Theme

  • theme.apply(stdscr) - Apply theme to screen (must call before using colors)
  • theme.draw_box(stdscr, y, x, height, width, title="") - Draw themed box

Semantic Colors (theme.colors.*)

General-purpose coloring by intent:

  • theme.colors.primary - Main UI highlights
  • theme.colors.success - Positive feedback
  • theme.colors.error - Error messages
  • theme.colors.warning - Caution messages
  • theme.colors.info - Informational messages
  • theme.colors.accent - Secondary highlights
  • theme.colors.background - Default background
  • theme.colors.foreground - Default text

Component Colors (theme.components.*)

UI widget styling:

  • theme.components.background - Default background
  • theme.components.button - Normal button
  • theme.components.button_focused - Focused button
  • theme.components.text_input - Input fields
  • theme.components.border - Borders and frames
  • theme.components.selection - Selected items
  • theme.components.disabled - Disabled elements

Examples

See the examples/ directory for complete demonstrations:

  • basic_usage.py - Simple theme demonstration
  • theme_switcher.py - Interactive theme switching
  • custom_theme.py - Creating custom themes
  • config_theme_demo.py - Loading themes from config files

Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines.

Adding New Themes

  1. Create theme class in curses_themes/themes/your_theme.py
  2. Define color_map and component_colors class attributes
  3. Optionally set border_chars (8-character string: TL, T, TR, L, R, BL, B, BR)
  4. Add tests in tests/test_themes/test_your_theme.py
  5. Submit pull request

Related Projects

  • curses-java - Java terminal UI library with themes (inspiration for this project)
  • Textual - Modern Python TUI framework
  • Rich - Rich terminal output library

License

MIT - See LICENSE file for details.

Author

FlossWare - https://github.com/FlossWare

Inspired by the excellent curses-java library.

About

Lightweight theme support for Python curses applications

Topics

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages