diff options
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | cmd2/ansi.py | 25 | ||||
-rw-r--r-- | tests/test_ansi.py | 17 |
3 files changed, 34 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dcb2a12..7d5c9745 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,16 @@ * Bug Fixes * Fixed bug where startup script containing a single quote in its file name was incorrectly quoted * Added missing implicit dependency on `setuptools` due to build with `setuptools_scm` +* Enhancements + * Added dim text style support via `style()` function and `ansi.INTENSITY_DIM` setting. * Breaking changes * Renamed the following `ansi` members for accuracy in what types of ANSI escape sequences are handled * `ansi.allow_ansi` -> `ansi.allow_style` * `ansi.ansi_safe_wcswidth()` -> `ansi.style_aware_wcswidth()` * `ansi.ansi_aware_write()` -> `ansi.style_aware_write()` + * Renamed the following `ansi` members for clarification + * `ansi.BRIGHT` -> `ansi.INTENSITY_BRIGHT` + * `ansi.NORMAL` -> `ansi.INTENSITY_NORMAL` ## 0.9.22 (December 9, 2019) * Bug Fixes diff --git a/cmd2/ansi.py b/cmd2/ansi.py index c80d3371..b3dd7cc1 100644 --- a/cmd2/ansi.py +++ b/cmd2/ansi.py @@ -22,9 +22,8 @@ STYLE_ALWAYS = 'Always' # Controls when ANSI style style sequences are allowed in output allow_style = STYLE_TERMINAL -# Regular expression to match ANSI style sequences -# This matches: colorama.ansi.CSI + 0 or more digits + m -ANSI_STYLE_RE = re.compile(r'\033\[[0-9]*m') +# Regular expression to match ANSI style sequences (including 8-bit and 24-bit colors) +ANSI_STYLE_RE = re.compile(r'\x1b\[[^m]*m') # Foreground color presets FG_COLORS = { @@ -72,8 +71,10 @@ FG_RESET = FG_COLORS['reset'] BG_RESET = BG_COLORS['reset'] RESET_ALL = Style.RESET_ALL -BRIGHT = Style.BRIGHT -NORMAL = Style.NORMAL +# Text intensities +INTENSITY_BRIGHT = Style.BRIGHT +INTENSITY_DIM = Style.DIM +INTENSITY_NORMAL = Style.NORMAL # ANSI style sequences not provided by colorama UNDERLINE_ENABLE = colorama.ansi.code_to_chars(4) @@ -139,7 +140,8 @@ def bg_lookup(bg_name: str) -> str: return ansi_escape -def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, underline: bool = False) -> str: +def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, + dim: bool = False, underline: bool = False) -> str: """ Apply ANSI colors and/or styles to a string and return it. The styling is self contained which means that at the end of the string reset code(s) are issued @@ -148,7 +150,8 @@ def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, underlin :param text: Any object compatible with str.format() :param fg: foreground color. Relies on `fg_lookup()` to retrieve ANSI escape based on name. Defaults to no color. :param bg: background color. Relies on `bg_lookup()` to retrieve ANSI escape based on name. Defaults to no color. - :param bold: apply the bold style if True. Defaults to False. + :param bold: apply the bold style if True. Can be combined with dim. Defaults to False. + :param dim: apply the dim style if True. Can be combined with bold. Defaults to False. :param underline: apply the underline style if True. Defaults to False. :return: the stylized string """ @@ -171,8 +174,12 @@ def style(text: Any, *, fg: str = '', bg: str = '', bold: bool = False, underlin removals.append(BG_RESET) if bold: - additions.append(Style.BRIGHT) - removals.append(Style.NORMAL) + additions.append(INTENSITY_BRIGHT) + removals.append(INTENSITY_NORMAL) + + if dim: + additions.append(INTENSITY_DIM) + removals.append(INTENSITY_NORMAL) if underline: additions.append(UNDERLINE_ENABLE) diff --git a/tests/test_ansi.py b/tests/test_ansi.py index 2382c333..cb68cb28 100644 --- a/tests/test_ansi.py +++ b/tests/test_ansi.py @@ -45,10 +45,16 @@ def test_style_bg(): def test_style_bold(): base_str = HELLO_WORLD - ansi_str = ansi.BRIGHT + base_str + ansi.NORMAL + ansi_str = ansi.INTENSITY_BRIGHT + base_str + ansi.INTENSITY_NORMAL assert ansi.style(base_str, bold=True) == ansi_str +def test_style_dim(): + base_str = HELLO_WORLD + ansi_str = ansi.INTENSITY_DIM + base_str + ansi.INTENSITY_NORMAL + assert ansi.style(base_str, dim=True) == ansi_str + + def test_style_underline(): base_str = HELLO_WORLD ansi_str = ansi.UNDERLINE_ENABLE + base_str + ansi.UNDERLINE_DISABLE @@ -59,9 +65,12 @@ def test_style_multi(): base_str = HELLO_WORLD fg_color = 'blue' bg_color = 'green' - ansi_str = ansi.FG_COLORS[fg_color] + ansi.BG_COLORS[bg_color] + ansi.BRIGHT + ansi.UNDERLINE_ENABLE + \ - base_str + ansi.FG_RESET + ansi.BG_RESET + ansi.NORMAL + ansi.UNDERLINE_DISABLE - assert ansi.style(base_str, fg=fg_color, bg=bg_color, bold=True, underline=True) == ansi_str + ansi_str = (ansi.FG_COLORS[fg_color] + ansi.BG_COLORS[bg_color] + + ansi.INTENSITY_BRIGHT + ansi.INTENSITY_DIM + ansi.UNDERLINE_ENABLE + + base_str + + ansi.FG_RESET + ansi.BG_RESET + + ansi.INTENSITY_NORMAL + ansi.INTENSITY_NORMAL + ansi.UNDERLINE_DISABLE) + assert ansi.style(base_str, fg=fg_color, bg=bg_color, bold=True, dim=True, underline=True) == ansi_str def test_style_color_not_exist(): |