Source code for chalky.chain

# -*- encoding: utf-8 -*-
# Copyright (c) 2020 Stephen Bunn <stephen@bunn.io>
# ISC License <https://choosealicense.com/licenses/isc>

"""Contains the chain class that can be used to quickly produce styles and colors."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Union, overload

from .chalk import Chalk
from .color import Color, Color_T, TrueColor
from .style import Style


[docs]@dataclass class Chain: """Quickly produce a chain of styles and colors that can be applied to a string. Parameters: chalk (Chalk): The container chalk instance that contains the current chain style. Examples: Chaining styles together should be fairly straightforward: >>> from chalk import chain >>> print(chain.bold.blue | "Bold blue text") >>> print(chain.black.bg.green.italic | "Italic black text on green background") Once a :class:`~.chain.Chain` instance is applied to a string, the styles are consumed and the chain instance is reset. """ _chalk: Chalk = field(default_factory=Chalk) _background: bool = field(default=False)
[docs] def __and__(self, other: Union[Chalk, Chain]) -> Chain: """Compose the chain with another chain or a chalk instance. Args: other (Union[Chalk, Chain]): Another :class:`~.shortcuts.chain.Chain` or :class:`~.chalk.Chalk` instance to compose with the current chain. Returns: :class:`~.shortcuts.chain.Chain`: The newly updated chain. """ if isinstance(other, Chalk): self._chalk = self._chalk & other return self self._chalk = self._chalk & other._chalk return self
@overload def __add__( self, other: Union[Chalk, Chain] ) -> Chain: # noqa: D105 # pragma: no cover ... @overload def __add__(self, other: str) -> str: # noqa: D105 # pragma: no cover ...
[docs] def __add__(self, other: Union[Chalk, Chain, str]) -> Union[Chain, str]: """Handle applying chain instances to things. Args: other (Union[Chalk, Chain, str]): Either a chalk instance, a chain instance, or a string. Returns: Union[Chain, str]: The updated chain or the applied string. """ if isinstance(other, str): return self | other return self & other
[docs] def __or__(self, value: str) -> str: """Style some given string with the current chain. Args: value (str): THe string to apply the current chain to. Returns: str: The newly styled string. """ applied = self._chalk | value self._reset() return applied
[docs] def __call__(self, value: str) -> str: """Handle applying a chain to a strings. Args: value (str): The string to apply the current chain to. Returns: str: The newly styled string. """ return self | value
def _reset(self): self._chalk = Chalk() self._background = False def _handle_style(self, style: Style) -> Chain: self._chalk.style.add(style) return self def _handle_color(self, color: Color_T) -> Chain: if self._background: self._chalk.background = color else: self._chalk.foreground = color return self
[docs] def rgb(self, red: int, green: int, blue: int) -> Chain: """Add a truecolor chalk from an RGB tuple. Args: red (int): The intensity of red (0-255). green (int): The intensity of green (0-255). blue (int): The intensity of blue (0-255). Returns: :class:`~.chain.Chain`: The newly updated chain. """ return self._handle_color(TrueColor(red, green, blue))
[docs] def hex(self, color: str) -> Chain: """Add a truecolor chalk from a hex string. Args: color (str): The hex color string (#ffffff) Returns: :class:`~.chain.Chain`: The newly updated chain. """ return self._handle_color(TrueColor.from_hex(color))
@property def chalk(self) -> Chalk: """Extract the currently built chalk instance. .. important:: Consuming this property will reset the current chain's styles. We are assuming that if you need the :class:`~.chalk.Chalk`, you have finished constructing it through the chaining syntax. Returns: ~.chalk.Chalk: The current chalk instance from the chained styles and colors. """ chalk = self._chalk self._reset() return chalk @property def bg(self) -> Chain: """Following colors will be applied as the background color.""" self._background = True return self @property def fg(self) -> Chain: """Following colors will be applied as the foreground color.""" self._background = False return self @property def bold(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.BOLD) @property def dim(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.DIM) @property def italic(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.ITALIC) @property def underline(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.UNDERLINE) @property def slow_blink(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.SLOW_BLINK) @property def rapid_blink(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.RAPID_BLINK) @property def reversed(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.REVERSED) @property def conceal(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.CONCEAL) @property def strikethrough(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.STRIKETHROUGH) @property def normal(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_style(Style.NORMAL) @property def black(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BLACK) @property def red(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.RED) @property def green(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.GREEN) @property def yellow(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.YELLOW) @property def blue(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BLUE) @property def magenta(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.MAGENTA) @property def cyan(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.CYAN) @property def white(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.WHITE) @property def bright_black(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BRIGHT_BLACK) @property def bright_red(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BRIGHT_RED) @property def bright_green(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BRIGHT_GREEN) @property def bright_yellow(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BRIGHT_YELLOW) @property def bright_blue(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BRIGHT_BLUE) @property def bright_magenta(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BRIGHT_MAGENTA) @property def bright_cyan(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BRIGHT_CYAN) @property def bright_white(self) -> Chain: # noqa: D102 # pragma: no cover return self._handle_color(Color.BRIGHT_WHITE)
chain = Chain()