Skip to content

About

Modern, high-performance terminal color styling for Python with intelligent auto-detection, readability contrast guards, and smooth multi-stop gradients. 🎨

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Latest commit

Β 

History

92 Commits

Folders and files

Repository files navigation

Rcolor Banner

🎨 Rcolor

High-Performance, Terminal-Aware Color & ANSI Styling Engine for Python

PyPI Python Platform License CI CodeQL Downloads


Random Foreground Colors Rainbow Text Output Backgrounds and Styles

Sample console outputs generated dynamically with Rcolor.


🌟 Introduction

Make your CLI applications look stunning with zero configuration.

Rcolor is an ultra-fast, zero-bloat Python library designed to bring colorful foregrounds, vibrant background highlights, terminal font styles, and per-character rainbow output to your terminal. Equipped with automatic terminal capability detection, Rcolor dynamically detects color depths (TrueColor > 256 colors > 16 colors > Plain Text) and automatically downsamples 256-color palettes to standard ANSI colors on restricted terminalsβ€”ensuring your terminal output looks flawless on Linux, macOS, and Windows.


πŸ—ΊοΈ Quick Navigation

πŸš€
Quick Start
Get started in seconds
✨
Key Features
What Rcolor can do
πŸ–₯️
Terminal Matrix
Cross-platform compatibility
🧬
Architecture
Color detection pipeline
⚑
Benchmarks
Up to 327x faster
πŸ“–
Usage Guide
Complete code examples
🎨
Custom Palettes
JSON schema & loading
πŸ“š
API Reference
Full function signature table
πŸ”
Troubleshooting
Fix common CLI issues
🀝
Contributing
Tests & development

πŸš€ Quick Start

Get colorful terminal output in 3 simple commands:

# 1. Install or upgrade Rcolor from PyPI
pip install -U Rcolor

# 2. Print an automatically optimized random colorful message
python -c "import Rcolor; print(Rcolor.auto_fg('✨ Hello Beautiful Terminal! ✨'))"

# 3. Print per-character rainbow output
python -c "import Rcolor; print(Rcolor.rainbow_fg('🌈 Dynamic Rainbow Console Output'))"

✨ Key Features

Feature Description Highlight
Lightning-Fast Execution Built on precomputed tuples with zero disk I/O at runtime and $O(N)$ string joins. ⚑ 1.8 ¡s per call (~327x faster)
Intelligent Terminal Detection Automatically inspects environment variables, TTY streams, and OS console APIs. 🧠 Auto TrueColor / 256 / 16 / None
Automatic Downgrading Maps 256-color escape codes to the nearest ANSI 16 color via Euclidean RGB distance. 🎯 Flawless legacy terminal fallback
Contrast Guard Dynamically enforces WCAG relative luminance contrast ratios ($\ge 4.0:1$) for dual styling. πŸ‘οΈ Guaranteed text readability
Curated Tone Presets Filter colors by cohesive aesthetic tones: neon, pastel, warm, and cool. 🎨 High-end palette curation
Smooth Linear Gradients Linear per-character color interpolation with multi-stop presets and TrueColor depth. 🌈 Seamless gradient banners
Universal Standards Compliance Respects NO_COLOR, FORCE_COLOR, CLICOLOR, and pipe redirections natively. πŸ›‘οΈ Clean CLI & CI logs
External JSON Palette Color definitions stored in Rcolor/data/colors.json, loaded lazily on first access. πŸ“¦ Clean architecture & lazy load
Custom Palette Support Load your own brand or project themes via Rcolor.load_palette(). 🎨 Full JSON schema flexibility
100% Backward Compatibility All original v3.0 public APIs remain functional with identical arguments and return types. πŸ”’ Zero breaking API changes
Fully Typed (PEP 561) Includes py.typed marker and comprehensive type hints for IDE autocompletion. πŸ’‘ Type checker friendly

πŸ–₯️ Terminal Compatibility Matrix

Rcolor automatically detects console capabilities and delivers optimal rendering:

