This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Reason given by maintainers: Textstyle is now available as Vargula. Try visiting the Vargula library!
textstyle
Simple, powerful, cross-platform terminal text styling for Python
textstyle is a lightweight Python library that makes terminal text styling effortless. With support for colors, backgrounds, text styles, and an intuitive markup format, you can create beautiful CLI applications with just a few lines of code.
✨ Features
- Rich Color Support - Named colors, hex codes (#FF5733), and RGB tuples
- Text Styling - Bold, italic, underline, strikethrough, and more
- Markup Format - Intuitive XML-style tags for easy formatting
- Theme System - Built-in themes (dark/light) and custom themes
- Utility Functions - Strip tags, clean ANSI codes, measure visible length
- Cross-Platform - Works seamlessly on Linux, macOS, and Windows
- NO_COLOR Support - Respects NO_COLOR and FORCE_COLOR environment variables
- Zero Dependencies - Pure Python, no external packages required
- Composable - Mix and match styles, nest tags, create reusable components
📦 Installation
pip install textstyle
Or install from source:
git clone https://github.com/crystallinecore/textstyle.git
cd textstyle
pip install -e .
🚀 Quick Start
import textstyle as ts
# Basic styling
print(ts.style("Error", color="red", look="bold"))
print(ts.style("Success", color="green", look="bold"))
# Markup format
print(ts.format("This is <red>red</red> and <bold>bold</bold>!"))
# Hex colors
print(ts.style("Custom", color="#FF5733", look="bold"))
# Create custom styles
ts.create("error", color="red", look="bold")
print(ts.format("An <error>error</error> occurred!"))
# Use themes
ts.set_theme("dark")
print(ts.format("<error>Error:</error> Connection failed"))
📖 Documentation
Basic Usage
style(text, color=None, bg=None, look=None)
Apply styling to text directly.
import textstyle as ts
# Simple colors
print(ts.style("Hello", color="red"))
print(ts.style("World", color="blue", look="bold"))
# Background colors
print(ts.style("Alert", color="white", bg="red", look="bold"))
# Hex colors
print(ts.style("Brand", color="#FF5733"))
# RGB tuples
print(ts.style("Custom", color=(255, 87, 51)))
# Multiple looks
print(ts.style("Fancy", color="cyan", look=["bold", "underline"]))
Available colors:
black,red,green,yellow,blue,magenta,cyan,whitebright_black,bright_red,bright_green,bright_yellow,bright_blue,bright_magenta,bright_cyan,bright_white
Available looks:
bold,dim,italic,underline,blink,reverse,hidden,strikethrough
Background colors:
- Prefix any color name with
bg_(e.g.,bg="red"orbg="bright_blue")
format(text)
Format text using markup-style tags.
import textstyle as ts
# Predefined color tags
print(ts.format("This is <red>red</red> text"))
# Predefined look tags
print(ts.format("This is <bold>bold</bold> text"))
# Background tags
print(ts.format("Alert: <bg_red><white>WARNING</white></bg_red>"))
# Hex color tags
print(ts.format("Brand: <#FF5733>orange</#FF5733>"))
# Nested tags
print(ts.format("<red><bold>Bold Red</bold></red>"))
# Complex combinations
print(ts.format(
"Status: <green>Connected</green> | "
"Warnings: <yellow>2</yellow> | "
"Errors: <red>0</red>"
))
Custom Styles
create(name, color=None, bg=None, look=None)
Create reusable custom styles.
import textstyle as ts
# Create custom styles
ts.create("error", color="red", look="bold")
ts.create("success", color="green", look="bold")
ts.create("warning", color="yellow", look="bold")
ts.create("highlight", color="black", bg="yellow")
# Use in format()
print(ts.format("<error>ERROR:</error> Connection failed"))
print(ts.format("<success>SUCCESS:</success> File saved"))
print(ts.format("Please <highlight>note</highlight> this"))
# Use as function (dynamic attribute access)
print(ts.error("Direct error styling"))
print(ts.success("Direct success styling"))
delete(name)
Remove a custom style.
ts.delete("error") # Returns True if deleted, False if not found
Theme System
set_theme(theme)
Apply a theme with multiple predefined styles.
Built-in themes:
import textstyle as ts
# Dark theme (bright colors)
ts.set_theme("dark")
print(ts.format("<error>Error</error> <success>Success</success>"))
# Light theme (standard colors)
ts.set_theme("light")
print(ts.format("<warning>Warning</warning> <info>Info</info>"))
Custom themes:
ts.set_theme({
"primary": {"color": "#007AFF", "look": "bold"},
"secondary": {"color": "#5856D6"},
"danger": {"color": "white", "bg": "#FF3B30", "look": "bold"},
"success": {"color": "#34C759", "look": "bold"},
"muted": {"color": "bright_black"}
})
print(ts.format("<primary>Primary Button</primary>"))
print(ts.format("<danger>Delete Account</danger>"))
Built-in theme styles:
error- Error messagessuccess- Success messageswarning- Warning messagesinfo- Informational messagesdebug- Debug outputcritical- Critical alerts
Temporary Styles
temporary(name, color=None, bg=None, look=None)
Context manager for temporary styles.
import textstyle as ts
# Temporary style exists only in context
with ts.temporary("temp", color="magenta", look="italic"):
print(ts.format("<temp>This is temporary</temp>"))
print(ts.format("Still using <temp>temp</temp>"))
# After context, style is automatically deleted
print(ts.format("<temp>This is plain text</temp>"))
Utility Functions
strip(text)
Remove all markup tags from text.
import textstyle as ts
markup = "<red>Hello</red> <bold>World</bold>"
print(ts.strip(markup)) # Output: "Hello World"
clean(text)
Remove all ANSI escape codes from text.
import textstyle as ts
styled = ts.style("Hello", color="red", look="bold")
print(ts.clean(styled)) # Output: "Hello"
length(text)
Calculate visible text length (ignoring ANSI codes).
import textstyle as ts
styled = ts.style("Hello", color="red", look="bold")
print(len(styled)) # Output: 19 (includes ANSI codes)
print(ts.length(styled)) # Output: 5 (visible length)
enable() / disable()
Globally enable or disable styling.
import textstyle as ts
print(ts.style("Styled", color="red")) # Colored output
ts.disable()
print(ts.style("Plain", color="red")) # Plain text
ts.enable()
print(ts.style("Styled", color="red")) # Colored output again
🎯 Real-World Examples
Logging System
import textstyle as ts
import time
ts.set_theme({
"timestamp": {"color": "bright_black"},
"info": {"color": "cyan"},
"success": {"color": "green", "look": "bold"},
"error": {"color": "red", "look": "bold"},
})
def log(level, message):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
print(ts.format(
f"<timestamp>[{timestamp}]</timestamp> "
f"<{level}>{level.upper():<8}</{level}> {message}"
))
log("info", "Application started")
log("success", "Database connected")
log("error", "Failed to load configuration")
CLI Menu
import textstyle as ts
ts.set_theme({
"title": {"color": "cyan", "look": "bold"},
"option": {"color": "green"},
"key": {"color": "yellow", "look": "bold"},
})
menu = """
<title>╔═══════════════════════════╗</title>
<title>║ MAIN MENU ║</title>
<title>╚═══════════════════════════╝</title>
<key>[1]</key> <option>New Project</option>
<key>[2]</key> <option>Open Project</option>
<key>[3]</key> <option>Settings</option>
<key>[Q]</key> <option>Quit</option>
"""
print(ts.format(menu))
Progress Bar
import textstyle as ts
import time
ts.set_theme({
"filled": {"color": "green", "look": "bold"},
"empty": {"color": "bright_black"},
"percent": {"color": "cyan", "look": "bold"},
})
def progress(current, total):
percent = int((current / total) * 100)
filled = int((current / total) * 20)
empty = 20 - filled
bar = ts.format(
f"<filled>{'█' * filled}</filled>"
f"<empty>{'░' * empty}</empty>"
)
print(f"\r{bar} {ts.format(f'<percent>{percent}%</percent>')}",
end="", flush=True)
for i in range(101):
progress(i, 100)
time.sleep(0.05)
Data Table
import textstyle as ts
ts.set_theme({
"header": {"color": "cyan", "look": "bold"},
"good": {"color": "green"},
"warn": {"color": "yellow"},
"error": {"color": "red"},
})
print(ts.format("""
┌─────────────┬─────────┬──────┐
│ <header>Server</header> │ <header>Status</header> │ <header>CPU</header> │
├─────────────┼─────────┼──────┤
│ web-01 │ <good>● Up</good> │ 23% │
│ web-02 │ <warn>◐ Warn</warn> │ 78% │
│ db-01 │ <error>○ Down</error> │ 95% │
└─────────────┴─────────┴──────┘
"""))
Form Validation
import textstyle as ts
ts.set_theme({
"field": {"color": "cyan", "look": "bold"},
"valid": {"color": "green"},
"invalid": {"color": "red"},
})
validation = """
<field>Email:</field> user@example.com <valid>✓ Valid</valid>
<field>Password:</field> ********** <valid>✓ Strong</valid>
<field>Username:</field> ab <invalid>✗ Too short</invalid>
<field>Phone:</field> 555-1234 <valid>✓ Valid</valid>
"""
print(ts.format(validation))
Git-Style Output
import textstyle as ts
ts.set_theme({
"branch": {"color": "cyan", "look": "bold"},
"added": {"color": "green"},
"modified": {"color": "yellow"},
"deleted": {"color": "red"},
})
output = """
On branch <branch>main</branch>
Changes to be committed:
<added>new file: src/app.py</added>
<added>new file: README.md</added>
Changes not staged:
<modified>modified: config.yaml</modified>
<deleted>deleted: old_file.py</deleted>
"""
print(ts.format(output))
🎨 Color Reference
Named Colors
# Standard colors
black, red, green, yellow, blue, magenta, cyan, white
# Bright colors
bright_black, bright_red, bright_green, bright_yellow,
bright_blue, bright_magenta, bright_cyan, bright_white
Hex Colors
# Full hex
print(ts.style("Text", color="#FF5733"))
# Short hex
print(ts.style("Text", color="#F00"))
# In markup
print(ts.format("<#FF5733>Colored text</#FF5733>"))
RGB Colors
# RGB tuples
print(ts.style("Text", color=(255, 87, 51)))
print(ts.style("Text", bg=(0, 128, 255)))
🌍 Environment Variables
textstyle respects standard terminal environment variables:
NO_COLOR
Disable all styling when set (any value):
export NO_COLOR=1
python your_script.py # No colors or styles
FORCE_COLOR
Force enable styling even in non-TTY environments:
export FORCE_COLOR=1
python your_script.py | tee output.log # Colors preserved
🔧 Advanced Usage
Nested Tags
import textstyle as ts
print(ts.format(
"<red><bold>Error:</bold> <underline>Connection failed</underline></red>"
))
print(ts.format(
"<bg_blue><white>Info: <bold>Processing...</bold></white></bg_blue>"
))
Combining Multiple Styles
import textstyle as ts
# Multiple looks in style()
print(ts.style("Text", color="red", look=["bold", "underline"]))
# Combining custom styles
ts.create("alert", color="white", bg="red", look="bold")
ts.create("code", color="cyan", look="italic")
print(ts.format(
"<alert>Warning:</alert> Check <code>config.yaml</code>"
))
Dynamic Styling
import textstyle as ts
def status_color(value):
if value < 50:
return "green"
elif value < 80:
return "yellow"
else:
return "red"
cpu_usage = 75
print(ts.style(
f"CPU: {cpu_usage}%",
color=status_color(cpu_usage),
look="bold"
))
Working with Alignment
import textstyle as ts
# Align with visible length
def align_text(text, width):
visible_len = ts.length(text)
padding = width - visible_len
return text + " " * padding
styled = ts.style("Status", color="green", look="bold")
print(align_text(styled, 20) + "OK")
🧪 Testing
Run the comprehensive test suite:
python -m textstyle
Or create your own tests:
import textstyle as ts
# Disable for testing
ts.disable()
assert ts.style("Test", color="red") == "Test"
# Re-enable
ts.enable()
assert "\033[" in ts.style("Test", color="red")
🤝 Contributing
Contributions are welcome! Here's how you can help:
- Report bugs - Open an issue with details
- Suggest features - Describe your use case
- Submit PRs - Fork, create a branch, and submit
- Improve docs - Help make documentation clearer
Development Setup
git clone https://github.com/crystallinecore/textstyle.git
cd textstyle
pip install -e .
# Run examples
python examples/usage_examples.py
# Run main module tests
python -m textstyle
📋 Requirements
- Python 3.6+
- No external dependencies
Platform Support
| Platform | Status | Notes |
|---|---|---|
| Linux | ✅ Full support | All features work |
| macOS | ✅ Full support | All features work |
| Windows | ✅ Full support | ANSI enabled automatically |
📄 License
MIT License - see LICENSE file for details.
Additional Resources
- GitHub Repository: github.com/crystallinecore/textstyle
- Issue Tracker: Report bugs or request features
- PyPI Package: pypi.org/project/textstyle
💡 Tips & Tricks
Disable Styling in Production
import os
import textstyle as ts
if os.getenv("PRODUCTION"):
ts.disable()
Custom Logger Integration
import logging
import textstyle as ts
class ColoredFormatter(logging.Formatter):
COLORS = {
'DEBUG': 'bright_black',
'INFO': 'cyan',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'white'
}
def format(self, record):
levelname = record.levelname
msg = super().format(record)
if levelname in self.COLORS:
color = self.COLORS[levelname]
bg = 'red' if levelname == 'CRITICAL' else None
look = 'bold' if levelname in ['ERROR', 'CRITICAL'] else None
parts = msg.split(levelname, 1)
if len(parts) == 2:
styled_level = ts.style(levelname, color=color, bg=bg, look=look)
msg = parts[0] + styled_level + parts[1]
return msg
handler = logging.StreamHandler()
handler.setFormatter(ColoredFormatter('%(levelname)s: %(message)s'))
logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
Performance Considerations
import textstyle as ts
# For high-frequency output, disable if not needed
if not sys.stdout.isatty():
ts.disable()
# Reuse styled strings
HEADER = ts.style("Header", color="cyan", look="bold")
ERROR = ts.style("ERROR", color="red", look="bold")
# Use format() for complex markup
# It's more efficient than multiple style() calls
🎓 Learning Path
- Beginner - Start with
style()function - Intermediate - Use
format()with markup tags - Advanced - Create themes and custom styles
- Expert - Build reusable components and utilities
Made with ❤️ by Sivaprasad Murali
Metadata
Release files for textstyle 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| textstyle-1.0.1.tar.gz | 22.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| textstyle-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.2 kB
Release files / textstyle-1.0.1.tar.gz
| Download URL | textstyle-1.0.1.tar.gz |
|---|---|
| Size | 22.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bb248984f250a869401492395feedbc8b6555af172161d807a37f3620a4b7e5a
|
|
BLAKE2b-256 checksum How to use checksums |
96d0d0fbb28816a1e2b47337745082c2d23bed7999a49b7babe49cf4c52757eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.2
|
Release files / textstyle-1.0.1-py3-none-any.whl
| Download URL | textstyle-1.0.1-py3-none-any.whl |
|---|---|
| Size | 19.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
80db0286ecf2dad78d4cf5991ece6b715b5bb6c54969ee97175bf580c6bd997f
|
|
BLAKE2b-256 checksum How to use checksums |
127a0ed0acc1ce63440646219130bbbf4ceef1d86d0f640898f9c80853638cde
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.2
|