diff --git a/qtconsole/ansi_code_processor.py b/qtconsole/ansi_code_processor.py index 8ebe5c92..063c9067 100644 --- a/qtconsole/ansi_code_processor.py +++ b/qtconsole/ansi_code_processor.py @@ -292,6 +292,31 @@ def _replace_special(self, match): self.actions.append(ScrollAction('scroll', 'down', 'page', 1)) return '' + def _parse_ansi_color(self, color, intensity): + """ + Map an ANSI color code to color name or a RGB tuple. + Based on: https://gist.github.com/MightyPork/1d9bd3a3fd4eb1a661011560f6921b5b + """ + parsed_color = None + if color < 16: + # Adjust for intensity, if possible. + if intensity > 0 and color < 8: + color += 8 + parsed_color = self.color_map.get(color, None) + elif (color > 231): + s = int((color - 232) * 10 + 8) + parsed_color = (s, s, s) + else: + n = color - 16 + b = n % 6 + g = (n - b) / 6 % 6 + r = (n - b - g * 6) / 36 % 6 + r = int(r * 40 + 55) if r else 0 + g = int(g * 40 + 55) if g else 0 + b = int(b * 40 + 55) if b else 0 + parsed_color = (r, g, b) + return parsed_color + class QtAnsiCodeProcessor(AnsiCodeProcessor): """ Translates ANSI escape codes into QTextCharFormats. @@ -323,12 +348,8 @@ def get_color(self, color, intensity=0): """ Returns a QColor for a given color code or rgb list, or None if one cannot be constructed. """ - if isinstance(color, int): - # Adjust for intensity, if possible. - if color < 8 and intensity > 0: - color += 8 - constructor = self.color_map.get(color, None) + constructor = self._parse_ansi_color(color, intensity) elif isinstance(color, (tuple, list)): constructor = color else: diff --git a/qtconsole/mainwindow.py b/qtconsole/mainwindow.py index b5b0476a..4d5c86b6 100644 --- a/qtconsole/mainwindow.py +++ b/qtconsole/mainwindow.py @@ -801,6 +801,7 @@ def set_syntax_style(self, syntax_style): colors='nocolor' elif styles.dark_style(syntax_style): colors='linux' + else: colors='lightbg' self.active_frontend.syntax_style = syntax_style @@ -809,7 +810,18 @@ def set_syntax_style(self, syntax_style): self.active_frontend._syntax_style_changed() self.active_frontend._style_sheet_changed() self.active_frontend.reset(clear=True) - self.active_frontend._execute("%colors linux", True) + self.active_frontend._execute( +f""" +from IPython.core.ultratb import VerboseTB +if getattr(VerboseTB, 'tb_highlight_style', None) is not None: + VerboseTB.tb_highlight_style = '{syntax_style}' +elif getattr(VerboseTB, '_tb_highlight_style', None) is not None: + VerboseTB._tb_highlight_style = '{syntax_style}' +else: + get_ipython().run_line_magic('colors', '{colors}') +""", + True) + def close_active_frontend(self): self.close_tab(self.active_frontend) diff --git a/qtconsole/tests/test_jupyter_widget.py b/qtconsole/tests/test_jupyter_widget.py index 43ab4a18..d1741ddd 100644 --- a/qtconsole/tests/test_jupyter_widget.py +++ b/qtconsole/tests/test_jupyter_widget.py @@ -36,9 +36,15 @@ def test_stylesheet_changed(self): # By default, the background is light. White text is rendered as black self.assertEqual(w._ansi_processor.get_color(15).name(), '#000000') + # Color code 40 + self.assertEqual(w._ansi_processor.get_color(40).name(), '#00d700') + # Change to a dark colorscheme. White text is rendered as white w.syntax_style = 'monokai' self.assertEqual(w._ansi_processor.get_color(15).name(), '#ffffff') + + # Color code 40 with monokai + self.assertEqual(w._ansi_processor.get_color(40).name(), '#00d700') @pytest.mark.skipif(not sys.platform.startswith('linux'), reason="Works only on Linux")