comparison sat_frontends/jp/base.py @ 3704:c143e7f35074

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
author Goffi <goffi@goffi.org>
date Sat, 06 Nov 2021 17:08:50 +0100
parents 43542cf32e5a
children 691dbd78981c
comparison
equal deleted inserted replaced
3703:de133b180941 3704:c143e7f35074
117 def get_config(self, name, section=C.CONFIG_SECTION, default=None): 117 def get_config(self, name, section=C.CONFIG_SECTION, default=None):
118 """Retrieve a setting value from sat.conf""" 118 """Retrieve a setting value from sat.conf"""
119 return config.getConfig(self.sat_conf, section, name, default=default) 119 return config.getConfig(self.sat_conf, section, name, default=default)
120 120
121 def guess_background(self): 121 def guess_background(self):
122 if not sys.stdin.isatty() or not sys.stdout.isatty(): 122 # cf. https://unix.stackexchange.com/a/245568 (thanks!)
123 return 'dark' 123 try:
124 stdin_fd = sys.stdin.fileno() 124 # for VTE based terminals
125 old_settings = termios.tcgetattr(stdin_fd) 125 vte_version = int(os.getenv("VTE_VERSION", 0))
126 try: 126 except ValueError:
127 tty.setraw(sys.stdin.fileno()) 127 vte_version = 0
128 # we request background color 128
129 sys.stdout.write("\033]11;?\a") 129 color_fg_bg = os.getenv("COLORFGBG")
130 sys.stdout.flush() 130
131 expected = "\033]11;rgb:" 131 if ((sys.stdin.isatty() and sys.stdout.isatty()
132 for c in expected: 132 and (
133 ch = sys.stdin.read(1) 133 # XTerm
134 if ch != c: 134 os.getenv("TERM", "") in {"xterm"}
135 # background id is not supported, we default to "dark" 135 # Konsole
136 # TODO: log something? 136 or os.getenv("KONSOLE_VERSION")
137 return 'dark' 137 # All VTE based terminals
138 red, green, blue = [int(c, 16)/65535 for c in sys.stdin.read(14).split('/')] 138 or vte_version >= 3502
139 # '\a' is the last character 139 ))):
140 sys.stdin.read(1) 140 # ANSI escape sequence
141 finally: 141 stdin_fd = sys.stdin.fileno()
142 termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings) 142 old_settings = termios.tcgetattr(stdin_fd)
143 143 try:
144 lum = utils.per_luminance(red, green, blue) 144 tty.setraw(sys.stdin.fileno())
145 if lum <= 0.5: 145 # we request background color
146 return 'dark' 146 sys.stdout.write("\033]11;?\a")
147 else: 147 sys.stdout.flush()
148 return 'light' 148 expected = "\033]11;rgb:"
149 for c in expected:
150 ch = sys.stdin.read(1)
151 if ch != c:
152 # background id is not supported, we default to "dark"
153 # TODO: log something?
154 return 'dark'
155 red, green, blue = [
156 int(c, 16)/65535 for c in sys.stdin.read(14).split('/')
157 ]
158 # '\a' is the last character
159 sys.stdin.read(1)
160 finally:
161 termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_settings)
162
163 lum = utils.per_luminance(red, green, blue)
164 if lum <= 0.5:
165 return 'dark'
166 else:
167 return 'light'
168 elif color_fg_bg:
169 # no luck with ANSI escape sequence, we try COLORFGBG environment variable
170 try:
171 bg = int(color_fg_bg.split(";")[-1])
172 except ValueError:
173 return "dark"
174 if bg in list(range(7)) + [8]:
175 return "dark"
176 else:
177 return "light"
178 else:
179 # no autodetection method found
180 return "dark"
149 181
150 def set_color_theme(self): 182 def set_color_theme(self):
151 background = self.get_config('background', default='auto') 183 background = self.get_config('background', default='auto')
152 if background == 'auto': 184 if background == 'auto':
153 background = self.guess_background() 185 background = self.guess_background()