Skip to main content

A powerful Python library for terminal string styling, advanced ANSI color manipulation, and SVG terminal rendering.

Project description

pyansistring

pyansistring Banner

CI/CD Pipeline Coverage PyPI Version PyPI Python version PyPI downloads License Ruff

pyansistring gives you a string type that keeps styling securely attached while you use familiar, native Python string operations. Whether you are building a simple CLI tool, visualizing data in a complex terminal dashboard, or exporting styled output to the web, pyansistring handles the math and formatting for you.

Features

  • ANSIString class that subclasses Python str.
  • Style-preserving operations for concatenation, slicing, splitting, joining, replacing, stripping, case transforms, and formatting (f-strings, .format()).
  • SGR styling and attributes: bold, dim, italic, underline, strikethrough, invert, and advanced underline modes (single, double, curly, dotted, dashed).
  • Color channels: 4-bit ANSI, 8-bit palette, and 24-bit RGB for foreground, background, and underlines.
  • Targeting modes: apply to full strings, slice ranges, or word matches (case-sensitive or insensitive).
  • Gradient engine: RGB or HSL interpolation, coordinate-based gradients for multiline text, and out-of-bounds handling.
  • SVG export: render text or path modes with per-character coloring and optional custom fonts.
  • ANSI parsing: convert raw ANSI-encoded strings back into ANSIString instances with styles intact.
  • Large constants base: extensive predefined color constants and palettes, plus SGR/regex helpers for easy access.

Requirements

  • Python 3.11+

Installation

Install the base package:

pip install pyansistring

Install extras when needed:

pip install pyansistring[svg]            # For SVG export
pip install pyansistring[all]            # Install all optional dependencies

Quick Start

from pyansistring import ANSIString, Foreground, Background, SGR

text = (
    ANSIString("Hello, World!")
    .fg(Foreground.YELLOW)
    .bg(Background.BLUE)
    .style(SGR.BOLD)
)

print(text)

Usage Examples

The examples below are generated by examples/generate_usage_svg.py.

Unstyled text

from pyansistring import ANSIString

print(ANSIString("Hello, World!"))

unstyled

Whole string styling

from pyansistring import ANSIString, Foreground, Background, SGR

print(
    ANSIString("Hello, World!")
    .fg(Foreground.YELLOW)
    .bg(Background.BLUE)
    .style(SGR.BOLD)
)

whole

Target Selectors: Slices

from pyansistring import ANSIString, Foreground, Background, SGR

print(
    ANSIString("Hello, World!")
    .fg(Foreground.YELLOW, (0, 5), (7, 12))
    .bg(Background.BLUE, (7, 12))
    .style(SGR.BOLD, (7, 12))
)

slice

Target Selectors: Words

from pyansistring import ANSIString, Foreground, Background, SGR, Words

print(
    ANSIString("Hello, World!")
    .fg(Foreground.YELLOW, Words(("Hello", "World")))
    .bg(Background.BLUE, Words(("World",)))
    .style(SGR.BOLD, Words(("Hello", "World")))
)

words

Target Selectors: Chars

from pyansistring import ANSIString, Chars

print(
    ANSIString("Hello, World!")
    .bg((200, 50, 50), Chars(skip_whitespace=True))
    .fg(0)
)

chars

Target Selectors: Regex Patterns

from pyansistring import ANSIString, NamedColors, Pattern, SGR

print(
    ANSIString("Error 404: Not Found!")
    .fg(NamedColors.RED, Pattern(r"\d+"))
    .style(SGR.BOLD, Pattern(r"\d+"))
)

pattern

Advanced Regex (Log Parsing)

from pyansistring import ANSIString, Foreground, Pattern, SGR

print(
    ANSIString("Login: [WARN] User 'admin' failed from 192.168.1.50")
    .fg(Foreground.YELLOW, Pattern(r"\[WARN\]"))
    .fg(Foreground.CYAN, Pattern(r"'.*?'"))
    .style(SGR.UNDERLINE, Pattern(r"\b\d{1,3}(?:\.\d{1,3}){3}\b"))
)

pattern_advanced

SGR attributes

from pyansistring import ANSIString, SGR

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

sgr

4-bit, 8-bit, and 24-bit colors

from pyansistring import ANSIString, Foreground, Background, NamedColors

# 4-bit (Enums)
print(ANSIString("Hello, World!").fg(Foreground.YELLOW).bg(Background.BLUE))
# 8-bit (Integers)
print(ANSIString("Hello, World!").fg(11).bg(4).ul(74))
# 24-bit (Tuples)
print(ANSIString("Hello, World!").fg((255, 255, 0)).bg((0, 0, 238)).ul((135, 175, 215)))
# Web Colors (Named Colors Namespace)
print(ANSIString("Hello, World!").fg(NamedColors.GOLD).bg(NamedColors.MIDNIGHT_BLUE))

