Skip to content

Add Colors Library to CLI #10

@krowvin

Description

@krowvin

Proposal

Either use a custom implementation or a library for handling colors in the terminal.

While these seems like a feature that could be saved until the end, if we take the time to include it at the base level it will make a sharper output long run and less refactoring.

Thoughts

I'll go with Option 1 for now if we have no preference on this. Ideally bubble it up to all of cwms-cli for use by the child scripts. But if you think color is not needed for all I can just have it in critical data places using the Option 1 code here to keep it small!

Pros/Cons

Pros Cons
Smaller size. More work to implement cross platform support (possibly).
No requirement to follow an upstream library's major versions (easier to maintain). Less features, we'd have to make them ourselves.
Custom Features are easy add. Lets us make something like a "counter" and color based on thresholds. Library could stop being maintained...

Option 1 - Something Custom

I have this in my current cli code that uses ANSI Escape Codes for csv i'm bringing over:

terminal.py (click to view)

The code below is called like this:

 logger.info(
            f"Built timeseries {colorize(name, 'blue')} with {colorize_count(valid, total)} valid points."
        )
        logger.debug(
            f"Timeseries {name} data range: {colorize(datetime.fromtimestamp(start_epoch), 'blue')} to {colorize(datetime.fromtimestamp(end_epoch), 'blue')}"
        )
def colorize_count(valid: int, total: int) -> str:
    ''' Colorize the count based on the percentage of valid data.
    Args:
        valid (int): Number of valid data.
        total (int): Total number of data.
    Returns:
        str: ANSI Escape Code representing the colorized count status.
    '''
    percent = valid / total if total else 0

    if valid == 0:
        color = "red"
    elif percent >= 0.95:
        color = "green"
    else:
        color = "yellow"

    return f"{colorize(f'{valid}/{total}', color)}"

def colorize(text: str, color: str) -> str:
    ''' Colorize the text with ANSI Escape Codes provided a color
    Args:
        text (str): Text to colorize.
        color (str): Color to use.

    Returns:
        str: ANSI Escape Code representing the colorized count status.
    '''
    COLORS = {
        "red": "\033[91m",
        "green": "\033[92m",
        "yellow": "\033[93m",
        "blue": "\033[94m",
        "magenta": "\033[95m",
        "cyan": "\033[96m",
        "white": "\033[97m",
        "gray": "\033[90m",
        "reset": "\033[0m",
    }
    
    if color not in COLORS:
        return text

    return f"{COLORS.get(color.lower(), COLORS['reset'])}{text}{COLORS['reset']}"

Option 2 : Library

here's some libraries I found for this:

Library Last PR stars
colorama last month 3700+
colored last month 45
tcolorpy 8 months ago 11

Leaning towards colorama, which has code like this:

from colorama import init
init(autoreset=True)
print(Fore.RED + 'some red text')
print('automatically back to default color again')

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions