Source code for hydraclick.terminal_effects

import shutil
from typing import Optional, Callable
import os
import sys

import click
from click import Context, Option


[docs] def get_no_terminal_effects() -> bool: """Check if terminal effects should be disabled by looking at environment variables. This function checks the environment variables `OMEGACLICK_NO_TERMINAL_EFFECTS` and `NO_TERMINAL_EFFECTS` to determine if terminal effects should be disabled. If no environment variable is set, it returns `False`. Returns: bool: `True` if terminal effects should be disabled, `False` otherwise. Example: >>> os.environ["NO_TERMINAL_EFFECTS"] = "true" >>> get_no_terminal_effects() True """ val = os.environ.get("OMEGACLICK_NO_TERMINAL_EFFECTS", os.environ.get("NO_TERMINAL_EFFECTS")) if val is None: return False return val.lower() in {"true", "1", "yes"}
[docs] def config_effect(effect): """Configure terminal effects such as print speed and gradient colors. This function adjusts the terminal effect's configuration, such as print speed, return speed, and gradient colors for rendering. Args: effect: The terminal effect object to be configured. Returns: The modified terminal effect object. Example: >>> effect = SomeEffect() >>> config_effect(effect) <configured effect> """ from terminaltexteffects.utils.graphics import Color # noqa: PLC0415 effect.effect_config.print_speed = 15 effect.effect_config.print_head_return_speed = 5 effect.effect_config.final_gradient_stops = (Color("00ffae"), Color("00D1FF"), Color("FFFFFF")) return effect
[docs] def remove_lines(num_lines: int): """Remove the last `num_lines` lines printed in the terminal. This function sends ANSI escape codes to move the terminal cursor up and clear the last `num_lines` lines from the terminal. Args: num_lines (int): The number of lines to remove. Example: >>> remove_lines(3) # Removes the last 3 printed lines """ for _ in range(num_lines): sys.stdout.write("\x1b[1A") # Move the cursor up one line sys.stdout.write("\x1b[2K") # Clear the entire line sys.stdout.flush()
[docs] def count_wrapped_lines(text: str, terminal_width: int) -> int: """Calculate the number of lines the given text will take when wrapped in the terminal. Args: text (str): The text to be wrapped. terminal_width (int): The width of the terminal in characters. Returns: int: The number of lines the text will occupy in the terminal. Example: >>> count_wrapped_lines("This is a long line of text.", 10) 3 """ lines = text.splitlines() total_lines = 0 for line in lines: if terminal_width > 0: num_terminal_lines = (len(line) + terminal_width - 1) // terminal_width else: num_terminal_lines = 1 total_lines += max(num_terminal_lines, 1) return total_lines
[docs] def display_terminal_effect(value: str, effect_cls=None): """Display a terminal effect animation for a given text. This function displays a text-based terminal effect using the provided effect class. The effect is rendered with custom configurations, and once the animation is complete, the effect is cleaned up from the terminal. Args: value (str): The text to display with the terminal effect. effect_cls (optional): The class of the terminal effect to use. Defaults to `Print`. Example: >>> display_terminal_effect("Hello World!") """ from terminaltexteffects.effects.effect_print import Print # noqa: PLC0415 effect_cls = effect_cls or Print effect = effect_cls(value) effect = config_effect(effect) with effect.terminal_output() as terminal: for frame in effect: terminal.print(frame) terminal_width = shutil.get_terminal_size().columns n_lines_last_rendered_frame = count_wrapped_lines(frame, terminal_width) remove_lines(n_lines_last_rendered_frame) last_effect = effect_cls(value) last_effect = config_effect(last_effect) last_effect.terminal_config.ignore_terminal_dimensions = True last_frame = list(last_effect)[-1] sys.stdout.write(last_frame.lstrip()) sys.stdout.write("\n") sys.stdout.flush()
[docs] def patch_parse_args(terminal_effect: Callable): """Patch the Click `parse_args` function to display a terminal effect. This function overrides the `parse_args` method of Click's `MultiCommand` to display a custom terminal effect for the help message when no arguments are passed. Args: terminal_effect (Callable): A callable that renders the terminal effect. Example: >>> patch_parse_args(display_terminal_effect) """ def parse_args(self, ctx: Context, args: list[str]) -> list[str]: """Display the help message with terminal effects when no arguments are provided.""" if not args and self.no_args_is_help and not ctx.resilient_parsing: terminal_effect(ctx.get_help()) ctx.exit() rest = super(click.core.MultiCommand, self).parse_args(ctx, args) if self.chain: ctx.protected_args = rest ctx.args = [] elif rest: ctx.protected_args, ctx.args = rest[:1], rest[1:] return ctx.args click.core.MultiCommand.parse_args = parse_args
[docs] def patch_get_help_option(terminal_effect: Callable): """Patch the Click `get_help_option` function to display a terminal effect for the help option. This function overrides Click's `get_help_option` method to display a terminal effect whenever the help message is requested. Args: terminal_effect (Callable): A callable that renders the terminal effect. Example: >>> patch_get_help_option(display_terminal_effect) """ def get_help_option(self, ctx: Context) -> Optional["Option"]: """Return the help option with a terminal effect callback.""" from gettext import gettext # noqa: PLC0415 help_options = self.get_help_option_names(ctx) if not help_options or not self.add_help_option: return None def show_help(ctx: Context, param: "click.Parameter", value: str) -> None: # noqa: ARG001 if value and not ctx.resilient_parsing: terminal_effect(ctx.get_help()) ctx.exit() return Option( help_options, is_flag=True, is_eager=True, expose_value=False, callback=show_help, help=gettext("Show this message and exit."), ) click.core.Command.get_help_option = get_help_option
[docs] def set_terminal_effect(terminal_effect: Callable): """Set a terminal effect animation for displaying help in Click commands. This function applies a patch to the Click `parse_args` and `get_help_option` methods, so the help message is displayed with the specified terminal effect. Args: terminal_effect (Callable): A callable that renders the terminal effect. Example: >>> set_terminal_effect(display_terminal_effect) """ if not get_no_terminal_effects(): patch_parse_args(terminal_effect) patch_get_help_option(terminal_effect)