4bit 8bit rgb named_colors

Underline modes

from pyansistring import ANSIString, UnderlineMode

print(
    ANSIString("Hello, World!")
    .bg((255, 255, 255))
    .ul((255, 0, 0))
    .style(UnderlineMode.DOUBLE)
)

underline

Rainbow Effect

from pyansistring import ANSIString

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

rainbow

Gradient APIs

from pyansistring import ANSIString, Words, Coords

print(
    ANSIString("Hello, World! This is gradient text!")
    .gradient([(84, 161, 255), (233, 200, 216)])
)

print(
    ANSIString("Hello, colorful gradient world!")
    .gradient([(255, 99, 71), (255, 215, 0)], Words(("Hello", "world"), ignore_case=True))
)

print(
    ANSIString("HELLO\nworld")
    .gradient(
        [(255, 0, 120), (0, 200, 255)],
        Coords(((1, 1), (2, 1), (3, 1), (4, 1), (5, 1)), index_base=1)
    )
)

gradient
gradient_words
gradient_coordinates

Data-Driven Colormaps

from pyansistring import ANSIString, Pattern, NamedColors, Channel
from pyansistring.color import SegmentedColorMap, ColorMap, ColorScale

ramp_text = "".join(f"{n:<5}" for n in range(0, 101, 10))

# Segmented Map (Threshold Snapping)
cmap_seg = SegmentedColorMap({
    0: NamedColors.LIME, 
    60: NamedColors.YELLOW, 
    90: NamedColors.RED
})

print(ANSIString(ramp_text).colormap(cmap_seg, Pattern(r"\d+\s*"), channel=Channel.BG).fg(0))

# Continuous Map (Smooth Interpolation)
scale = ColorScale([(0, 255, 255), (255, 255, 0), (255, 0, 0)], space="hsl")
cmap_cont = ColorMap(scale, vmin=0, vmax=100)

print(ANSIString(ramp_text).colormap(cmap_cont, Pattern(r"\d+\s*"), channel=Channel.BG).fg(0))

colormap_segmented
colormap_continuous

Parse ANSI text back into ANSIString

from pyansistring import ANSIString

raw = "\x1b[31mError\x1b[0m: file not found"
parsed = ANSIString.from_ansi(raw)

print(parsed.plain_text)
print(parsed)

Export ANSIString to SVG

from fontTools.ttLib import TTFont
from pyansistring import ANSIString, SGR

font = TTFont("path/to/font.ttf")
styled = ANSIString("SVG output").style(SGR.BOLD).fg((90, 170, 255))

svg_code = styled.to_svg(
    font=font,
    font_size_px=16,
    convert_text_to_path=False,
)

For a complete terminal tour, run examples/showcase.py.

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.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feat/amazing-feature)
  3. Commit your Changes (git commit -m 'feat: ✨ add some amazing-feature')
  4. Push to the Branch (git push origin feat/amazing-feature)
  5. Open a Pull Request

[!IMPORTANT] If linting or tests fail, make sure to fix those and push the changes.

License

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

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

pyansistring-0.5.0.tar.gz (206.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyansistring-0.5.0-py3-none-any.whl (67.4 kB view details)

Uploaded Python 3

File details

Details for the file pyansistring-0.5.0.tar.gz.

File metadata

  • Download URL: pyansistring-0.5.0.tar.gz
  • Upload date:
  • Size: 206.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyansistring-0.5.0.tar.gz
Algorithm Hash digest
SHA256 e0a186b7be5b1947b26593127e864184a6b1d1d84d4429576bd289d21c1e6f6e
MD5 82579d0ff5127f76cd2c1e58b6b33e5e
BLAKE2b-256 9a3dfdb2042145d358ae5fce16fe41ce2e116ef4795e9c53c3ff13a114d0832f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyansistring-0.5.0.tar.gz:

Publisher: ci-cd.yml on l1asis/pyansistring

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyansistring-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: pyansistring-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 67.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyansistring-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2f14453b4d1ad5b2513fbfe5aad2977f647a53806249ac72bb14628f0c1ece5a
MD5 35959d10633c2b3f2fcad4f048e80eca
BLAKE2b-256 c381c1d8a68e0e28ba5301c1654ca01d34ae2d4f0b27a2fcccd26c39a592ad32

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyansistring-0.5.0-py3-none-any.whl:

Publisher: ci-cd.yml on l1asis/pyansistring

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page