Terminal / Platform TrueColor (24-bit) 256 Colors (8-bit) 16 Colors (4-bit) Notes
Windows Terminal βœ… Full βœ… Full βœ… Full Natively detected via WT_SESSION
PowerShell 7+ βœ… Full βœ… Full βœ… Full Native VT support on modern Windows builds
Legacy cmd.exe πŸ”„ Auto-Downgraded πŸ”„ Auto-Downgraded βœ… Full Uses colorama VT initialization when available
GNOME Terminal βœ… Full βœ… Full βœ… Full Detected via COLORTERM=truecolor
Konsole (KDE) βœ… Full βœ… Full βœ… Full Full 24-bit TrueColor rendering
iTerm2 (macOS) βœ… Full βœ… Full βœ… Full Detected via TERM_PROGRAM=iTerm.app
Terminal.app (macOS) πŸ”„ Auto-Downgraded βœ… Full βœ… Full Detected via TERM_PROGRAM=Apple_Terminal
tmux / screen βœ… Full βœ… Full βœ… Full Handles nested terminal session strings
VS Code Terminal βœ… Full βœ… Full βœ… Full Detected via TERM_PROGRAM=vscode
PyCharm / IntelliJ βœ… Full βœ… Full βœ… Full Detected via PYCHARM_HOSTED / TERMINAL_EMULATOR
Jupyter / IPython πŸ”„ Auto-Downgraded βœ… Full βœ… Full Native ANSI support in web notebook cells
CI Logs / Pipes (> file) 🚫 Disabled 🚫 Disabled 🚫 Disabled Output safely stripped to plain text
πŸ” How Automatic Capability Detection & Fallback Hierarchy Works

Rcolor inspects your execution context using the following deterministic hierarchy:

  1. Explicit Standards: NO_COLOR (always plain text) > FORCE_COLOR (0/1/2/3) > CLICOLOR_FORCE > CLICOLOR.
  2. Stream Target: sys.stdout.isatty() verifies output is attached to an interactive terminal rather than a log file or redirected pipe.
  3. IDE / Notebook Isolation: Detects Jupyter notebooks (ipykernel) and IDLE (idlelib).
  4. Multiplexers & SSH: Detects tmux, screen, and SSH_CONNECTION sessions.
  5. Windows VT Engine: Activates Windows Virtual Terminal Processing on Windows 10/11 or initializes colorama fallback.
  6. Nearest-Color Downgrade: If 256 colors are requested on an ANSI 16 console, colors are projected into standard 16 space via Euclidean RGB distance ($O(1)$ lookup table).

🧬 Detection & Downgrading Architecture

