Source code for chalky.chalk

# -*- encoding: utf-8 -*-
# Copyright (c) 2020 Stephen Bunn <>
# ISC License <>

"""Contains the base chalk class that is used to group some style and colors."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Optional, Set, Union, overload

from .color import Color_T
from .constants import is_disabled
from .interface import get_interface
from .style import Style

[docs]@dataclass class Chalk: """Describes the style and color to use for styling some printable text. Chalk can be composed using ``&`` and can be applied to strings with ``|``. You can create your own instance of chalk by setting your desired :class:`~style.Style` and :class:`~color.Color` when creating a new instance. Examples: Creating custom instances of chalk looks like the following: >>> my_chalk = Chalk( ... style={Style.BOLD, Style.UNDERLINE}, ... foreground=Color.RED, ... ) Composing two chalk instances can be done through either using ``&`` or ``+``: >>> bold_chalk = Chalk(style={Style.BOLD}) >>> error_chalk = bold_chalk & Chalk(foreground=Color.RED) Using chalk instances to style strings can be done using either ``|`` or ``+``: >>> error_chalk | "Hello, World!" Hello, World! .. important:: When composing two chalk instances together, the chalk *being* applied to the base chalk instance will override the foreground and background colors. This means that if you apply a new chalk with a different foreground color it will override the starting foreground color: >>> red = Chalk(foreground=Color.RED) >>> blue = Chalk(foreground=Color.BLUE) >>> assert blue == (red & blue) """ style: Set[Style] = field(default_factory=set) foreground: Optional[Color_T] = field(default=None) background: Optional[Color_T] = field(default=None)
[docs] def __and__(self, other: Chalk) -> Chalk: """Create a new chalk instance from the composition of two chalk. Args: other (:class:`~Chalk`): Another chalk to combine with the current chalk. Returns: :class:`~Chalk`: The newly created chalk instance. """ return Chalk(, foreground=other.foreground or self.foreground, background=other.background or self.background, )
[docs] def __or__(self, value: Any) -> str: """Style some given string with the current chalk instance. .. tip:: If a non-string value is provided, we will attempt to get the most appropriate string from the value by simply calling ``str(value)``. So if you are passing in an object, make sure to use an appropriate ``__str__`` or ``__repr__``. Args: value (~typing.Any): The value to apply the current chalk styles to. Returns: str: The newly styled string. """ if is_disabled(): return str(value) interface = get_interface() return interface.apply( value=str(value),, background=self.background, foreground=self.foreground, )
@overload def __add__(self, other: Chalk) -> Chalk: # pragma: no cover """Handle applying chalk to other chalk instances. Args: other (:class:`~Chalk`): The chalk instance to apply to the current instance. Returns: :class:`~Chalk`: They newly created chalk instance. """ ... @overload def __add__(self, other: str) -> str: # pragma: no cover """Handle applying chalk to strings. Args: other (str): The string to style with the current chalk instance. Returns: str: They newly styled string. """ ...
[docs] def __add__(self, other: Union[Chalk, str]) -> Union[Chalk, str]: """Handle applying chalk instances to things. Args: other (Union[Chalk, str]): Either another chalk instance or a string. Returns: Union[Chalk, str]: The combined chalk instances or a styled string. """ if isinstance(other, Chalk): return self & other return self | other
[docs] def __call__(self, value: str) -> str: """Handle applying chalk instances to strings. Args: value (str): The string to apply the current styles to. Returns: str: The newly styled string. """ return self | value
@property def reverse(self) -> Chalk: """Color reverse of the current chalk instance. Returns: :class:`~Chalk`: The revsered chalk instance """ return self & Chalk(style={Style.REVERSED})