Skip to content

Commit

Permalink
Improve legibility on light-background terminals
Browse files Browse the repository at this point in the history
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())
  • Loading branch information
dlitz committed Apr 19, 2024
1 parent 2aea99d commit b371fbd
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 3 deletions.
6 changes: 4 additions & 2 deletions devtools/prettier.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand All @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions devtools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

__all__ = (
'isatty',
'bg_dark_or_light',
'env_true',
'env_bool',
'use_highlight',
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion docs/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
1 change: 1 addition & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@

def pytest_sessionstart(session):
os.environ.pop('PY_DEVTOOLS_HIGHLIGHT', None)
os.environ['PY_DEVTOOLS_STYLE'] = 'vim'

0 comments on commit b371fbd

Please sign in to comment.