The ASCII diagram below illustrates how Rcolor determines color capabilities and renders output:

               +----------------------------------+
               |  User calls Rcolor function     |
               |  (e.g., auto_fg, foreground)    |
               +-----------------+----------------+
                                 |
                                 v
               +----------------------------------+
               | Check NO_COLOR or stdout != TTY  |
               +-----------------+----------------+
                                / \
                        YES    /   \   NO
               +--------------+     +-------------------+
               | Return plain |     | Check FORCE_COLOR |
               | text string  |     | or COLORTERM/TERM |
               +--------------+     +---------+---------+
                                              |
                   +--------------------------+--------------------------+
                   |                          |                          |
                   v                          v                          v
          [ TrueColor / 256 ]            [ 16-Color ]             [ Dumb / None ]
                   |                          |                          |
        +----------+----------+     +---------+----------+      +--------+---------+
        | Use 256-color code  |     | Map 256 color to   |      | Output plain     |
        | (\033[38;5;{id}m)   |     | nearest ANSI 16 via|      | string without   |
        |                     |     | RGB Euclidean dist |      | ANSI escapes     |
        +----------+----------+     +---------+----------+      +--------+---------+
                   |                          |                          |
                   +--------------------------+--------------------------+
                                              |
                                              v
                              +-------------------------------+
                              | Append clean '\033[0m' reset  |
                              +-------------------------------+

⚑ Benchmarks

Benchmarks measured on Python 3.14 comparing Rcolor v3.0.1 (legacy) vs Rcolor v3.1.0 (current):

Metric Legacy (v3.0.1) Optimized (v3.1.0) Speedup Factor
Import Time (fresh) 0.673 ms 1.601 ms Lazy zero-cost imports
foreground() call latency 250.91 Β΅s 1.85 Β΅s 135.7x faster πŸš€
rainbow_fg() (1,000 chars) 147.40 ms 0.45 ms 327.1x faster πŸš€

Note

Legacy v3.0.1 re-opened and parsed JSON files from the filesystem on every single function call. Rcolor v3.1.0 reads the data file lazily once, precomputes immutable escape tuples, and uses optimized $O(N)$ string joins.

To reproduce these measurements locally:

python benchmarks/bench.py
βš™οΈ Benchmark Reproduction & Methodology Details

All benchmarks use Python's built-in timeit module:

  • Import Time: Evaluates fresh module imports after removing Rcolor from sys.modules across 200 iterations.
  • Function Latency: Evaluates 10,000 iterations of Rcolor.foreground("Hello, World!").
  • Rainbow Throughput: Evaluates 200 iterations of Rcolor.rainbow_fg("A" * 1000) measuring per-character join performance.

πŸ“– Usage Guide

1. Basic Importing

import Rcolor

# Or import specific functions
from Rcolor import (
    foreground,
    background,
    style,
    rainbow_fg,
    standard_fg,
    standard_bg,
    standard_rainbow_fg,
    auto_fg,
    auto_bg,
    foreground_background,
    foreground_style,
    background_style,
    foreground_background_style,
)

2. Automatic Terminal-Aware Colors (auto_fg / auto_bg)

Recommended for general use. Chooses 256-color when available, standard 16-color on restricted consoles, and plain text in non-TTY environments:

import Rcolor

# Automatically styled foreground
print(Rcolor.auto_fg("This text adapts to your terminal capabilities!"))

# Automatically styled background
print(Rcolor.auto_bg("Highlighted text with automatic color selection!"))

3. Extended 256-Color Palette (foreground / background)

Applies a random color from the complete 256-color palette. If executed on a 16-color terminal, Rcolor automatically downsamples to the closest ANSI color:

# Random 256 foreground color
print(Rcolor.foreground("Vibrant 256-color foreground"))

# Random 256 background color
print(Rcolor.background("Vibrant 256-color background"))

4. Standard 16-Color Palette (standard_fg / standard_bg)

Guaranteed compatibility with all legacy ANSI terminals:

# Standard 16 ANSI foreground
print(Rcolor.standard_fg("Standard ANSI foreground color"))

# Standard 16 ANSI background
print(Rcolor.standard_bg("Standard ANSI background color"))

5. Font Styles (style)

Applies ANSI text attributes such as bold, dim, italic, and underline:

# Random text style
print(Rcolor.style("Bold, dim, italic, or underlined text!"))

6. Per-Character Rainbow Effects (rainbow_fg / standard_rainbow_fg)

Colorizes every character in the string individually:

# 256-color rainbow (with auto-downgrade)
print(Rcolor.rainbow_fg("Every single character has a unique random color!"))

# Standard 16-color rainbow
print(Rcolor.standard_rainbow_fg("Standard 16-color rainbow string!"))

7. Composite Styling & Readability Contrast Guard

Apply multiple ANSI attributes simultaneously. foreground_background automatically enforces a Contrast Guard based on WCAG 2.1 relative luminance, ensuring the foreground is always crisp and readable against the chosen background:

# Guaranteed readable foreground on background (min_contrast default is 4.0)
print(Rcolor.foreground_background("Always readable text!"))

# Customize contrast ratio (e.g. 7.0:1 for high contrast)
print(Rcolor.foreground_background("High contrast banner", min_contrast=7.0))

# Foreground + Font Style
print(Rcolor.foreground_style("Random foreground AND font style"))

# Background + Font Style
print(Rcolor.background_style("Random background AND font style"))

# Foreground + Background + Font Style with Contrast Guard
print(Rcolor.foreground_background_style("Full composite random styling!"))

8. Curated Tone Presets (neon, pastel, warm, cool)

Instead of pure white-noise randomness, style your console with cohesive aesthetic color themes:

# Vibrant electric neon tones
print(Rcolor.foreground("Neon cyan, lime, magenta & electric orange", tone="neon"))

# Soft, elegant pastel tones
print(Rcolor.foreground("Soft lavender, mint, pastel pink & baby blue", tone="pastel"))

# Warm sunset and amber tones
print(Rcolor.foreground("Rich red, orange, gold & amber tones", tone="warm"))

# Cool ocean and frost tones
print(Rcolor.foreground("Deep blue, cyan, teal & sapphire tones", tone="cool"))

# Tone presets work with auto_fg, auto_bg, and background too:
print(Rcolor.auto_fg("Automated neon theme", tone="neon"))
print(Rcolor.background("Pastel card background", tone="pastel"))

9. Smooth Linear Gradients & Multi-Stop Rainbow

Generate seamless character-by-character color transitions with TrueColor depth and automatic terminal fallback:

# 2-stop gradient from hex colors
print(Rcolor.gradient_fg("Smooth cyberpunk transition!", start="#ff007f", end="#00f0ff"))

# 2-stop gradient from RGB tuples
print(Rcolor.gradient_fg("Deep blue into lime green", start=(0, 0, 255), end=(0, 255, 0)))

# Built-in multi-stop presets: 'rainbow', 'neon', 'sunset', 'warm', 'cool', 'pastel', 'cyberpunk', 'ocean'
print(Rcolor.gradient_fg("Sunset horizon across characters", preset="sunset"))
print(Rcolor.gradient_fg("Electric cyberpunk aesthetic", preset="cyberpunk"))

# Instant smooth multi-stop rainbow text
print(Rcolor.gradient_rainbow("A gorgeous smooth rainbow gradient banner across your terminal!"))

10. ANSI Strip Utility (strip_color)

Cleanly calculate visible string lengths and align formatted CLI tables or progress boxes:

colored_banner = Rcolor.gradient_rainbow("Hello World")

# Strip ANSI codes for clean length measurement
plain_banner = Rcolor.strip_color(colored_banner)
print(len(plain_banner))  # Correctly prints 11, ignoring escape sequences!

🎨 Custom Palette Support

You can supply custom palettes at runtime using Rcolor.load_palette().

JSON Schema

Custom palettes must adhere to the following schema:

{
  "schema_version": 1,
  "standard": [
    {
      "id": 0,
      "name": "brand_blue",
      "fg": 34,
      "bg": 44,
      "rgb": [0, 102, 204],
      "hex": "#0066cc"
    }
  ],
  "extended": [
    {
      "id": 33,
      "name": "brand_accent",
      "rgb": [0, 153, 255],
      "hex": "#0099ff"
    }
  ],
  "styles": {
    "bold": 1,
    "underline": 4
  }
}

Loading a Custom Palette in Python

import Rcolor

# Load palette from a JSON file
Rcolor.load_palette("my_brand_palette.json")

# Or load from an in-memory dictionary
Rcolor.load_palette({
    "schema_version": 1,
    "standard": [{"id": 0, "name": "primary", "fg": 32, "bg": 42}],
    "extended": [{"id": 46, "name": "bright_green"}],
    "styles": {"bold": 1}
})

# Reset back to default built-in palette at any time
Rcolor.reset_palette()

print(Rcolor.foreground("Styled with custom palette!"))
πŸ“‹ Complete Formal JSON Schema for Custom Palettes
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "RcolorPalette",
  "type": "object",
  "required": ["schema_version", "standard", "extended", "styles"],
  "properties": {
    "schema_version": { "type": "integer", "enum": [1] },
    "standard": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "name", "fg", "bg"],
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" },
          "fg": { "type": "integer" },
          "bg": { "type": "integer" },
          "rgb": { "type": "array", "items": { "type": "integer" } },
          "hex": { "type": "string" }
        }
      }
    },
    "extended": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id"],
        "properties": {
          "id": { "type": "integer", "minimum": 0, "maximum": 255 },
          "name": { "type": "string" },
          "rgb": { "type": "array", "items": { "type": "integer" } },
          "hex": { "type": "string" }
        }
      }
    },
    "styles": {
      "type": "object",
      "additionalProperties": { "type": "integer" }
    }
  }
}

