A library for string color styling using ANSI escape sequences.
Project description
pyansistring
About The Project
pyansistring is a library for string color styling using ANSI escape sequences. The base class inherits from Python's str. You can split, join, or slice the string while preserving the styling.
Features
- Preservation of the str methods.
- Support for 4-, 8-, and 24-bit (True Color) color modes.
- Per-word coloring.
- Left, right, and center alignment without problems caused by string length.
- Support for multiple SGR (Select Graphic Rendition) parameters.
- Support for both the traditional ";" and the modern ":" SGR parameter separators.
- Automated coloring functionality, e.g., rainbow text.
For a more comprehensive list of what's been done so far, see the TODO section.
Inspired by rich and colorama Python libraries.
Getting Started
Prerequisites
- Python 3.11 or higher
- Git (for local installation)
Installation
You can install the package via pip:
pip install pyansistring # or pip3 install pyansistring
pip install pyansistring[svg] # for SVG conversion support
Or locally via git:
- Clone the repository
git clone https://github.com/l1asis/pyansistring
- Navigate to the cloned directory
cd pyansistring
- Change git remote url to avoid accidental pushes to base project
git remote set-url origin github_username/repo_name # Verify the changes git remote -v
- (Optional) Create and activate a virtual environment
python -m venv venv # On Windows .\venv\Scripts\activate # On Unix or MacOS source venv/bin/activate
- Install the package
pip install . pip install .[svg] # for SVG conversion support
Usage
Import the necessary classes and initialize an ANSIString instance:
from pyansistring.pyansistring import ANSIString
from pyansistring.constants import SGR, Foreground, Background, UnderlineMode
Unstyled plain string:
text = ANSIString("Hello, World!")
print(text)
Style the whole string:
print(
ANSIString("Hello, World!")
.fg_4b(Foreground.YELLOW)
.bg_4b(Background.BLUE)
.fm(SGR.BOLD)
)
Style by slice (indices are [start, end, step]):
print(
ANSIString("Hello, World!")
.fg_4b(Foreground.YELLOW, (0, 5), (7, 12)) # "Hello" and "World"
.bg_4b(Background.BLUE, (7, 12)) # "World"
.fm(SGR.BOLD, (7, 12)) # "World"
)
Style by words:
print(
ANSIString("Hello, World!")
.fg_4b_w(Foreground.YELLOW, "Hello", "World")
.bg_4b_w(Background.BLUE, "World")
.fm_w(SGR.BOLD, "Hello", "World")
)
SGR parameters like bold and underline:
print(
ANSIString("Hello, World!")
.fm(SGR.BOLD)
.fm(SGR.UNDERLINE)
)
4-bit examples (doesn't exist for underline):
print(
ANSIString("Hello, World!")
.fg_4b(Foreground.YELLOW)
.bg_4b(Background.BLUE)
)
8-bit examples:
print(
ANSIString("Hello, World!")
.fg_8b(11) # Bright Yellow
.bg_8b(4) # Blue
.ul_8b(74) # Muted Sky Blue
)
24-bit (True Color) example:
print(
ANSIString("Hello, World!")
.fg_24b(255, 255, 0) # Bright Yellow
.bg_24b(0, 0, 238) # Blue
.ul_24b(135, 175, 215) # Light Steel Blue
)
Underline modes (not "styles" to avoid confusion with other styling):
print(
ANSIString("Hello, World!")
.bg_24b(255, 255, 255) # White
.ul_24b(255, 0, 0) # Red
.fm(UnderlineMode.DOUBLE)
)
Lengths and plain text:
styled = ANSIString("Hello, World!").fg_4b(Foreground.MAGENTA)
print(len(styled) == len("Hello, World!"))
# True (logical length ignores ANSI)
print(len(styled.styled_text) == len("Hello, World!"))
# False (includes ANSI codes)
print(styled.actual_length == len("Hello, World!"))
# False (includes ANSI codes)
print(styled.plain)
# "Hello, World!"
ANSIString conversion to SVG text:
from fontTools.ttLib import TTFont
styled = ANSIString("Hello, World!").fg_4b(Foreground.MAGENTA)
styled.to_svg(
font=TTFont("path/to/font.ttf"),
font_size_px=16,
output_file="hello_world.svg"
)
ANSIString conversion to SVG path (for better compatibility when font is not guaranteed to be present):
from fontTools.ttLib import TTFont
styled = ANSIString("Hello, World!").fg_4b(Foreground.MAGENTA)
styled.to_svg(
font=TTFont("path/to/font.ttf"),
font_size_px=16,
convert_text_to_path=True,
output_file="hello_world_path.svg"
)
[!NOTE] Please note that when
convert_text_to_pathis set toTrue, the characters will be converted into vector shapes, which can help ensure that the appearance of the text remains consistent across different platforms and devices, even if the specified font is not available. However, this also means that the text will no longer be selectable or searchable in the SVG file, as it will be treated as graphical elements rather than text. Neither will it be 100% identical to how it looks in the terminal or being rendered as text in the SVG.
[!WARNING] Supported SGR parameters for SVG conversion include:
- Foreground and background colors (4-bit, 8-bit, and 24-bit)
- Underline colors with all modes (single, double, curly, dotted, dashed)
- Bold and italic font styles Unsupported SGR parameters (e.g., strikethrough, inverse, etc.) will be ignored during SVG conversion.
Rainbow text as a separate function:
print(
ANSIString("Hello, World! This is rainbow text!")
.rainbow(fg=True)
)
Colored text using multicolor functionality:
print(
ANSIString("Hello, World! This is multicolor text!")
.multicolor((
"r=0:|g=0:|b=255: $ " # Start with blue
"b>0:repeat(auto) # " # Decrease blue
"r>255:repeat(auto) | " # Increase green and combine with...
"g>255:repeat(auto) " # Increase red
" &*" # Cycle & Start without apply flags
))
)
For more examples, see the examples directory.
Contributing
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
P.S. I would love to see your arts made with pyansistring in the arts.py file, with proper attribution, of course!
License
Distributed under the MIT License. See LICENSE for more information.
Acknowledgements
Project details
Release history Release notifications | RSS feed
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 pyansistring-0.2.0.tar.gz.
File metadata
- Download URL: pyansistring-0.2.0.tar.gz
- Upload date:
- Size: 128.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de2bc921bc4b3902a1b58f7189923d7f97c157bd8f3d9a2c69e4b94734d77e94
|
|
| MD5 |
50499f31b72f276c9a10ba718b541877
|
|
| BLAKE2b-256 |
35508234512fe1cb4c240af48e09c488372e6385cfc0c43d4dbf29451211de09
|
Provenance
The following attestation bundles were made for pyansistring-0.2.0.tar.gz:
Publisher:
publish-to-pypi.yml on l1asis/pyansistring
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyansistring-0.2.0.tar.gz -
Subject digest:
de2bc921bc4b3902a1b58f7189923d7f97c157bd8f3d9a2c69e4b94734d77e94 - Sigstore transparency entry: 1004936160
- Sigstore integration time:
-
Permalink:
l1asis/pyansistring@389b560932c529bb453d8dd5fbf860298059f22f -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/l1asis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@389b560932c529bb453d8dd5fbf860298059f22f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyansistring-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pyansistring-0.2.0-py3-none-any.whl
- Upload date:
- Size: 56.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8361e28992d8d96ff71302f6cef7637c3e446a15776e62c3dddddbb91f5b9af
|
|
| MD5 |
68edcad07284340dc60d365a18ad3c6e
|
|
| BLAKE2b-256 |
bf390ea2dbe129317a2d2dda4a8ef02ddaaea8b973a51a0d32bb8fb36cb7c32e
|
Provenance
The following attestation bundles were made for pyansistring-0.2.0-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on l1asis/pyansistring
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyansistring-0.2.0-py3-none-any.whl -
Subject digest:
d8361e28992d8d96ff71302f6cef7637c3e446a15776e62c3dddddbb91f5b9af - Sigstore transparency entry: 1004936161
- Sigstore integration time:
-
Permalink:
l1asis/pyansistring@389b560932c529bb453d8dd5fbf860298059f22f -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/l1asis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@389b560932c529bb453d8dd5fbf860298059f22f -
Trigger Event:
push
-
Statement type: