From b371fbd448f67739848e6b6dac246ea390dd21f7 Mon Sep 17 00:00:00 2001 From: Darsey Litzenberger Date: Thu, 18 Apr 2024 20:12:51 -0600 Subject: [PATCH] Improve legibility on light-background terminals This fixes the problem of light-gray text being rendered on a light background. Users can now choose a different Pygments style/theme using the PY_DEVTOOLS_STYLE environment variable. If PY_DEVTOOLS_STYLE is not set, we attempt auto-detection using the COLORFGBG environment variable, as is commonly done by some tools on Linux and macOS. - Dark-background terminals use the "vim" style, as before. - Light-background terminals now use the "sas" style. - If auto-detection fails, we use the "default" style, which is legible on most terminals. A list of available styles can be obtained by running: import pygments.styles list(pygments.styles.get_all_styles()) --- devtools/prettier.py | 6 ++++-- devtools/utils.py | 21 +++++++++++++++++++++ docs/plugins.py | 2 +- tests/conftest.py | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/devtools/prettier.py b/devtools/prettier.py index c45bc6a..d7b3781 100644 --- a/devtools/prettier.py +++ b/devtools/prettier.py @@ -4,7 +4,7 @@ from collections import OrderedDict from collections.abc import Generator -from .utils import DataClassType, LaxMapping, SQLAlchemyClassType, env_true, isatty +from .utils import DataClassType, LaxMapping, SQLAlchemyClassType, bg_dark_or_light, env_true, isatty try: from functools import cache @@ -32,6 +32,8 @@ MISSING = object() PRETTY_KEY = '__prettier_formatted_value__' +PYGMENTS_STYLE = os.getenv('PY_DEVTOOLS_STYLE', {'dark': 'vim', 'light': 'sas', None: 'default'}[bg_dark_or_light()]) + def fmt(v: 'Any') -> 'Any': return {PRETTY_KEY: v} @@ -50,7 +52,7 @@ def get_pygments() -> 'Tuple[Any, Any, Any]': except ImportError: # pragma: no cover return None, None, None else: - return pygments, PythonLexer(), Terminal256Formatter(style='vim') + return pygments, PythonLexer(), Terminal256Formatter(style=PYGMENTS_STYLE) # common generator types (this is not exhaustive: things like chain are not include to avoid the import) diff --git a/devtools/utils.py b/devtools/utils.py index 2a96765..e75826c 100644 --- a/devtools/utils.py +++ b/devtools/utils.py @@ -3,6 +3,7 @@ __all__ = ( 'isatty', + 'bg_dark_or_light', 'env_true', 'env_bool', 'use_highlight', @@ -111,6 +112,26 @@ def use_highlight(highlight: 'Optional[bool]' = None, file_: 'Any' = None) -> bo return isatty(file_) +def bg_dark_or_light() -> str | None: + """ + Returns: + 'dark' if the terminal background is dark, + 'light' if the terminal background is light, or + None if the terminal background color is unknown. + """ + colorfgbg = os.environ.get('COLORFGBG', '') + try: + _, bg_str = colorfgbg.split(';') + bg = int(bg_str) + except ValueError: + return None + if 0 <= bg <= 6 or bg == 8: + return 'dark' + elif bg == 7 or 9 <= bg <= 15: + return 'light' + return None + + def is_literal(s: 'Any') -> bool: import ast diff --git a/docs/plugins.py b/docs/plugins.py index 5f40bf1..e88bbc5 100755 --- a/docs/plugins.py +++ b/docs/plugins.py @@ -51,7 +51,7 @@ def gen_example_html(markdown: str): def gen_examples_html(m: re.Match) -> str: sys.path.append(str(THIS_DIR.resolve())) - os.environ.update(PY_DEVTOOLS_HIGHLIGHT='true', PY_DEVTOOLS_WIDTH='80') + os.environ.update(PY_DEVTOOLS_HIGHLIGHT='true', PY_DEVTOOLS_STYLE='vim', PY_DEVTOOLS_WIDTH='80') conv = Ansi2HTMLConverter() name = THIS_DIR / Path(m.group(1)) diff --git a/tests/conftest.py b/tests/conftest.py index 2a62df2..544ebd4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,3 +5,4 @@ def pytest_sessionstart(session): os.environ.pop('PY_DEVTOOLS_HIGHLIGHT', None) + os.environ['PY_DEVTOOLS_STYLE'] = 'vim'