πŸ“š API Reference

Function Parameters Return Type Description
auto_fg(*user_input, tone=None) *user_input: Any, tone: str | None str Terminal-aware random foreground color (256/16/None), optional tone preset.
auto_bg(*user_input, tone=None) *user_input: Any, tone: str | None str Terminal-aware random background color (256/16/None), optional tone preset.
foreground(*user_input, tone=None) *user_input: Any, tone: str | None str Random 256-color foreground with auto-downgrade, optional tone preset ("neon", "pastel", "warm", "cool").
background(*user_input, tone=None) *user_input: Any, tone: str | None str Random 256-color background with auto-downgrade, optional tone preset.
standard_fg(*user_input) *user_input: Any str Random standard ANSI 16 foreground color.
standard_bg(*user_input) *user_input: Any str Random standard ANSI 16 background color.
style(*user_input) *user_input: Any str Random ANSI text style (bold, dim, underline, etc.).
rainbow_fg(user_input) user_input: Any str Per-character random 256-color rainbow string.
standard_rainbow_fg(user_input) user_input: Any str Per-character random 16-color rainbow string.
gradient_fg(user_input, start=..., end=..., preset=None) user_input: Any, ... str Smooth linear color gradient with auto TrueColor/256/16/None fallback.
gradient_rainbow(user_input) user_input: Any str Smooth multi-stop linear rainbow gradient across text.
foreground_background(*user_input, min_contrast=4.0) *user_input: Any, min_contrast: float str Combined random fg and bg with WCAG Contrast Guard readability guarantee.
foreground_style(*user_input) *user_input: Any str Combined random foreground and style.
background_style(*user_input) *user_input: Any str Combined random background and style.
foreground_background_style(*user_input, min_contrast=4.0) *user_input: Any, min_contrast: float str Combined random fg, bg, and style with WCAG Contrast Guard.
strip_color(text) text: str str Strips all ANSI escape sequences for width and alignment calculations.
contrast_ratio(rgb1, rgb2) rgb1: Sequence[int], rgb2: Sequence[int] float Computes WCAG 2.1 relative contrast ratio between two RGB colors (1.0 to 21.0).
relative_luminance(rgb) rgb: Sequence[int] float Calculates WCAG relative luminance ($L \in [0.0, 1.0]$).
load_palette(source) source: str | Path | dict Palette Loads and activates custom color palette.
reset_palette() None None Resets active palette back to default built-in palette.
detect_color_level() None ColorLevel Detects terminal color capability level without caching.
get_color_level() None ColorLevel Returns current terminal color capability level (cached).
set_color_level(level) level: ColorLevel | None None Manually overrides or resets color level.

πŸ” Troubleshooting

Issue Cause Solution
Output shows raw escape codes like \033[38;5;12m Terminal does not interpret ANSI sequences (e.g. Windows legacy cmd without VT). Ensure colorama is installed, or set environment variable FORCE_COLOR=1.
Output appears completely uncolored NO_COLOR is set, or output is redirected to a file or pipe. Check echo $NO_COLOR. If writing to terminal pipes, pass FORCE_COLOR=1 or CLICOLOR_FORCE=1.
Colors look washed out or different on remote SSH Remote terminal reports TERM=xterm instead of xterm-256color. Run export TERM=xterm-256color in your remote session.
TypeError: Unsupported input type Non-primitive object (such as None or a list) passed to styling function. Ensure inputs are strings, numbers, or booleans.

Tip

To temporarily test how your CLI outputs look without color in CI pipelines, set NO_COLOR=1 in your environment.

Warning

Do not use from Rcolor import * in production scripts. Explicitly import the functions you need to keep your namespace clean.


🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository on GitHub.
  2. Create a branch:
    git checkout -b feature/my-feature
  3. Install development dependencies:
    pip install -e .[dev]
  4. Run the test suite:
    python -m unittest discover tests
    # or
    pytest
  5. Run the benchmark:
    python benchmarks/bench.py
  6. Commit & Push your changes, then submit a Pull Request.
πŸ§ͺ Running Tests & Quality Checks Across Toolchains

Run the test suite using standard library unittest (zero third-party dependencies required):

python -m unittest discover tests

Or using pytest:

pytest -v

Lint with ruff and flake8:

ruff check .
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics

πŸ“· Visual Assets Required

To complete the visual presentation in the README, please create and place the following image assets into docs/images/:

Image File Path Target Dimensions Description & Content to Show
docs/images/rcolor_banner.png 1280 x 400 px Centered project banner featuring modern typographic "Rcolor" logo with vibrant gradient glow on a sleek dark background (#0f172a).
docs/images/preview_foreground.png 800 x 480 px Terminal screenshot demonstrating 8 lines of text generated by Rcolor.foreground() showing diverse 256-color foregrounds.
docs/images/preview_rainbow.png 800 x 480 px Terminal screenshot demonstrating Rcolor.rainbow_fg() showing multi-line vibrant per-character rainbow text.
docs/images/preview_styles.png 800 x 480 px Terminal screenshot demonstrating foreground_background_style() showing bold, underline, and dual-tone color combinations.
docs/images/preview_gradient.png 800 x 480 px Terminal screenshot demonstrating gradient_fg() and gradient_rainbow() showing smooth continuous multi-stop gradients across text.

πŸ“„ License

This project is licensed under the terms of the MIT License.

About

Modern, high-performance terminal color styling for Python with intelligent auto-detection, readability contrast guards, and smooth multi-stop gradients. 🎨

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages