Terminal text colorization with regex-based pattern highlighting and smart nesting
Project description
PipeTint
The only terminal colorizer with smart color nesting and pipeline composition.
Python library and CLI tool for terminal text colorization with automatic priority-based color nesting, pipeline composition, and ANSI-aware pattern matching. Zero dependencies, pure Python.
๐ Quick Navigation
- โก Quick Start - Get started in 30 seconds
- ๐จ What Makes PipeTint Unique - Smart nesting, pipelines, channel isolation
- ๐ก Real-World Examples - Log highlighting, syntax highlighting
- ๐ Full Documentation - Complete API reference
- ๐ Installation
โก Quick Start
# Install
pip install pipetint
# Smart color nesting - inner groups automatically win
echo "hello world" | pipetint '(h.(ll))' red blue
# Output: "he" is red, "ll" is blue (inner has higher priority)
# Pipeline composition - colors preserved across stages
echo "hello world" | pipetint 'hello' red | pipetint 'world' blue
# Output: "hello" is red, "world" is blue
# Python API with type-safe constants
from pipetint import colored, RED, BLUE, BOLD
print(colored("Error") | RED | BOLD)
๐จ What Makes PipeTint Unique
1. ๐ง Smart Color Nesting (No other tool has this!)
Automatic priority-based rendering without manual z-index configuration:
# Nested regex groups - inner automatically wins
echo "hello world" | pipetint '(h.(ll))' red blue
# "he" is red, "ll" is blue (inner group has higher priority)
Priority Rules:
- Pipeline stage - Later commands override earlier ones
- Nesting depth - Inner regex groups override outer groups
- Application order - Later applications win within same depth
2. ๐ Pipeline Composition
Colors preserved across pipeline stages with intelligent priority:
# Both colors preserved
echo "hello world" | pipetint 'hello' red | pipetint 'world' blue
# Later stage overrides overlaps
echo "hello world" | pipetint 'hello' red | pipetint 'llo w' green
# "he" is red, "llo w" is green (overrides)
3. ๐ฏ Channel Isolation
Foreground, background, and attributes work independently:
# Background + foreground coexist in same text
echo "hello world" | pipetint '(h.(ll))' bg_red blue
# "he" = red background only
# "ll" = red background AND blue foreground (both channels!)
4. ๐ ANSI-Aware Pattern Matching
Patterns match original text, ignoring existing ANSI codes:
# Works on already-colored text!
colored_text = ColorizedString("H\x1b[31mello\x1b[0m World")
result = colored_text.highlight(r'Hello', ['green'])
# Pattern matches "Hello" despite ANSI codes in the middle
๐ก Real-World Examples
Log File Highlighting
from pipetint import ColorizedString
log = "ERROR: Connection failed at 10:30:45"
result = (ColorizedString(log)
.highlight(r'ERROR', ['red', 'bold'])
.highlight(r'\d{2}:\d{2}:\d{2}', ['blue'])
)
print(result)
# "ERROR" is red+bold, timestamp is blue
Multi-Stage Pipeline Processing
# Stage 1: Highlight errors
cat log.txt | pipetint 'ERROR|CRITICAL' red > /tmp/colored.txt
# Stage 2: Add timestamps (higher priority)
cat /tmp/colored.txt | pipetint '\d{2}:\d{2}:\d{2}' blue
# Both colors preserved, timestamps override errors if overlapping
Syntax Highlighting
code = "def hello_world():"
result = (ColorizedString(code)
.highlight(r'\b(def)\b', ['blue']) # Keywords
.highlight(r'[a-z_]+\w*(?=\()', ['green']) # Functions
)
print(result)
๐ Installation
# From PyPI
pip install pipetint
# From source
git clone https://github.com/jim-my/pipetint.git
cd pipetint
pip install -e .
Requirements:
- Python 3.9+
- Zero dependencies (pure Python)
โจ Features
- ๐ง Smart Color Nesting: Automatic priority-based rendering without manual z-index
- ๐ ANSI-Aware Matching: Patterns match original text, ignoring color codes
- ๐ฏ Channel Isolation: Foreground, background, and attributes work independently
- ๐ Pipeline Composition: Colors preserved across pipeline stages
- ๐ Production Safe: No monkey patching or global state pollution
- ๐ญ Multiple APIs: Choose your style - fluent, functional, or global
- โก High Performance: Efficient implementation with minimal overhead
- ๐งช Well Tested: 143 tests with comprehensive coverage
- ๐ฆ Zero Dependencies: Pure Python implementation
- ๐ฅ๏ธ Cross Platform: Works on Linux, macOS, and Windows
๐ Full Documentation
CLI Usage
Basic Usage
# Simple pattern matching
echo "hello world" | pipetint 'l' red
# Pattern groups
echo "hello world" | pipetint '(h.*o).*(w.*d)' red blue
Advanced: Nested Colors
# Nested regex groups - inner wins
echo "hello world" | pipetint '(h.(ll))' red blue
# Output: "he" is red, "ll" is blue
# Channel isolation - foreground + background
echo "hello world" | pipetint '(h.(ll))' bg_red blue
# Output: "he" = red bg, "ll" = red bg + blue fg
# Color name formats (both work)
echo "hello" | pipetint 'hello' bg_red # Official format
echo "hello" | pipetint 'hello' red_bg # Natural format (auto-normalized)
CLI Options
# List all available colors
pipetint --list-colors
# Case sensitive matching
echo "Hello World" | pipetint --case-sensitive 'Hello' green
# Verbose mode (debugging)
echo "test" | pipetint --verbose 'test' red
# Clear all previous colors before applying new ones
echo "hello world" | pipetint 'hello' red | pipetint --replace-all 'world' blue
# Result: Only "world" is blue, "hello" has no color
Color Removal & Output Formats
Strip ANSI color codes or convert to different formats:
# Remove all colors (strip ANSI codes)
cat colored.log | pipetint --remove-color > clean.log
# Same using --output-format
cat colored.log | pipetint --output-format=plain > clean.log
# Convert colored output to HTML (with inline styles)
echo "ERROR: Failed" | pipetint 'ERROR' red --output-format=html > output.html
# Pipeline: colorize then strip colors for data processing
cat app.log | pipetint 'ERROR' red | grep ERROR | pipetint --remove-color | wc -l
Use Cases:
- Extract plain text from colored terminal output
- Process logs without ANSI codes interfering
- Convert terminal colors to HTML for web display
- Clean up output before saving to files
Python Library API
Type-Safe Constants (Recommended)
from pipetint import colored, txt, RED, GREEN, BLUE, YELLOW, BOLD, BG_WHITE, UNDERLINE
# Type-safe constants with operator chaining
print(colored("Success") | GREEN | BOLD)
print(txt("Warning") | YELLOW)
print(colored("Error") | RED | BOLD | BG_WHITE)
print(txt("Info") >> BLUE >> UNDERLINE)
Global Object with Constants
from pipetint import C, RED, BOLD
C.red("hello") # Direct color method
C("hello") | RED | BOLD # Factory with type-safe constants
C("hello", "red") # Direct colorization (legacy)
Pattern Highlighting
from pipetint import ColorizedString
# Highlight search terms
text = "The quick brown fox jumps over the lazy dog"
highlighted = ColorizedString(text).highlight(
r"(quick)|(fox)|(lazy)",
["red", "blue", "green"]
)
print(highlighted)
# Syntax highlighting
code = "def hello_world():"
result = ColorizedString(code).highlight(r"\b(def)\b", ["blue"])
print(result)
Color Removal
Remove ANSI color codes from text:
from pipetint import Colorize, ColorizedString
# Method 1: Using Colorize
colorizer = Colorize()
colored_text = "\033[31mERROR\033[0m: Connection failed"
clean_text = colorizer.remove_color(colored_text)
print(clean_text) # "ERROR: Connection failed"
# Method 2: Using ColorizedString
cs = ColorizedString("\033[31mERROR\033[0m: Connection failed")
clean = cs.remove_color()
print(str(clean)) # "ERROR: Connection failed"
# Useful for processing colored output
log_line = ColorizedString("...").highlight(r'ERROR', ['red'])
# Later, extract plain text for analysis
plain_text = str(log_line.remove_color())
Available Colors and Styles
Foreground Colors
red, green, blue, yellow, magenta, cyan, white, black, lightred, lightgreen, lightblue, lightyellow, lightmagenta, lightcyan, lightgray, darkgray
Background Colors
bg_red, bg_green, bg_blue, bg_yellow, bg_magenta, bg_cyan, bg_white, bg_black, bg_lightred, bg_lightgreen, bg_lightblue, bg_lightyellow, bg_lightmagenta, bg_lightcyan, bg_lightgray, bg_darkgray
Text Styles
bright/bold, dim, underline, blink, invert/swapcolor, hidden, strikethrough
Type-Safe Color Constants
Use constants instead of error-prone string literals:
from pipetint import colored, RED, GREEN, BLUE, YELLOW, BOLD, BG_WHITE
# โ
Type-safe with IDE autocompletion and error checking
error_msg = colored("CRITICAL") | RED | BOLD | BG_WHITE
success_msg = colored("SUCCESS") | GREEN | BOLD
warning_msg = colored("WARNING") | YELLOW
# โ Error-prone string literals
error_msg = colored("CRITICAL") | "red" | "typo" # Runtime error!
Benefits:
- ๐ IDE Autocompletion: Get suggestions for valid colors
- ๐ก๏ธ Type Checking: Catch typos at development time
- ๐ Self-Documenting: Clear, readable code
- ๐ Refactoring Safe: Rename constants across codebase
- โก No Runtime Errors: Invalid colors caught early
๐จ Advanced: Color Nesting & Priority
Nested Regex Groups
Inner (more specific) capture groups automatically override outer ones:
from pipetint import ColorizedString
text = ColorizedString("hello world")
# Pattern: (h.(ll)) creates two groups
# - Group 1: "hell" (outer) โ red
# - Group 2: "ll" (inner, higher priority) โ blue
result = text.highlight(r'(h.(ll))', ['red', 'blue'])
print(result)
# Output: "he" is red, "ll" is blue (inner wins)
Priority Rules:
- Pipeline stage: Later commands override earlier ones
- Nesting depth: Inner regex groups override outer groups
- Application order: Later applications win within same depth
Channel Isolation
Foreground, background, and attributes are independent channels that can coexist:
text = ColorizedString("hello world")
# Background and foreground don't conflict!
result = text.highlight(r'(h.(ll))', ['bg_red', 'blue'])
print(result)
# Output: "he" has red background
# "ll" has BOTH red background AND blue foreground
Available Channels:
- Foreground (fg): Text color (red, blue, green, etc.)
- Background (bg): Background color (bg_red, bg_blue, etc.)
- Attributes (attr): Bold, underline, dim, etc.
ANSI-Aware Pattern Matching
Patterns always match the original text, even if it contains ANSI codes:
# Text with existing ANSI codes
colored_text = ColorizedString("H\x1b[31mello\x1b[0m World")
# Pattern still matches "Hello" ignoring the ANSI codes in between
result = colored_text.highlight(r'Hello', ['green'])
print(result)
# Works! Pattern matched the original text "Hello World"
Color Name Flexibility
Both bg_red and red_bg formats are supported:
# These are equivalent:
text.highlight(r'hello', ['bg_red']) # Official format
text.highlight(r'hello', ['red_bg']) # Natural format (auto-normalized)
๐งช Development
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=pipetint
# Run specific test file
pytest tests/test_nesting.py
Code Quality
# Format and lint
ruff format --preview .
ruff check --preview .
# Type checking
mypy src/
# Run pre-commit hooks
pre-commit run --all-files
๐ Examples
See the examples/ directory for more comprehensive examples:
examples/quickstart.py- Basic usage patternsexamples/enhanced_demo.py- Full enhanced API demonstrationexamples/nesting_demo.py- Color nesting and priority examples
๐ค Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
Quick Start:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes and add tests
- Run tests and pre-commit hooks:
pytest && pre-commit run --all-files - Commit your changes:
git commit -m "feat: add amazing feature" - Push and create a Pull Request
๐บ๏ธ Roadmap
See ROADMAP.md for planned features and future direction.
Upcoming features:
- Configuration file support (.pipetintrc.yaml)
- Built-in color themes (log-levels, git-diff, python)
- TrueColor (24-bit RGB) support
- Pygments integration for syntax highlighting
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
- Inspired by the Ruby colorize gem
- Built with modern Python best practices
- Designed for production safety and developer experience
๐ Legacy API (Still Supported)
The original API remains fully supported for backward compatibility:
from pipetint import Colorize, ColorizedString
# Original Colorize class
colorizer = Colorize()
print(colorizer.colorize("hello", "red"))
# Original ColorizedString
cs = ColorizedString("hello")
print(cs.colorize("blue"))
๐ Version Management
This project uses automated versioning via git tags:
- Versions are managed by
setuptools-scmbased on git tags poetry-dynamic-versioningintegrates this with Poetry builds- To release:
git tag v1.2.3 && git push --tags
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pipetint-2.1.1.tar.gz.
File metadata
- Download URL: pipetint-2.1.1.tar.gz
- Upload date:
- Size: 30.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.12.10 Darwin/25.0.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3537b5c915304aa663ab9f0b793589ccaed0dc35bbd7ab9f05cecc7e8937a23d
|
|
| MD5 |
f0fc350ce80b5f548a468b992f93f157
|
|
| BLAKE2b-256 |
843ab8c14a3dfc596eb07aac26364ab5ad1b2534e1b0728fceeda05ba40f8ad0
|
File details
Details for the file pipetint-2.1.1-py3-none-any.whl.
File metadata
- Download URL: pipetint-2.1.1-py3-none-any.whl
- Upload date:
- Size: 26.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.12.10 Darwin/25.0.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6ee6b0fc51c393743b53a04ea6a3c75264911f9e3ebff1a667fb46685d4cf80
|
|
| MD5 |
c805013316bd6c774befda5e06144393
|
|
| BLAKE2b-256 |
bdee3e5cb4f59d06e0685c8acc38c56d90e0c8cbde8099861aecf16782ef7d1e
|