cli (base): better background detection:

- ANSI escape code detection is only used on terminals known to be compatible (currently
  xterm, konsole, and all VTE based ones)
- `COLORFGBG` environment variable is used as fallback
- if both methods fail, `dark` is used

This should avoid problems with incompatible terminals (e.g. on QTerminal, users had to
press `[ENTER]` each time).

fix 406
This commit is contained in:
Goffi 2021-11-06 17:08:50 +01:00
commit b1529c1ebf

View file

@ -119,33 +119,65 @@ class LiberviaCli:
return config.getConfig(self.sat_conf, section, name, default=default)
def guess_background(self):
if not sys.stdin.isatty() or not sys.stdout.isatty():
return 'dark'
stdin_fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(stdin_fd)
# cf. https://unix.stackexchange.com/a/245568 (thanks!)
try:
tty.setraw(sys.stdin.fileno())
# we request background color
sys.stdout.write("\033]11;?\a")
sys.stdout.flush()
expected = "\033]11;rgb:"
for c in expected:
ch = sys.stdin.read(1)
if ch != c:
# background id is not supported, we default to "dark"
# TODO: log something?
return 'dark'
red, green, blue = [int(c, 16)/65535 for c in sys.stdin.read(14).split('/')]
# '\a' is the last character
sys.stdin.read(1)
finally:
termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings)
# for VTE based terminals
vte_version = int(os.getenv("VTE_VERSION", 0))
except ValueError:
vte_version = 0
lum = utils.per_luminance(red, green, blue)
if lum <= 0.5:
return 'dark'
color_fg_bg = os.getenv("COLORFGBG")
if ((sys.stdin.isatty() and sys.stdout.isatty()
and (
# XTerm
os.getenv("TERM", "") in {"xterm"}
# Konsole
or os.getenv("KONSOLE_VERSION")
# All VTE based terminals
or vte_version >= 3502
))):
# ANSI escape sequence
stdin_fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(stdin_fd)
try:
tty.setraw(sys.stdin.fileno())
# we request background color
sys.stdout.write("\033]11;?\a")
sys.stdout.flush()
expected = "\033]11;rgb:"
for c in expected:
ch = sys.stdin.read(1)
if ch != c:
# background id is not supported, we default to "dark"
# TODO: log something?
return 'dark'
red, green, blue = [
int(c, 16)/65535 for c in sys.stdin.read(14).split('/')
]
# '\a' is the last character
sys.stdin.read(1)
finally:
termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings)
lum = utils.per_luminance(red, green, blue)
if lum <= 0.5:
return 'dark'
else:
return 'light'
elif color_fg_bg:
# no luck with ANSI escape sequence, we try COLORFGBG environment variable
try:
bg = int(color_fg_bg.split(";")[-1])
except ValueError:
return "dark"
if bg in list(range(7)) + [8]:
return "dark"
else:
return "light"
else:
return 'light'
# no autodetection method found
return "dark"
def set_color_theme(self):
background = self.get_config('background', default='auto')