diff options
-rw-r--r-- | cmd2/ansi.py | 62 | ||||
-rw-r--r-- | cmd2/argparse_completer.py | 4 | ||||
-rw-r--r-- | cmd2/cmd2.py | 18 |
3 files changed, 24 insertions, 60 deletions
diff --git a/cmd2/ansi.py b/cmd2/ansi.py index f10c29ea..97fb1e8a 100644 --- a/cmd2/ansi.py +++ b/cmd2/ansi.py @@ -1,7 +1,8 @@ # coding=utf-8 """Support for ANSI escape codes which are used for things like applying style to text""" +import functools import re -from typing import Any, Optional +from typing import Any import colorama from colorama import Fore, Back, Style @@ -77,48 +78,15 @@ UNDERLINE_ENABLE = colorama.ansi.code_to_chars(4) UNDERLINE_DISABLE = colorama.ansi.code_to_chars(24) -class TextStyle: - """Style settings for text""" - - def __init__(self, *, fg: str = '', bg: str = '', bold: bool = False, underline: bool = False): - """ - Initializer - :param fg: foreground color. Expects color names in FG_COLORS (e.g. 'lightred'). Defaults to blank. - :param bg: background color. Expects color names in BG_COLORS (e.g. 'black'). Defaults to blank. - :param bold: apply the bold style if True. Defaults to False. - :param underline: apply the underline style if True. Defaults to False. - """ - self.fg = fg - self.bg = bg - self.bold = bold - self.underline = underline - - -# Default styles. These can be altered to suit an application's needs. -SuccessStyle = TextStyle(fg='green', bold=True) -WarningStyle = TextStyle(fg='lightyellow') -ErrorStyle = TextStyle(fg='lightred') - - -def style(text: Any, text_style: Optional[TextStyle] = None, *, - fg: Optional[str] = None, bg: Optional[str] = None, - bold: Optional[bool] = None, underline: Optional[bool] = None) -> str: +def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, underline: bool = False) -> str: """ Applies a style to text :param text: Any object compatible with str.format() - :param text_style: a TextStyle object. Defaults to None. - - The following are keyword-only parameters which allow calling style without creating a TextStyle object - style(text, fg='blue') - - They can also be used to override a setting in a provided TextStyle - style(text, ErrorStyle, underline=True) - - :param fg: foreground color. Expects color names in FG_COLORS (e.g. 'lightred'). Defaults to None. - :param bg: background color. Expects color names in BG_COLORS (e.g. 'black'). Defaults to None. - :param bold: apply the bold style if True. Defaults to None. - :param underline: apply the underline style if True. Defaults to None. + :param fg: foreground color. Expects color names in FG_COLORS (e.g. 'lightred'). Defaults to no color. + :param bg: background color. Expects color names in BG_COLORS (e.g. 'black'). Defaults to no color. + :param bold: apply the bold style if True. Defaults to False. + :param underline: apply the underline style if True. Defaults to False. :return: the stylized string """ @@ -131,16 +99,6 @@ def style(text: Any, text_style: Optional[TextStyle] = None, *, # Convert the text object into a string if it isn't already one text = "{}".format(text) - # Figure out what parameters to use - if fg is None and text_style is not None: - fg = text_style.fg - if bg is None and text_style is not None: - bg = text_style.bg - if bold is None and text_style is not None: - bold = text_style.bold - if underline is None and text_style is not None: - underline = text_style.underline - # Process the style settings if fg: try: @@ -166,3 +124,9 @@ def style(text: Any, text_style: Optional[TextStyle] = None, *, # Combine the ANSI escape strings with the text return "".join(additions) + text + "".join(removals) + + +# Default styles. These can be altered to suit an application's needs. +style_success = functools.partial(style, fg='green', bold=True) +style_warning = functools.partial(style, fg='lightyellow') +style_error = functools.partial(style, fg='lightred') diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py index fd0eb0ec..72973bec 100644 --- a/cmd2/argparse_completer.py +++ b/cmd2/argparse_completer.py @@ -66,7 +66,7 @@ import sys from argparse import ZERO_OR_MORE, ONE_OR_MORE, ArgumentError, _, _get_action_name, SUPPRESS from typing import List, Dict, Tuple, Callable, Union -from .ansi import ansi_safe_wcswidth, style, ErrorStyle +from .ansi import ansi_safe_wcswidth, style_error from .rl_utils import rl_force_redisplay # attribute that can optionally added to an argparse argument (called an Action) to @@ -994,7 +994,7 @@ class ACArgumentParser(argparse.ArgumentParser): linum += 1 self.print_usage(sys.stderr) - formatted_message = style(formatted_message, ErrorStyle) + formatted_message = style_error(formatted_message) self.exit(2, '{}\n\n'.format(formatted_message)) def format_help(self) -> str: diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index dbc540cd..c92a32ec 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -60,7 +60,7 @@ if rl_type == RlType.NONE: # pragma: no cover rl_warning = "Readline features including tab completion have been disabled since no \n" \ "supported version of readline was found. To resolve this, install \n" \ "pyreadline on Windows or gnureadline on Mac.\n\n" - sys.stderr.write(ansi.style(rl_warning, ansi.WarningStyle)) + sys.stderr.write(ansi.style_warning(rl_warning)) else: from .rl_utils import rl_force_redisplay, readline @@ -616,7 +616,7 @@ class Cmd(cmd.Cmd): where the message text already has the desired style. Defaults to True. """ if apply_style: - final_msg = ansi.style(msg, ansi.ErrorStyle) + final_msg = ansi.style_error(msg) else: final_msg = "{}".format(msg) self._decolorized_write(sys.stderr, final_msg + end) @@ -639,11 +639,11 @@ class Cmd(cmd.Cmd): final_msg = "{}".format(msg) if apply_style: - final_msg = ansi.style(final_msg, ansi.ErrorStyle) + final_msg = ansi.style_error(final_msg) if not self.debug: warning = "\nTo enable full traceback, run the following command: 'set debug true'" - final_msg += ansi.style(warning, ansi.WarningStyle) + final_msg += ansi.style_warning(warning) # Set apply_style to False since style has already been applied self.perror(final_msg, end=end, apply_style=False) @@ -3246,7 +3246,7 @@ class Cmd(cmd.Cmd): if args.__statement__.command == "pyscript": warning = ("pyscript has been renamed and will be removed in the next release, " "please use run_pyscript instead\n") - self.perror(ansi.style(warning, ansi.WarningStyle)) + self.perror(ansi.style_warning(warning)) return py_return @@ -3555,7 +3555,7 @@ class Cmd(cmd.Cmd): # Check if all commands ran if commands_run < len(history): warning = "Command {} triggered a stop and ended transcript generation early".format(commands_run) - self.perror(ansi.style(warning, ansi.WarningStyle)) + self.perror(ansi.style_warning(warning)) # finally, we can write the transcript out to the file try: @@ -3675,7 +3675,7 @@ class Cmd(cmd.Cmd): if args.__statement__.command == "load": warning = ("load has been renamed and will be removed in the next release, " "please use run_script instead\n") - self.perror(ansi.style(warning, ansi.WarningStyle)) + self.perror(ansi.style_warning(warning)) # load has been deprecated do_load = do_run_script @@ -3702,7 +3702,7 @@ class Cmd(cmd.Cmd): if args.__statement__.command == "_relative_load": warning = ("_relative_load has been renamed and will be removed in the next release, " "please use _relative_run_script instead\n") - self.perror(ansi.style(warning, ansi.WarningStyle)) + self.perror(ansi.style_warning(warning)) file_path = args.file_path # NOTE: Relative path is an absolute path, it is just relative to the current script directory @@ -3756,7 +3756,7 @@ class Cmd(cmd.Cmd): if test_results.wasSuccessful(): self._decolorized_write(sys.stderr, stream.read()) finish_msg = '{0} transcript{1} passed in {2:.3f} seconds'.format(num_transcripts, plural, execution_time) - finish_msg = ansi.style(utils.center_text(finish_msg, pad='='), ansi.SuccessStyle) + finish_msg = ansi.style_success(utils.center_text(finish_msg, pad='=')) self.poutput(finish_msg) else: # Strip off the initial traceback which isn't particularly useful for end users |