Skip to content

l1asis/pyansistring

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pyansistring

pyansistring Banner

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

Installation

You can install the package via pip:

pip install pyansistring # or pip3 install pyansistring

Or locally via git:

  1. Clone the repository
    git clone https://github.com/l1asis/pyansistring
  2. Navigate to the cloned directory
    cd pyansistring
  3. 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
  4. (Optional) Create and activate a virtual environment
    python -m venv venv
    # On Windows
    .\venv\Scripts\activate
    # On Unix or MacOS
    source venv/bin/activate
  5. Install the package
    pip install .

(back to top)

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)

Result: unstyled plain string in black

Style the whole string:

print(
    ANSIString("Hello, World!")
        .fg_4b(Foreground.YELLOW)
        .bg_4b(Background.BLUE)
        .fm(SGR.BOLD)
)

Result: string with yellow foreground, blue background, and bold styling

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"
)

Result: string where "Hello" and "World" have a yellow foreground. "World" also has a blue background and is in bold.

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")
)

Result: string where "Hello" and "World" have a yellow foreground and bold styling. "World" also has a blue background.

SGR parameters like bold and underline:

print(
    ANSIString("Hello, World!")
        .fm(SGR.BOLD)
        .fm(SGR.UNDERLINE)
)

Result: bold and single underlined string

4-bit examples (doesn't exist for underline):

print(
    ANSIString("Hello, World!")
        .fg_4b(Foreground.YELLOW)
        .bg_4b(Background.BLUE)
)

Result: string with yellow foreground and blue background

8-bit examples:

print(
    ANSIString("Hello, World!")
        .fg_8b(11)  # Bright Yellow
        .bg_8b(4)   # Blue
        .ul_8b(74)  # Muted Sky Blue
)

Result: string with bright yellow foreground, blue background, and muted sky blue underline

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
)

Result: string with bright yellow foreground, blue background, and light steel blue underline

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)
)

Result: string with white background and red double underline

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: The convert_text_to_path parameter does not affect the visual appearance of the generated SVG. It only changes how the text is represented within the SVG file. But, it does not support bold and italic styles or underlines at the moment.

Rainbow text as a separate function:

print(
    ANSIString("Hello, World! This is rainbow text!")
        .rainbow(fg=True)
)

Result: rainbow text with automatic transition

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
        ))
)

Result: multicolor text with a transition effect from blue to yellow

(back to top)

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!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. 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!

(back to top)

License

Distributed under the MIT License. See LICENSE for more information.

(back to top)

Acknowledgements

(back to top)

Releases

No releases published

Packages

No packages published

Languages